0.들어가며
Node 기반의 서버를 쓰면 기본적으로 준비해야하는 것중 하나가
돌아가는 서버에 CPU 코어를 모두 활용할 수 있도록 준비하는 것이 필요하다.
자바 환경에서라면 알아서 쓰니까 세부적인 튜닝만 하면 되는데,
Node 에서는 직접 넣어줘야 한다.
내가 전에 했던 프로젝트에서는 부하테스트 후에 서버 버스트가 되었을때
예상했던 트래픽이 버텨질것으로 예상했었는데, 실제로 핫트래픽이 발생했을때
인프라쪽에서는 전혀문제가 없는데 서비스 p95가 점진적으로 늘어나는 현상을 발견한 경험이 있다.
발주처 요구사항으로 스프링기반의 서비스에서 Node 기반의 서비스로 마이그레이션을 한건데,
기존 초기설계 담당자가 해당 문제를 고려하지 못했고, 기간이 급해서였을까
이를 파악한 사람이 없었다.
후에 문제가 발생했을때 급하게 조치해서 사용했던 경험이 있어서, 이번에 정리한다.
1. 배경
Node.js는 기본적으로 싱글 스레드 이벤트 루프 기반으로 동작한다.
비동기 I/O는 효율적이지만, CPU 코어는 기본적으로 1개만 사용한다.
이 한계를 해결하기 위해 cluster를 사용해 멀티코어를 활용할 수 있으나,
모든 컴포넌트가 멀티 프로세스에 적합한 것은 아니다. (다음글에서 설명)
JS는 기본적으로 하나의 실행흐름을 가지는데, 이걸 단일 쓰레드라고 볼 수있다.
근데 보면 Node가 기본적으로 멀티 쓰레드 환경을 지원하는걸 볼 수 있다.
근데 실제로 CPU안에 있는 코어를 모두 활용하지않고 (아무것도 설정하지 않았을때)
1개만 쓰고 있는걸 알 수 있다. 즉, 하나의 프로세스만 발생한건데 이를 보안해야한다.
(즉, 여기서 말하는 이야기는 멀티프로세스를 만들어서 모든자원을 할당할 수 있게 최적화가 필요하다는 의미이다.)
여기서 프로세스랑 쓰레드를 간략하게만 설명하면
프로세스는 자원단위 할당의 범위이고, 쓰레드는 할당된 자원에서 독립된 작업흐름을 말한다.
자세한내용은 해당 포스트를 참고해라
https://sejin-technology.tistory.com/128
그래서 멀티 쓰레딩이 어떻게 되는건지는, Node 가 돌아가는 걸 조금 이해해야한다.
1.1 노드 구조를 간략히
우리가 작성하는 코드는 Application 레이어에 위치한다.
Node.js 환경에서는 Node.js Core APIs가 기본적으로 제공되며,
브라우저 환경에서는 Web APIs가 런타임에 포함된다.
Node.js 런타임 내부에는 JavaScript, C++, C로 구현된 다양한 구성 요소가 존재하며,
그중 libuv는 OS와 Node.js 사이에서 비동기 I/O를 추상화하고
이벤트 루프(Event Loop)를 실제로 구현·관리하는 핵심 라이브러리다.
libuv 내부에는 파일 I/O, 암호화 등 일부 블로킹 작업을 처리하기 위한
백그라운드 스레드 풀(thread pool)이 구현되어 있으며,
JavaScript 코드는 이를 직접 제어하지는 않지만
Node.js Core API를 통해 간접적으로 활용하게 된다.
1.2 그러면 어떻게 이런 멀티 클러스트를 사용할 수 있는가
1.2.1 Node.js Cluseter 모듈
Node.js의 내장모듈로 마스터 프로세스 + 워커 프로세스를 1:N 으로 쓰는거다
Nginx 같은 마스터 - 워커 구조를 사용하는건데, 쉽게 말해
마스터는 관리자 , 실제 동작은 워커를 통해한다고 이해할 수 있다.
Master
├─ Worker 1 (PID)
├─ Worker 2 (PID)
└─ Worker 3 (PID)
- 각 워커는 독립적인 Node 프로세스
- 각자 이벤트 루프 1개
- OS가 요청을 분산
1.2.2 PM2
PM2(Process Manager 2)는 Node.js 애플리케이션을 실행·관리·모니터링하기 위한
프로덕션용 프로세스 매니저다.
https://pm2.keymetrics.io/docs/usage/quick-start/
PM2의 핵심 목적은 다음과 같다.
- Node 프로세스 실행 및 종료 관리
- 장애 발생 시 자동 재시작
- 멀티 프로세스(멀티코어) 실행 지원
- 로그 관리 및 무중단 배포 지원
PM2의 실행 모델
PM2는 두 가지 실행 모드를 제공한다.
1) Fork Mode (기본)
- Node 프로세스 1개
- 싱글 프로세스 실행
- 상태를 유지하는 서비스(Socket, Scheduler 등)에 적합
PM2 └─ App (PID 1234)
2) Cluster Mode
- 내부적으로 Node.js
cluster모듈 사용 - CPU 코어 수만큼 워커 프로세스 실행
- HTTP API 같은 stateless 서비스에 적합
PM2 (Master) ├─ Worker 1 (PID) ├─ Worker 2 (PID) └─ Worker 3 (PID)
실행 예:
pm2 start app.js -i max
그래서 구조가 이렇게 잡힌다.
[ Client ]
↓
[ Server ]
↓
[ PM2 Cluster ]
↓
[ Worker 1 / 2 / 3 ]
근데, 여기서 문제가 단일 서버라면 문제가 없겠지만, 멀티 서버라면 문제가 된다.
'JS' 카테고리의 다른 글
| Node.js 에서 멀티코어를 활용하자 - 3 - 기본 Cluster (0) | 2026.02.02 |
|---|---|
| Node.js 에서 멀티코어를 활용하자 - 실무에서 쓰자 개념 (0) | 2026.02.02 |
| TDZ (Temporal Dead Zone) (0) | 2026.01.19 |
| npm 호이스팅과 js 호이스팅 (1) | 2026.01.19 |
| npm VS pnpm (0) | 2026.01.19 |