SHIN
Node.js 실전 팁 20선
20편Node.js 기본 내장 cluster 모듈로 포크(fork) 방식의 멀티프로세스 서버를 구성할 수 있습니다.
const cluster = require('cluster');
const http = require('http');
const os = require('os');
if (cluster.isPrimary) {
const numCPUs = os.cpus().length;
console.log(`Master ${process.pid} 실행 중, ${numCPUs}개 워커 포크`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} 종료. 재시작...`);
cluster.fork(); // 자동 재시작
});
} else {
// 워커: 실제 서버 로직
http.createServer((req, res) => {
res.end(`Worker ${process.pid} 응답`);
}).listen(3000);
console.log(`Worker ${process.pid} 시작`);
}const cluster = require('cluster');
const os = require('os');
if (cluster.isPrimary) {
for (let i = 0; i < os.cpus().length; i++) cluster.fork();
cluster.on('exit', () => cluster.fork());
} else {
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({ pid: process.pid, message: 'OK' });
});
app.listen(3000);
}if (cluster.isPrimary) {
const worker = cluster.fork();
// 워커에게 메시지 전송
worker.send({ type: 'config', data: { timeout: 5000 } });
// 워커 메시지 수신
worker.on('message', (msg) => {
if (msg.type === 'stats') {
console.log(`Worker stats: ${JSON.stringify(msg.data)}`);
}
});
} else {
process.on('message', (msg) => {
if (msg.type === 'config') {
// 설정 적용
}
});
// 주기적으로 통계 보고
setInterval(() => {
process.send({ type: 'stats', data: { memory: process.memoryUsage() } });
}, 5000);
}if (!cluster.isPrimary) {
process.on('SIGTERM', () => {
server.close(() => {
console.log(`Worker ${process.pid} 정상 종료`);
process.exit(0);
});
});
}| 구분 | cluster | Worker Threads |
|---|---|---|
| 격리 수준 | 완전 격리 (별도 프로세스) | 같은 프로세스 |
| 메모리 공유 | 불가 | SharedArrayBuffer |
| 용도 | HTTP 서버 스케일링 | CPU 계산 |
| 오버헤드 | 높음 (프로세스 포크) | 낮음 |
PM2를 사용하면 cluster 모드를 명령어 하나로 관리할 수 있습니다:
pm2 start app.js -i max