Skip to main content

Node.js

Node.js란, 비동기 이벤트 주도 JavaScript 런타임 환경이다.

이렇게 말하면 이해가 잘 되지 않을테니 구조를 함께 살펴보자.


Architecture

nodejs-architecture

(Image from https://medium.com/yet-another-node-js-blog/architecture-of-node-js-internal-codebase-57cd8376b71f by Aren Yanqi Li)


1. V8

V8은 Google에서 C++로 개발한, 고성능 JavaScript 및 WebAssembly Engine이다. Chrome과 Node.js에서 특히 사용된다. V8은 독자적으로 실행될 수 있으며, C++ 애플리케이션에서도 사용될 수 있다.


2. libuv

Node.js를 위해 만들어진, 비동기 I/O 기반의 Event Loop를 지원하는 C 라이브러리이다. 그렇기 때문에 Node.js에서는 네트워크 요청이나 I/O 등의 작업을 비동기적으로(즉, 여러 작업을 동시에) 처리할 수 있다. 이 라이브러리에서 다음의 기능을 제공한다.

  • Full-featured event loop backed by epoll, kqueue, IOCP, event ports.
  • Asynchronous TCP and UDP sockets
  • Asynchronous DNS resolution
  • Asynchronous file and file system operations
  • File system events
  • ANSI escape code controlled TTY
  • IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
  • Child processes
  • Thread pool
  • Signal handling
  • High resolution clock
  • Threading and synchronization primitives

3. Other C/C++ Components

가령, crypto(openssl), html-parser 등의 저수준의 기능을 제공한다.


4. Application/Modules

JavaScript Core Module, 소스 코드, npm 라이브러리 등이 포함된다.


5. C/C++ Bindings

Node.js에는 C/C++로 작성된 라이브러리가 많이 사용되는데, 따라서 이를 Node.js 환경에서 사용하기 위해 바인딩이 필요하다.


6. C/C++ Addons

그 외에 다른 third-party C/C++ 라이브러리를 포함시키기 위해서는 바인딩 하기위한 코드를 직접 작성해야한다.


Features

위의 구조를 통해 Node.js는 결국 다음의 주요 기능으로 설명될 수 있다.

1. Event-Driven Architecture와 Non-blocking I/O

Node.js는 네트워크의 요청, 사용자의 I/O 이벤트에 반응해서 동작하게 된다. 이렇게 이벤트가 발생하면 Event Loop가 이를 감지하고, 콜백함수를 호출해 백그라운드에서 이를 처리한다. 그로 인해 작업이 완료되기 전에 I/O의 작업을 차단하지 않고, 다른 요청을 처리할 수 있게 되므로 비동기 처리가 가능해진다.


2. JavaScript Core(Built-in) Module

또 중요한 것으로, JavaScript의 Core Module을 들 수 있다. 가령 crypto, fs, path, http 등이 있고, 이들은 별도의 설치 없이 import 후 사용이 가능하다.


3. Single Thread

Node.js는 매 요청마다 스레드를 새로 생성하지 않고, 기본적으로 단일 스레드를 사용한다. 그렇기 때문에 Multi-Threading, Multi-Processing과는 다르다. 어떻게 가능한걸까?

사실 Node.js에서는 libuv에서 제공하는 Worker Thread 덕분이다. Node.js 프로세스가 생성 됐을 때, 하나의 Thread가 기본적으로 되는데, 이게 Main Thread이다. Node.js에서는 메인 스레드에서 모든 요청을 다 처리한다. 그 외의 I/O 작업 등은 백그라운드에서 libuv에 의해 유지되고 있는 Worker Thread 에서 처리한다. 따라서 I/O 작업은 메인 스레드가 아닌, Worker Thread에서 비동기적으로 처리되는 것이다. 그리고 Node.js의 libuvThread Pool에 있는 Worker Thread를 직접 관리한다.

Related Links