이 포스트는 DSC HUFS에서 진행하는 Flutter 스터디를 바탕으로 정리한 내용입니다.
Dart는 싱글 쓰레드 기반의 언어입니다. 하지만 Dart로 만들어진 Flutter에서는 비동기를 다룹니다. 어떻게 플러터가 싱글 쓰레드로 비동기 처리를 하는지 알아봤더니 event loop를 쓴다고 합니다. 놀랍지 않은게 Android, iOS에서도 이런 loop(aka. main loop)를 사용한다고 합니다. Javascript에서도 event loop를 사용합니다. 다음은 event loop를 Flutter 팀에서 설명한 영상합니다.
Event loop를 이해하기 전에 isolate의 개념의 설명이 필요할 것 같아서 isolate 설명을 먼저 정리했습니다.
쓰레드는 자신만의 isolate와 메모리를 갖습니다. 각 isolate는 자신만의 메모리와 event loop를 할당 받습니다. isolate는 새로운 ioslate을 만들 수 있고, 새로운 isolate는 새로운 메모리와 새로운 event loop를 할당받습니다. 여기서 새로운 isolate는 부모 isolate의 메모리에 접근할 수 없습니다. 이렇게 isolate는 서로 격리(isolated)되어있다는 특징을 갖습니다. 따라서 서로 메모리를 공유하지 않고, 메모리 Locking이 필요없다는 장점이 있습니다. 격리된 각 isolate 간의 통신을 하려고 하면 메시지를 주고 받아야합니다.
“An event loop is a background infinite loop which periodically wakes up and looks in the event queue for any tasks that need to run. If any exist, the event loops puts them onto the run stack if and only if the CPU is idle.”
출처: https://medium.com/flutter-community/futures-async-await-threading-in-flutter-baeeab1c1fe3
이벤트 루프는 이벤트 큐에 들어있는 태스크들을 차례로 실행하는 루프입니다. 여기서 말하는 태스크는 I/O나 사용자가 dart에서 작성하는 코드로 인해 발생하는 모든 이벤트들입니다.
CPU와 비교해서 한참 느린 작업들이 있습니다. 예를 들면 File을 읽고 쓰거나, http 통신으로 데이터를 가져오거나 보내는 등이 있습니다. 이런 작업들을 기다리는 것은 시간 낭비입니다.
그래서 Dart에서는 아래와 같은 순서로 작업합니다
여러분들이 해야하는 것은 Future 인스턴스를 만들고 그 Future를 다룰 코드를 작성하는 것입니다.
Future에서 결과값을 가져오는 방법은 두가지 입니다.
첫 번째는 then을 사용하는 것이고,
두 번째는 async, await 을 사용하는 것입니다.
아래는 future 인스턴스에 할당된 작업이 끝났을 때 handleValue(value) 함수가 실행되는 것을 나타냅니다. future 인스턴스는 Future<int> 인스턴스이기 때문에 then 이후에 나타나는 value 는 int 형이 됩니다.
Future<int> future = getFuture();
future.then((value) => handleValue(value))
.catchError((error) => handleError(error));
await 을 사용하면 await 을 사용한 곳에서 future 작업이 끝날 때까지 기다립니다. 다음은 await을 사용하는 예시입니다.
var order = await fetchUserOrder();
하지만 await을 사용할 경우 다른 작업을 전부 멈추고, future 작업을 기다리기 때문에 앱의 성능에 악영향을 끼치게 됩니다. 이 때 async 를 사용합니다. 즉, 내부에서 await을 사용하는 함수는 async 함수가 되어야합니다.
함수가 비동기라는 것을 나타내기 위해 async를 사용해줍니다. 그리고 async 함수는 항상 Future<String> 인스턴스를 반환합니다.
Future<String> createOrderMessage() async {
var order = await fetchUserOrder();
return 'Your order is: $order';
}
더 자세한 설명은 아래의 dart 공식 문서에서 볼 수 있습니다. 감사합니다.
https://dart.dev/codelabs/async-await