node.js를 배우기 시작하면서 배운 개념 중 Event Loop라는 녀석이 있다.
오늘은 내가 Event Loop를 이해한 내용을 바탕으로 적으려고 한다.
node.js는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임이다.
내부에 V8 엔진
을 가지고 있어 크롬같은 브라우저에서 실행하던 자바스크립트를 로컬에서 실행할 수 있다.
또한 node.js는 libuv
라는 라이브러리가 존재한다.
libuv는 논블로킹 비동기 I/O 라이브러리다. node.js는 싱글 스레드로 이루어져 있는데 이러한 비동기적 처리로 작업을 효율적으로 진행할 수 있다.
그리고 바로 libuv 안에 오늘의 주제인 Event Loop가 있다.
node.js는 비동기 처리로 libuv를 사용하고, 그 기반에는 Event Loop가 있다.
자바스크립트에는 콜 스택이 존재하여 일의 순서대로 스택이 쌓이는데,
비동기 작업의 경우 Event Loop에 들어간 뒤 처리가 완료되는대로 빠져나와 콜 스택에 합류하게 된다.
그럼 Event Loop는 어떻게 작동하는 것일까?
필자가 이해한 내용을 바탕으로 적는 것이니 틀린지점이 있을 수 있다는 양해를 우선 구한다.
이벤트 루프에는 각각의 페이즈(phase)가 존재한다.
- Timer Phase
- Pending Callbacks Phase
- Idle, Prepare Phase
- Poll Phase
- Check Phase
- Close Callbacks Phase
각 페이즈들은 자신만의 큐를 가지고 있고, 큐에서 작업이 끝나거나 시스템의 작업 한도에 다다르면 다음 페이즈로 넘어가는데,
한 페이즈에서 다음 페이즈로 넘어가는 것을 틱(Tick) 이라고 한다.
Event Loop에 작업이 들어오면 위 순서대로 루프를 돌게 된다.
예시를 들어서
Poll에 console.log("1");
Check에 console.log("2"); console.log("3");
Close Callbacks에 console.log("4");
위 처럼 작업이 할당되어 있다면,
Poll phase에 있는 큐 작업인 1을 출력하고, 더 이상 큐에 작업이 없으니 Check phase로 이동한다.
Check phase에선 2와 3을 순서대로 출력하고, 큐가 비었으니 다음 페이즈로 넘어간다.
Close Callbacks phase에서 4를 출력하고나면, 해당 페이즈의 큐가 비었으니 페이즈가 넘어가고,
페이즈에 남은 작업이 없으면 Event Loop를 종료한다.
단순한 예시를 들어 단순해 보이지만 실상은 그렇지 않다.
각 phase는 특징이 있고, 각자 정해진 비동기 작업을 처리한다.
예를 들어 Timer phase는 말 그대로 타이머가 정해진 작업을 처리한다(ex. setTimeout)
다음 포스팅에는 각 phase들의 특징과 동작에 대한 설명을 다루도록 하겠다.
어렵긴 하지만 재밌는 부분이라 생각이 들고,
node.js의 내부 동작을 이해할 수 있는 좋은 공부라고 생각한다.