오늘 배울 것
오늘은 Flutter 프로그래밍에서 중요한 개념인 동기와 비동기에 대해 공부하고 Future, async/await의 개념과 사용법을 알아보겠습니다.
동기(Synchronous) vs 비동기(Asynchronous)
쉽게 비유적으로 설명해 보자면 동기는 줄 서서 일을 처리하는 것이고, 비동기는 맡겨두고 다른 일 먼저 하고 오는 것입니다.
동기와 비동기를 표로 정리하면 다음과 같습니다.
동기 | 비동기 |
한 번에 하나씩 처리 | 동시에 여러 일 가능 |
앞 작업이 끝나야 다음 일로 넘어감 | 기다리는 동안 다른 일 가능 |
예: ATM에서 돈 뽑기 | 예: 배달 주문하고 다른 일 하기 |
동기의 장점은 흐름이 예측 가능하다는 것입니다. 코드가 작성된 순서대로 차례차례 실행되기 때문에 디버깅이나 버그를 찾기도 쉽습니다.
동기의 단점은 오래 걸리는 작업, 특히 언제 응답이 올지 알 수 없는 외부 요청이 있으면 응답이 올 때까지 기다리기 때문에 성능이 저하되고 앱이 멈춘 것처럼 보일 수 있습니다.
비동기의 장점은 네트워크 요청이나 파일 읽기 같은 느린 작업도 다중으로 처리가 가능하여 전반적인 앱의 성능을 높일 수 있습니다.
비동기의 단점은 코드 흐름이 직관적이지 않아 헷갈릴 수 있고 작업의 실행 순서가 보장되지 않기에 파악하기 어려운 문제들이 발생할 수 있습니다.
이러한 장담점을 고려하여 간단한 작업이나 값이 보장되어야 하는 경우에는 동기로 처리하고, 외부 요청처럼 얼마나 걸릴지 알 수 없는 작업에는 비동기로 처리하는 것이 좋습니다.
비동기 Future, async/await 개념 설명
비동기를 수행하는 Future, async/await 을 비유적으로 설명하면 다음과 같습니다.
Future 는 나중에 결과를 반환하는 약속입니다. 예를 들어, 카페에서 '아메리카노 한 잔을 주문'하면 카페 점원이 '곧 드릴게요' 하며 커피를 만들어주는 걸 약속하는 것입니다. 약속한 커피를 기다리는 동안 다른 작업을 할 수 있죠.
async/await 은 약속을 기다렸다가 코드를 순차적으로 실행하도록 도와줍니다. 커피를 주문한 뒤에 자리로 가서 다른 일을 하는 게 아니라, 그 자리에 서서 '커피가 나올 때까지 기다리는 것'입니다.
async 는 비동기 함수를 정의할 때 사용하고 await 은 비동기 함수를 실행할 때 사용합니다. 즉, await를 붙이면 Future가 끝날 때까지 기다렸다가 그 결과 값을 받아와서 다음 작업으로 넘어가는 순차적인 흐름을 만들어줍니다.
await 사용 실습
위에서 설명한 Future, async/await 가 실제 코드에서는 어떻게 사용되고 어떤 결과가 나오는지 실습 코드를 통해 살펴보겠습니다.
다음은 Future.delayed 를 이용하여 await 을 '사용하지 않을 때'와 '사용할 때'를 비교하는 코드입니다. (Future, async/await 코드를 어떻게 작성하는지 유의 깊게 봐주세요)
// Future 사용 (await 없이)
Future<void> getDataWithoutAwait() async {
print('1. Future 함수 시작!');
setState(() {
resultText = '요청 보냄 (Future)';
isLoading = true;
});
print('2. Future: setState 완료 (로딩 시작)');
Future.delayed(const Duration(seconds: 2), () {
print('4. Future: 2초 지남! 이제 데이터가 도착했어요');
setState(() {
resultText = '데이터 도착! (Future)';
isLoading = false;
});
print('5. Future: setState 완료 (로딩 종료)');
});
print('3. Future: 함수 종료 (하지만 데이터는 아직 오는 중...)');
}
// await 사용
Future<void> getDataWithAwait() async {
print('1. await 함수 시작!');
setState(() {
resultText = '요청 보냄 (await)';
isLoading = true;
});
print('2. await: setState 완료 (로딩 시작)');
await Future.delayed(const Duration(seconds: 2), () {
print('4. await: 2초 지남! 이제 데이터가 도착했어요');
setState(() {
resultText = '데이터 도착! (await)';
isLoading = false;
});
print('5. await: setState 완료 (로딩 종료)');
});
print('6. await: 함수 종료 (모든 처리가 완료됨)');
}
위 두 개의 함수를 각각 호출하면 다음과 같은 print 출력을 얻을 수 있습니다.
flutter: 1. Future 함수 시작!
flutter: 2. Future: setState 완료 (로딩 시작)
flutter: 3. Future: 함수 종료 (하지만 데이터는 아직 오는 중...)
flutter: 4. Future: 2초 지남! 이제 데이터가 도착했어요
flutter: 5. Future: setState 완료 (로딩 종료)
flutter: 1. await 함수 시작!
flutter: 2. await: setState 완료 (로딩 시작)
flutter: 4. await: 2초 지남! 이제 데이터가 도착했어요
flutter: 5. await: setState 완료 (로딩 종료)
flutter: 6. await: 함수 종료 (모든 처리가 완료됨)
await 을 사용하지 않은 일반적인 Future 함수의 경우 로딩을 시작하자마자 함수가 종료되고 2초 후에 데이터가 도착해 로딩이 종료됩니다. 즉, 데이터가 오는 동안 이미 다음 로직을 실행하고 있는 거죠.
반대로 await 을 사용한 경우에는 2초가 지나 데이터가 도착할 때까지 기다립니다. 로딩이 종료되고 나서야 함수가 최종 종료됩니다. 실행 흐름을 동기적으로 바꿔주는 거죠.
여기서 우리가 알 수 있는 것은 await 가 없으면 데이터가 도착하기 전에 다음 코드가 실행되므로 어떤 상황이 발생할지 파악하기가 어렵다는 것입니다.
만약 다음 코드가 직전 요청에 대한 응답 값을 필요로 한다면 응답이 오기 전에 다음 코드가 실행 되므로 문제가 발생할 수 있는 거죠. 그러니 다음 코드에서 응답 값이 필요한 경우라면 꼭 await 을 사용해야 합니다.
await 을 쓰면 비동기가 아닌 걸까?
await 을 쓴다고 해서 '비동기가 아닌 것'은 아닙니다. 오히려 비동기(여기서는 Future)를 더 안전하고 깔끔하게 제어하기 위해 await을 사용합니다.
await 가 걸려 있는 동안은 해당 함수의 '나머지 로직'은 일시 정지가 됩니다.
하지만 이때 Flutter는 다른 작업 예를 들어 UI 렌더링이나 다른 이벤트 처리 등은 계속 수행할 수 있습니다. 아직 데이터가 도착하지 않아도 미리 화면을 그리는 등의 작업을 수행하는 거죠.
만약 비동기 코드가 아닌 동기 코드가 응답을 기다리기 위해 멈춘다면 앱의 모든 작업이 일시 정지 됩니다. 이때 화면도 멈추기에 사용자 입장에서는 앱이 멈춘 것처럼 보이죠.
그렇기 때문에 Flutter에서는 I/O 작업이나 외부 요청처럼 시간이 오래 걸리는 작업은 비동기로 처리하는 것을 권장합니다.
Recap
- 동기 는 순차적으로 실행하지만 응답을 기다릴 동안 앱이 멈춤
- 비동기 는 빠르고 효율적이지만 흐름 파악이 어려울 수 있음
- Future 는 나중에 값이 올 거라는 약속 객체
- async 는 비동기 함수를 선언할 때 사용
- await 는 응답을 받고 나서 다음 코드 실행
- await 이 있어도 앱 전체가 멈추는 것은 아님
- await 을 사용하지 않으면 다음 코드가 먼저 실행될 수 있음
'Flutter 독학으로 기본기 익히기' 카테고리의 다른 글
08. 실시간 데이터를 UI에 반영하는 StreamBuilder 알아보기 (0) | 2025.05.09 |
---|---|
07. 비동기 상태에 따라 UI를 바꾸는 FutureBuilder 알아보기 (0) | 2025.05.08 |
05. Flutter Navigator로 화면 이동하는 방법 (0) | 2025.05.06 |
04. Flutter 에서 자주 사용하는 레이아웃 위젯 (0) | 2025.05.03 |
03. 위젯 트리 구조, DevTools 로 Widget Tree 보는 방법 (0) | 2025.05.02 |