/* 이벤트 루프 */
이벤트 루프는 시스템 커널에서 가능한 작업이 있다면 그 작업을 커널에서 수행한다.
자바스크립트는 단인 스레드 기반이지만 Node.js가 논블로킹 I/O 작업을 수행할 수 있도록 해주는 핵심 기능입니다.
각 단계에서는 해당 단계에서 실행되는 작업을 저장하는 큐가 존재한다.
/* 타이머 단계 */
이벤트 루프는 타이머 단계 (timer phase)에서 시작한다. 타이머 단계의 큐에는 setTimeout이나 setInterval 과 같은 함수를 통해 만들어진 타이머들을 큐에 넣고 실행한다. 타이머들은 min heap 으로 관리 된다. 힙을 구성할 때 기준으로 실행할 시각이 가장 적게 남은 타이머가 힙의 루트가 된다.
ex) 딜레이 값이 100, 200, 300, 400 인 4개의 타이머 (A, B, C, D)를 특정시간 t에 힙에 등록했다고 가정해보자. 이벤트 루프가 t+250 시각에 타이머 단계에 진입했다고 하면 힙에서 A, B, C, D 순으로 시간을 비교한다. A, B는 이미 250만큼의 시간이 지났기 때문에 두 콜백은 실행이 되지만, C는 아직 시간이 지나지 않았기 때문에 실행 되지 않는다. D는 이미 C를 실행하지 않기로 결정해서 비교할 필요가 없다.
타이머의 콜백이 무한정 실행되는 것은 아니고 실행 한도 (hard limit)에 도달하면 다음 단계로 넘어간다.
/* 대기 콜백 단계 */
대기 단계의 큐에 들어있는 콜백들은 현재 돌고 있는 루프 이전의 작업에서 큐에 들어온 콜백이다. 예를 들어 TCP 핸들러 내에서 비동기의 쓰기 작업을 한다면, TCP 통신과 쓰기 작업이 끝난 후 해당 작업의 콜백이 큐에 들어 온다.
타이머 단계를 거쳐 대기 콜백 단계에 들어오면 이전 작업들의 콜백이 pending_queue에서 대기 중인지 검사. 실행 대기 중이라면 실행 한도 도달 전까지 꺼내어 실행한다.
/* 유후 준비 단계 */
유후 단계는 tick 마다 실행 된다. 준비 단계는 매 폴링 직전에 실행 된다. 폴링은 이벤트 루프가 I/O 이벤트를 대기하고 처리하는 단계이다.
이는 Node.js의 내부 동작을 위한 것이다
/* 폴 단계 */
폴 단계에서는 새로운 I/O 이벤트를 가져와서 관련 콜백을 수행한다. 이 단계가 가지고 있는 큐는 watch_queue 다. 이 단계에 진입한 후 watch_queue가 비어있지 않다면 큐가 비거나 실행 한도에 다다를 때까지 동기적으로 모든 콜백을 실행한다. 큐가 비게 되면 check_queue, pending_queue, closing_callbacks_queue (종료 콜백 단계의 큐)에 남은 작업이 있는 지 검사한 다음 다음 단계로 이동한다. 만약 큐가 모두 비면은 대기를 한다.
/* 체크 단계 */
setImmediate의 콜백만을 위한 단계이다.
/* 종료 콜백 단계 */
socket.on 과 같은 close나 destroy 이벤트 타입의 콜백이 처리된다
이벤트 루프는 종료 콜백 단계를 마치고 나면 다음 루프에서 처리 해야하는 작업이 남아 있는 지 검사합니다. 만약 작업이 남아 있다면 타이머 단계에서 한 번 더 루프를 돌게되고 아니면 루프를 종료한다.
'서버' 카테고리의 다른 글
[HTTP] DNS (0) | 2024.10.07 |
---|---|
[HTTP] OSI 7계층 (1) | 2024.09.02 |
[Node.js] 무엇인가 (0) | 2024.07.07 |
[서버] RESTful API (0) | 2024.03.30 |
[HTTP] 멱등성 (0) | 2024.02.03 |