웹 브라우저에서 자바스크립트가 어떻게 작동하는 지를 살펴보고 난 이후에 생긴 궁금증이다.
백엔드 쪽에서 사용하기 위해 만들어진 Node.js
에서는 코드가 어떻게 작동을 할지에 대해서 말이다. Node.js
"About" 페이지에는 간단하게 설명한다.
As an asynchronous event-driven JavaScript runtime, Node.js is designed to build scalable network applications. In the following "hello world" example, many connections can be handled concurrently. Upon each connection, the callback is fired, but if there is no work to be done, Node.js will sleep.
-> Node.js 웹페이지
"asynchronoius"는 비동기다. Node.js
에서도 마찬가지로 비동기 프로그래밍을 지원한다. 이제 Node.js
에서 어떻게 비동기 프로그래밍을 구현하는지 간단하게 살펴보려고 한다.
Libuv
라이브러리는 C++
로 작성되어 비동기 I/O 처리를 도와준다. 커널을 추상화해서 만들어 놓고, 커널이 처리할 수 있는 명령은 거기서 처리하고, 그렇지 않은 명령들은 쓰레드풀에 집어 넣어 다른 I/O 처리들을 동기적으로 처리한다.
아직 헷갈리는 것은 명령들을 집어 넣는 쓰레드풀과 이후 설명하는 이벤트루프가 같은 존재인지다.
그래서 Libuv는 Node.js
의 I/O 작업을 위임받아 논 블로킹 I/O
를 지원하고, 이 기반에는 I/O Loop
가 있다고 한다.
Node.js
에서 작성한 코드를 실행하면 우선 순서대로 명령을 수행하게 된다. 그 중 시간이 걸리는 I/O 처리가 있다면 Libuv
는 I/O Loop
를 생성해서 해당 명령이 속하는 큐에 집어넣어 잠시 실행을 보류하고 남아 있는 코드의 명령을 수행한다.
I/O Loop
총 6개의 Queue
로 구성되어 있다. 간단히 각각의 큐를 설명하겠다.
SetTimeout
SetImmediate
함수를 관리하는 큐. Min-Heap으로 구현하여 시간이 짧은 순서대로 실행을 시키며, 효율적인 관리를 한다.File Descriptor
와 Queue
를 사용하여 다른 Queue
의 작업들을 확인하여 단계를 넘겨 나머지 지금 할 수 있는 작업들을 처리하고 돌아오는 등의 다른 효율적인 메커니즘을 수행한다.SetInterval
함수 실행을 관리한다.I/O Loop
는 위의 6단계를 처음 Timer로 시작하여 모든 Queue의 실행되는 명령들을 수행할 때까지 순환한다. 앞의 코드의 즉각 실행 가능한 명령들은 비동기적으로 실행이 끝났고, 여기서부터는 개발자가 짜놓은 코드대로 Non-Blocking
하게 각 I/O 명령들을 처리하게 된다.\