[Flutter] 이벤트 루프(Event Loop)와 Isolate

osung·2023년 5월 31일
4
post-thumbnail

Dart는 JavaScript와 같이 싱글스레드 언어이다(애초에 js잡겠다고 나온 언어이니..)
이러한 싱글 스레드 언어의 경우 이벤트 루프의 개념을 알고 넘어가는 게 중요하기에 간단히 정리해 보았다.

이벤트 루프(Event Loop)란?

이벤트 루프는 이벤트나 작업을 관리하고 하나의 작업이 완료되면 다음 작업을 실행하는 역할을 하는 프로그래밍 구조이다. 이벤트 루프는 큐(queue)를 사용하여 이벤트나 작업을 관리하며 그 중 하나를 선택하여 실행한다.

Dart에서 이벤트 루프는 두 가지 주요 큐를 관리하는데 그것이 마이크로태스크 큐(Microtask Queue)이벤트 큐(Event Queue)이다.

1. 마이크로태스크 큐(Microtask Queue)
마이크로태스크 큐에 들어있는 작업들은 현재 실행 중인 코드가 끝나자마자 실행된다. 마이크로태스크는 우선 순위가 높아서 마이크로태스크 큐가 비워질 때까지 이벤트 루프는 이벤트 큐의 작업을 실행하지 않는다. 마이크로태스크 큐는 비동기 작업의 완료를 알리거나 비동기 작업이 완료된 후에 수행할 추가 작업을 관리하는 데 주로 사용된다.

//microtask 예시
await fetchPost().then((_) => print("microtask 작업"));

2. 이벤트 큐(Event Queue)
이벤트 큐는 마이크로태스크 큐가 비어 있을 때에만 이벤트 루프에 의해 처리된다. 이벤트 큐에는 I/O, 타이머, 제스처, 키보드 이벤트, 그래픽 렌더링 등의 이벤트가 포함된다.

이런 방식으로 이벤트 루프는 동기적으로 실행되는 코드와 비동기적으로 실행되는 코드 사이에 조율을 하게 된다.

Isolate로 멀티스레드 흉내내기

Dart에서는 Isolate를 추가 생성해 별도의 스레드에서 코드를 실행할 수 있다. 각각의 Isolate는 독립적인 메모리 공간과 하나의 Event Loop를 가지며 서로간에 메모리를 공유하지 않는다. 이로 인해 병렬 처리가 가능하게 되고 다중 CPU 코어를 활용할 수 있게 된다. 다음 코드를 살펴보자

import 'dart:isolate';

void main() async {
  var mainIsolateReceivePort = ReceivePort(); // 메시지를 받기 위한 포트를 생성
  Isolate.spawn(echoIsolate, mainIsolateReceivePort.sendPort); // 새 Isolate를 생성

  // 새 Isolate로부터 SendPort를 받아옴
  var echoIsolateSendPort = await mainIsolateReceivePort.first;

  // 메시지 응답을 받을 ReceivePort
  var response = ReceivePort();

  // 새 Isolate에 메시지를 보냄
  echoIsolateSendPort.send(['Hello', response.sendPort]);

  // 새 Isolate로부터 응답을 받음
  print(await response.first);
}

// 새 Isolate에서 실행되는 함수
void echoIsolate(SendPort mainIsolateSendPort) {
  var receivePort = ReceivePort();

  // Main Isolate에게 이 Isolate의 SendPort를 보냄
  mainIsolateSendPort.send(receivePort.sendPort);

  // 메시지를 받고 처리
  receivePort.listen((message) {
    var data = message[0];
    SendPort replyTo = message[1];
    replyTo.send('Echo from isolate: $data'); // 받은 메시지를 다시 보냄
  });
}

멀티스레드 지원하네 그럼 멀티스레드 언어 아니야?

이렇게 Isolate를 활용하면 Dart에서도 병렬 처리가 가능하지만 그렇다고해서 이 방법이 Dart를 멀티 스레드 언어로 만들지는 않는다. 각 Isolate는 메모리를 공유하지 않고 서로간의 통신은 sendPortreceivePort를 이용한 메시지 패싱을 통해 이루어지게 되는데 이런 통신 방식은 전통적인 멀티 스레드 프로그래밍에서의 메모리 공유와는 다르게 동작하기 때문이다 요약하면 싱글 스레드 끼리의 통신일 뿐이란 얘기다

결국 Dart는 Isolate 통해 병렬 처리를 지원하긴 하지만, 기본적으로는 싱글 스레드 언어라는 점에는 변함이 없다

Isolate를 프로젝트에 도입하고 싶다면 사용후 제대로 닫아주는 것(Kill)이 앱 건강에 좋다.

참고 사이트
https://web.archive.org/web/20170704074724/https://webdev.dartlang.org/articles/performance/event-loop
https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a

profile
킹왕짱 개발자가 될테야

2개의 댓글

comment-user-thumbnail
2023년 6월 12일

사용후 제대로 닫아주는 것(Kill)이 앱 건강에 좋다. >> 안 닫고 그대로 두면 영원히 살아있나요??

1개의 답글