Thread
프로세스 내에서 실행되는 흐름의 단위
Event loop
Dart는 Single Thread로 운영됨 → Event loop를 통해 복잡한 작업들을 효율적으로 처리
Flutter 앱을 실행시키는 순간 isolate라고 불리는 새로운 thread process가 하나 생성됨
이 thread가 앱 전체를 총괄하는 단일 thread가 됨
thread가 생성되는 순간 dart는 자동적으로 3가지 작업을 하게됨
- 내부적으로 First In First Out(FIFO)방식으로 MicroTask 와 Event 준비 MicroTask : event queue로 넘어가기 전에 아주 짧은 시간 동안 비동기적으로 먼저 실행되고 끝나는 작은 작업
- 앱의 시작점인 main 함수 실행
- Event loop 실행
Dart는 하나의 단일 thread가 실행되는 순간 내부적으로 event loop process를 통해 순서대로 대기열에 있는 micro task와 event를 처리
더 이상 내부적으로 진행할 micro task가 없다면 event loop는 외적으로 전달되는 각종 이벤트 (gesture, drawing, reading files, fetching data, button tap, future, stream 등)를 순서대로 처리하게 됨
각종 외적인 이벤트들이 이벤트 큐에 등록되고 이벤트 루프를 통해 처리
Future
비동기 방식으로 미래의 어느시점에 완성되어서 실제적인 데이터가 되거나 에러를 반환하는 객체
코드상에서 새로운 future를 객체화 시키면
- 다트에 의해서 future 객체가 내부적인 배열에 등록
- Future 관련해서 실행되어야하는 코드들이 이벤트 큐(대기열)에 등록
- 불완전한 future 객체가 반환
- Synchronous 방식으로 실행되어야 할 코드 먼저 실행
- 최종적으로 실제적인 data 값이 future 객체로 전달
Async method
async 키워드를 사용한 순간
- 메서드를 통해서 나오는 결과물들은 future라는 것을 알게 됨
- await 키워드를 만날때까지 synchronous 방식으로 코드 처리
- await 키워드를 만나면 future가 완료될 때까지 대기
- future가 완료 되자마자 그 다음 코드들을 실행
전체 앱의 실행이 중지되지 않고 future 부분은 건너띄고 그 아래에 있는 코드들을 synchronous하게 처리
예시
String createOrderMessage(){
var order = fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder(){
return Future.delayed(
Duration(second: 2), ()=>'Large Latte',
);
}
void main(){
print('Fetching user order...');
print(createOrderMessage());
}
실행시 에러 → main()의 두번째 print에서 createOrderMessage()는 미완성의 객체를 반환하고 있기 때문
fetchUserOrder()에서 2초를 기다리고 fetchUserOrder()가 반환해야 하는데 기다리지 않고 즉시 반환하기 때문 → 이를 해결하기 위해 async 키워드 사용
createOrderMessage() 수정
- 비동기 방식으로 실행된 결과의 String 값을 리턴해줘야하므로 타입 변경 String → Future
- order 변수에 fetchUserOrder 함수의 리턴값을 할당해줄려면 즉시할당하는 synchronous 방식이 아니라 기다렸다가 값이 전달되는 비동기 방식어야함 createOrderMessage()가 비동기 방식으로 처리되어야함을 dart에게 알려줘야함 → async 키워드 추가
- fetchUserOrder()의 실행이 끝날때까지 기다렸다가 order 변수에 값을 할당해줘야함 → await 추가
// 1
Future<String> createOrderMessage() async{ // 2
// 3
var order = await fetchUserOrder();
return 'Your order is: $order';
}
main() 수정
- main()에서 호출되는 createOrderMessage()가 비동기 방식으로 처리되는 함수이므로 main()도 비동기 방식으로 처리됨을 알려줘야함 → async 추가
- createOrderMessage()의 리턴값이 출려되려면 order변수의 값이 할당될 때까지 기다려야함 → await 추가
// 1
void main() async{
print('Fetching user order...');
// 2
print(await createOrderMessage());
}
정리
async 키워드는 future 자체를 대신하는 것이 아니라 비동기 방식으로 실행되는 함수라는 것을 dart에게 알려주는 기능을 하는 것이며 await 키워드와 함께 미래의 어느 시점에 전달될 값을 기다리는 것
future는 하나의 객체로서 객체가 생성되는 순간에는 미완성으로 존재하다가 미래의 어느 시점에 데이터를 전달받은 온전한 객체가 되거나 데이터에 문제가 생긴다면 에러를 반환
심화 예제
void main() async {
methodA(); // 1
await methodB(); // 3
await methodC('main'); // 9
methodD(); // 12
}
methodA(){
print('A'); // 2
}
methodB() async {
print('B start'); // 4
await methodC('B'); // 5
print('B end'); // 8
}
methodC(String from) async {
print('C start from $from'); // 6 'b' // 10 'main'
Future((){
print('C running Future from $from'); // 14 'b' // 16 'main'
}).then((_){
print('C end of Future from $from'); // 15 'b' // 17 'main'
});
print('C end from $from'); // 7 'b' // 11 'main'
}
methodD(){
print('D'); // 13
}
//////
A
B start
C start from B
C end from B
B end
C start from main
C end from main
D
C running Future from B
C end of Future from B
C running Future from main
c runngin Future from main
///
참고
https://www.youtube.com/watch?v=HjhPhAUPHos&list=PLQt_pzi-LLfoOpp3b-pnnLXgYpiFEftLB&index=12
'Study > Dart' 카테고리의 다른 글
[Dart] factory 패턴 (0) | 2021.06.24 |
---|---|
[Dart] const 와 final 이해하기 (0) | 2021.06.15 |
[Dart] Future, Isolate (0) | 2021.06.08 |
[Dart] 상속을 쓰는 이유 (0) | 2021.06.07 |
[Dart] 상속 (0) | 2021.06.07 |