아래는 Node.js의 이벤트 루프가 여러 단계(phase)로 나뉘어 동작하는 방식과, libuv가 각 단계에서 어떤 역할을 수행하는지에 대해 상급자 수준으로 자세하게 설명한 내용입니다.
1. Node.js 이벤트 루프 개요
Node.js는 libuv라는 라이브러리를 기반으로 이벤트 루프를 구현합니다. 이벤트 루프는 비동기 I/O 작업을 관리하며, 여러 단계(phase)로 나뉘어 각 단계별로 특정 작업들을 처리합니다. 이 구조 덕분에 Node.js는 단일 스레드 환경에서도 높은 동시성을 구현할 수 있습니다.
2. 이벤트 루프의 각 단계(phase)
Node.js의 이벤트 루프는 일반적으로 다음과 같은 주요 단계로 구성됩니다. 각 단계는 특정 작업의 집합을 처리하며, libuv는 이 단계들을 관리하고 스케줄링합니다.
2.1. 타이머(Timers) 단계
- 역할:
setTimeout()
과 setInterval()
에서 예약한 콜백들을 실행합니다.
- 동작 방식:
- 타이머는 지정된 시간이 경과한 후, 콜백 큐에 추가됩니다.
- 이벤트 루프는 타이머 큐를 검사하여, 만료된 타이머 콜백을 실행합니다.
- libuv의 기여:
- libuv는 내부 타이머 큐를 유지하며, OS의 타이머 API(예: POSIX 타이머)를 활용하여 정확한 타이머 관리를 수행합니다.
2.2. I/O 콜백(Pending Callbacks) 단계
- 역할:
일부 시스템 콜(예: 에러가 발생한 TCP 연결 관련 콜백, DNS 쿼리의 일부 콜백 등)을 처리합니다.
- 동작 방식:
- 이전 단계에서 발생한 일부 시스템 호출의 결과 콜백이 대기하고 있다면, 이 단계에서 실행됩니다.
- libuv의 기여:
- libuv는 OS에 요청한 비동기 I/O 작업의 완료 알림을 받고, 해당 콜백들을 이 단계로 전달합니다.
2.3. Idle, Prepare 단계
- 역할:
내부적으로 사용되는 단계로, 이벤트 루프가 다음 단계(예: poll 단계) 전에 수행할 사전 준비 작업이나, 특별한 작업이 없는 동안의 처리를 담당합니다.
- 동작 방식:
- 이 단계는 주로 libuv 내부에서 사용되며, 사용자가 직접 접근할 일은 거의 없습니다.
- libuv의 기여:
- libuv는 이 단계를 활용해 다음 단계의 준비 작업을 하거나, 내부 루틴을 실행합니다.
2.4. Poll 단계