Node.js Event loop에 대해서 - 1

June 14, 2019

Event Loop, Timer, process.nextTick() 에 대해서 - 1

해당 글은 https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ 를 번역한 글입니다.

이벤트루프는 javascript가 Single thread라는 것에도 불구하고 가능할때마다 시스템 커널의 작업을 오프로드하여 Non-Blocking I/O 작업을 수행할 수 있게 합니다.

대부분의 최신 커널은 Multi-thread이기 때문에 백그라운드에서 실행되는 여러 작업을 처리할 수 있습니다. 이러한 작업중 하나가 완료되면 커널이 Node.js에 알려주어 관련된 콜백함수가 풀 대기열에 추가되어 실행됩니다.

Node.js가 시작되면, 이벤트루프를 초기화하고 비동기 API 호출, Timer, 또는 process.nextTick() 호출을 할수 있는 입력 스크립트 (추가적으로 해당 문서에서 다루지 않은 REPL에 포함된)를 처리합니다. 그런다음 이벤트루프 처리를 시작합니다.

아래 다이어그램을 확인해 보겠습니다.

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

각 단계에는 실행할 콜백 FIFO(First In First Out) Queue가 존재합니다. 일반적으로 각 단계에서는 이벤트루프가 해당 주어진 단계에 들어가면 모든 작업을 수행한 다음 대기열이 모두 사용되거나 최대 콜백횟수가 될때까지 전체 대기열을 실행합니다.

대기열이 모두 사용되거나 콜백 제한에 도달하면 이벤트 루프가 다음 단계로 이동합니다. 작업중 더 많은 작업들을 예약할수 있으며, polling 하는 단계에서 처리된 새 이벤트가 커널에 의해서 콜백 Queue에 저장되므로, polling 이벤트가 처리되는 동안 해당 이벤트를 대기시킬 수 있습니다. 결과적으로 장시간 실행되는 콜백은 poll 단계가 타이머의 임계값보다 훨씬 길어질수 있게 할 수 있습니다.

  • timer: 이단계는 setTimeout()setInterval() 에 의해 스케쥴 된 콜백을 실행합니다.
  • pending callback: 다음 loop 반복에 지연된 I/O 콜백을 실행합니다.
  • idle, prepare: 내부적으로만 사용됩니다.
  • poll: 새로운 I/O 이벤트를 검색합니다. I/O 관련 callback (close callback, timer에 의해 스케쥴된 callback, setImmediate()) 를 지외하고 거의 모든 callback을 수행합니다. 해당 poll이 찬경우 node가 차단됩니다.
  • check: setImmediate() callback이 여기에서 호출됩니다.
  • close callbacks: 일부 콜백이 해당됩니다. (socke.on('close'))
...