본문 바로가기
Flutter

Flutter에서 비동기 프로그래밍 이해하기: Future와 async/await

by 김무스비 2024. 10. 12.
728x90
반응형

오늘은 다른 프로그래밍 언어/프레임워크에서도 자주 나오는 개념인 비동기 프로그래밍을 Flutter의 관점에서 한 번 살펴보려고 합니다. 특히, 이 글에서는 Flutter에서 비동기 프로그래밍을 이해하는 데 필요한 핵심 개념인 Future async/await 을 중심으로 알아보겠습니다.

future에 대한 이미지


1. 비동기 프로그래밍이란 무엇인가?

비동기 프로그래밍이란 작업이 완료되기를 기다리지 않고 다른 작업을 계속할 수 있는 프로그래밍 방식입니다.

Flutter는 기본적으로 단일 스레드로 동작하기 때문에, 무거운 작업을 동기 방식으로 처리하면 UI가 멈추는 문제가 발생할 수 있습니다. 네트워크 요청이나 파일 읽기 같은 오래 걸리는 작업을 수행할 때가 대표적인 예시죠.

이 때, 비동기 프로그래밍을 사용하면 앱이 네트워크 요청, 파일 시스템 접근, 데이터베이스 쿼리 등을 처리하는 동안에도 사용자 인터페이스가 원활하게 동작하게 할 수 있습니다.

2. Future란 무엇인가?

Flutter에서 비동기 작업은 Future 객체로 표현됩니다. Future는 미래에 완료될 작업을 나타내며, 이 작업이 완료되면 성공 또는 실패 결과를 반환합니다. Future는 JavaScript의 Promise와 유사한 개념으로, 비동기 작업의 결과를 나중에 받기 위해 사용됩니다.

예를 들어, 서버에서 데이터를 가져오는 작업은 시간이 걸릴 수 있는데, 이 작업을 Future로 처리하여 결과가 반환될 때까지 기다릴 수 있습니다. Future는 다음과 같은 두 가지 상태를 가집니다:

  • 완료되지 않음 (Pending): 작업이 아직 완료되지 않은 상태.
  • 완료됨 (Completed): 작업이 완료되어 성공 또는 실패로 결과가 반환된 상태.
Future<String> fetchData() {
  return Future.delayed(Duration(seconds: 2), () {
    return '데이터 로드 완료';
  });
}

위 코드에서 fetchData 함수는 2초 후에 데이터를 반환하는 비동기 작업을 나타냅니다. Future는 데이터를 즉시 반환하지 않고, 2초 후에 완료될 것임을 나타냅니다.

3. async와 await의 역할

Future를 사용할 때 결과를 처리하는 두 가지 방법이 있습니다.

then() 메서드를 사용하는 방법과 async/await 키워드를 사용하는 방법입니다.

두 가지 방법 중, Flutter에서는 주로 async/await을 사용하여 비동기 작업을 처리하는 것이 가독성이 좋고, 코드가 더 직관적입니다.

3.1 async 키워드

async 키워드는 함수가 비동기 작업을 포함하고 있다는 것을 Flutter에 알리는 역할을 합니다. async로 선언된 함수는 무조건 Future를 반환하며, 해당 함수 내에서 비동기 작업을 처리할 수 있습니다.

Future<void> loadData() async {
  // 비동기 작업 수행
}

3.2 await 키워드

await 키워드는 Future가 완료될 때까지 기다렸다가, 그 결과를 받아올 수 있도록 도와줍니다.

await를 사용하면 Future가 완료될 때까지 다음 코드가 실행되지 않으며, Future의 결과를 변수에 저장할 수 있습니다.

Future<void> fetchData() async {
  String data = await loadData();
  print(data);
}

await는 비동기 작업의 결과를 기다리는 동안 다른 작업이 동기적으로 실행되지 않도록 보장합니다.

위 코드를 기준으로 설명드리면, loadData() 함수의 결과가 완료될 때까지 기다린 후, 그 값을 data 변수에 저장하고 출력하는 구조인 것입니다.

4. async/await 사용 예시

다음은 간단한 예시로, 서버에서 데이터를 가져오는 비동기 작업을 처리하는 방법입니다. fetchData 함수는 2초 후에 데이터를 반환하고, 해당 데이터를 출력하는 코드입니다.

Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return '서버에서 데이터를 가져왔습니다.';
}

void main() async {
  print('데이터 가져오는 중...');
  String data = await fetchData();
  print(data);
}

이 예시에서 await 키워드를 사용하여 fetchData() 함수가 완료될 때까지 기다렸다가, 완료된 결과를 data 변수에 저장한 후 출력하게 되고, 출력 결과는'데이터 가져오는 중...'과 '서버에서 데이터를 가져왔습니다.' 이 됩니다.

5. then() 메서드와 async/await 비교

Future의 결과를 처리할 때 async/await 외에도 then() 메서드를 사용할 수 있습니다. then()은 Future가 완료된 후 수행할 작업을 정의할 수 있는 메서드입니다.

fetchData().then((data) {
  print(data);
});

위 코드에서 fetchData()가 완료된 후, 그 결과가 data로 전달되어 출력됩니다. 하지만 then()을 사용하면 중첩된 콜백 함수가 많아져 코드가 복잡해질 수 있습니다. 반면, async/await을 사용하면 비동기 코드를 동기 코드처럼 작성할 수 있어 가독성이 훨씬 좋아집니다.

- then을 사용한 경우

fetchData().then((data) {
  print('데이터: $data');
}).catchError((error) {
  print('오류 발생: $error');
});

- async와 await을 사용한 경우

try {
  String data = await fetchData();
  print('데이터: $data');
} catch (error) {
  print('오류 발생: $error');
}

async/await 방식은 오류 처리도 try-catch 블록을 사용하여 더욱 직관적으로 작성할 수 있습니다. 따라서 코드의 복잡도를 낮추고 가독성을 높이는 데 유리합니다.

6. 비동기 프로그래밍을 사용할 떄 주의점

비동기 작업을 사용할 때 주의할 점은 메인 스레드를 차단하지 않도록 설계하는 것입니다. Flutter는 싱글 스레드로 동작하기 때문에, 모든 작업이 동기적으로 처리되면 UI가 멈추는 현상이 발생할 수 있습니다. 이를 방지하려면, 비동기 프로그래밍을 통해 작업을 백그라운드에서 처리하고, 그 결과를 UI에 반영하는 구조로 앱을 설계해야 합니다.

7. 결론

Flutter에서 비동기 프로그래밍은 앱 개발에 있어서 필수적인 기술입니다. Future, async/await는 비동기 작업을 처리하는 기본적인 도구이며, 이를 활용하여 네트워크 요청이나 파일 읽기 같은 시간이 오래 걸리는 작업을 처리할 수 있습니다. 또한 async/await 키워드를 사용하면 더 깔끔하고 직관적인 코드를 작성할 수 있으며, UI가 멈추지 않는 사용자 친화적인 앱을 개발할 수 있습니다.

비동기 프로그래밍을 잘 활용하면 복잡한 작업도 효율적으로 처리할 수 있고, 앱 성능을 극대화할 수 있습니다. Future와 async/await에 대한 개념을 확실히 이해하고 이를 프로젝트에 적절하게 적용해서 좋은 앱을 만드는 데 이 글이 도움이 되었으면 좋겠습니다.

728x90
반응형