Node.js 개념

연도·2025년 6월 3일

JavaScript, TypeScript

목록 보기
7/8
post-thumbnail

참고한 인사이트 : https://dlwoals727.medium.com/그래서-nodejs-가-싱글스레드야-멀티스레드야-6bb43eb44501, https://helloinyong.tistory.com/350
https://velog.io/@surim014/async-io-in-nodejs

Node.js

Node.js는 Chrome V8 JavaScript 엔진 위에서 구동되는 JavaScript 런타임입니다. 자바스크립트를 브라우저 밖, 즉 서버 사이드에서도 실행할 수 있게 해준다.

Node.js는 싱글 스레드 기반이지만, libuv 기반의 이벤트 루프 + 쓰레드 풀 구조를 활용해서 비동기적으로 많은 요청을 동시에 처리할 수 있는 특징이 있다.

싱글 스레드란

  • 하나의 메인 스레드에서 자바스크립트 코드를 실행.
  • 한 번에 한 줄의 JS 코드만 실행되므로 락, 데드락 문제 없다.
  • 구조가 단순하고 가벼워 메모리 소비도 적음.

동시성을 스레드 수가 아니라 비동기 처리 구조로 해결.

논블로킹 I/O (비동기 처리)

  • Node.js는 I/O 작업(파일 읽기, DB, 네트워크 등)을 기다리지 않고 다음 작업을 바로 수행하는 논블로킹 방식을 사용.
  • 오래 걸리는 작업은 libuv의 쓰레드 풀에 맡기고, 완료되면 콜백(또는 Promise) 형태로 알려준다.
  • 이 콜백은 콜백 큐(Task Queue)에 쌓이고, 이벤트 루프(Event Loop)가 이를 순차적으로 실행.

싱글 스레드지만, 쓰레드 풀을 활용해 병렬 I/O 처리가 가능하고, 이벤트 루프가 콜백을 비동기적으로 처리하기 때문에 수많은 요청을 동시에 다룰 수 있는 구조가 되는 것이다.

이벤트 루프 (Event Loop)

  • Node.js 비동기 처리의 핵심 메커니즘.
  • 백그라운드에서 완료된 작업의 콜백을 콜백 큐에 쌓고, 이벤트 루프가 이를 순차적으로 실행.
[JS 코드 실행]
 → [I/O 작업은 libuv 쓰레드 풀로 위임]
 → [작업 완료 시 콜백 큐에 등록]
 → [이벤트 루프가 콜백 실행]

비유

식당에서 요리사는 주문만 받고 요리는 주방에 맡김. 음식이 다 되면 알림을 받고 서빙한다. 요리사가 모든 손님을 직접 응대하는 구조가 바로 Node.js의 이벤트 루프이다.

경량화 & 모듈화

  • 불필요한 기능 없이, 필요한 기능만 require 혹은 import로 불러와 사용.
  • 멀티스레드 기반 서버에 비해 컨텍스트 스위칭 비용이 없고, 구조가 단순해서 빠르고 가벼움.

왜 Node.js는 빠르고 효율적인가

  • 요청마다 스레드를 생성하지 않는다.
  • 하나의 메인 스레드가 요청을 받고, I/O 작업은 백그라운드 쓰레드 풀로 넘김.
  • 따라서 I/O 중심 서비스에서 높은 처리량을 낼 수 있다.

Node.js 작동 원리

V8 엔진

  • Google Chrome에서 사용하는 자바스크립트 엔진.
  • JS 코드를 빠르게 머신 코드로 변환해 실행.

Libuv

Libuv는 Node.js의 비동기 처리를 담당하는 C 기반 라이브러리.

자바스크립트 자체는 비동기 I/O 기능이 없기 때문에, 이를 위해 libuv가 필요한 것.

libuv가 담당하는 일

  • 이벤트 루프 실행
  • 비동기 I/O 처리 (파일, 네트워크 등)
  • 쓰레드 풀 관리
  • 타이머(setTimeout 등) 처리
  • OS와 저수준 비동기 통

이벤트 루프 + 쓰레드 풀 구조

Node.js는 다음과 같은 구조로 작동함.

  1. 자바스크립트 코드는 V8 엔진이 메인 스레드에서 실행.
  2. 비동기 작업(예를 들어 fs.readFile, setTimeout, DB 요청 등)은 libuv를 통해 백그라운드 쓰레드 풀로 위임.
  3. 작업이 완료되면 해당 작업의 콜백이 Callback Queue(콜백 큐) 에 등록.
  4. 이벤트 루프가 이 큐를 순회하며 준비된 콜백을 순차적으로 실행함.

이 구조가 바로 Node.js가 논블로킹 I/O를 구현하는 핵심 메커니즘.

Thread Pool (기본 4개)

libuv는 내부적으로 4개의 워커 스레드(기본값)를 가지고 있음.

fs, crypto, zlib 같은 무거운 작업은 여기서 처리한다.

완료되면 콜백을 메인 스레드에서 실행.

Node.js의 단점

  • CPU 연산에 약하다

복잡한 계산이 많은 작업은 워커 스레드, 또는 다른 언어로 분리하는 것이 바람직하다.

  • 콜백 지옥 우려

과거에는 중첩된 콜백 형태가 많았으나, 지금은 Promise와 async/await로 대부분 해결 가능해졌다.

정리

Node.js는 싱글 스레드 기반이지만, 내부적으로는 libuv라는 C++ 라이브러리를 통해 이벤트 루프와 쓰레드 풀을 같이 운용하면서 비동기 처리를 효율적으로 수행합니다. I/O 같은 느린 작업은 백그라운드 쓰레드 풀에서 처리되고, 완료되면 메인 이벤트 루프가 콜백을 실행한다. 실제로 무거운 작업이 많을 땐 worker_threads 모듈을 활용해서 별도의 워커 스레드에서 처리하도록 구현해야 한다.

profile
Software Engineer

0개의 댓글