Node.js 클러스터링 vs 워커 스레드: 포크할 때와 스레드를 사용할 때
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
DevOps
대상자
- 대상: Node.js 서버 확장 및 성능 최적화를 담당하는 개발자
- 난이도: 중급~고급 (Node.js의 동시성 모델 이해 필요)
핵심 요약
- 클러스터링 (
cluster
모듈)은 상태 없는 API(예: REST 서비스)와 프로세스 고립에 적합하며, 간단한 확장이 가능하다. - 워커 스레드는 CPU 집약적 작업(예: 이미지 처리, 수학 연산)에 최적화되어 있고, 공유 메모리를 통해 효율적 처리가 가능하다.
- 혼합 사용이 효과적: 클러스터링으로 HTTP 로드 밸런싱, 워커 스레드로 PDF 생성과 같은 CPU 집약 작업 처리.
섹션별 세부 요약
1. 클러스터링 개요
- 마스터 프로세스는
os.cpus().length
에 따라 서브 프로세스를 복제하여 CPU 코어 수만큼 실행. - 장점:
- ✔ 상태 없는 API에 적합 (예: REST 서비스)
- ✔ 단일 프로세스 실패 시 다른 프로세스 영향 없음
- ✔
cluster
모듈로 간단한 확장 가능 - 단점:
- ❌ 각 프로세스 별로 메모리 복제 (메모리 사용량 증가)
- ❌ 공유 상태 없음 (Redis 등 외부 저장소 필요)
2. 워커 스레드 개요
worker_threads
모듈을 사용해 하나의 프로세스 내 스레드 분할.- 장점:
- ✔ CPU 집약 작업에 적합 (예: PDF 생성, 수학 연산)
- ✔ 메모리 공유 가능 (via
SharedArrayBuffer
) - 단점:
- ❌ 스레드 안전 코드 작성 어려움 (경쟁 조건, 데드락 가능성)
- ❌ 자동 로드 밸런싱 없음 (수동 관리 필요)
3. 성능 비교 결과
- 클러스터링:
- ✅ 4코어 머신에서 4배의 처리량 향상
- ❌ 메모리 사용량 2배 증가 (동일 데이터 캐시 중복)
- 워커 스레드:
- ✅ CPU 작업에서 30% 빠름 (클러스터링 대비)
- ❌ 경쟁 조건으로 인한 한 번의 크래시 발생
4. 사용 시나리오 비교
| 시나리오 | 클러스터링 | 워커 스레드 |
|------------------|------------|-------------|
| 상태 없는 HTTP 서버 | ✅ 최적 | ❌ 필요 없음 |
| CPU 집약 작업 | ❌ 과도한 복잡성 | ✅ 최적 |
| 크래시 고립 필요 | ✅ 가능 | ❌ 불가능 |
| 공유 메모리 필요 | ❌ 불가능 | ✅ 가능 |
결론
- 혼합 전략이 효과적: 클러스터링으로 HTTP 요청 분산 처리, 워커 스레드로 PDF 생성과 같은 CPU 집약 작업 처리.
- 주의사항: 워커 스레드는 스레드 안전성과 경쟁 조건 주의, 클러스터링은 메모리 사용량 증가에 주의.
- 코드 예시:
```javascript
// 클러스터링 예시
const cluster = require('cluster');
const os = require('os');
if (cluster.isMaster) {
for (let i = 0; i < os.cpus().length; i++) {
cluster.fork(); // CPU 코어 수만큼 포크
}
} else {
require('./server'); // 실제 앱 로드
}
// 워커 스레드 예시
const { Worker } = require('worker_threads');
function runWorker(data) {
return new Promise((resolve) => {
const worker = new Worker('./worker.js', { workerData: data });
worker.on('message', resolve);
});
}
```