Node.js 멀티코어 활용을 위한 Cluster 모듈 적용기
문제 상황
운영 중인 API 서버가 트래픽 증가로 응답 속도가 느려지기 시작했다. AWS 모니터링을 확인해보니 CPU 사용률이 25% 정도에서 머물렀다. 4코어 인스턴스인데 1개만 쓰고 있었던 것이다.
Node.js는 단일 스레드 기반이라 하나의 프로세스는 하나의 코어만 사용한다. 멀티코어를 활용하려면 여러 프로세스를 띄워야 한다.
Cluster 모듈 도입
Node.js 내장 Cluster 모듈을 사용하면 마스터-워커 구조로 프로세스를 관리할 수 있다.
const cluster = require('cluster');
const os = require('os');
const express = require('express');
if (cluster.isMaster) {
const numCPUs = os.cpus().length;
console.log(`Master ${process.pid} is running`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died`);
cluster.fork(); // 워커가 죽으면 재시작
});
} else {
const app = express();
// ... 기존 Express 설정
app.listen(3000);
console.log(`Worker ${process.pid} started`);
}
결과
- CPU 사용률이 고르게 분산됨
- 동일 트래픽 대비 응답 시간 30% 개선
- 워커 프로세스 하나가 죽어도 서비스 지속 가능
주의사항
세션 스토어는 Redis를 사용해야 한다. 메모리 세션은 프로세스마다 따로 관리되기 때문에 문제가 생긴다. PM2 같은 프로세스 매니저를 쓰는 것도 대안이지만, 일단 내장 모듈로 해결했다.
작은 변경이지만 효과는 확실했다. 수평 확장 전에 수직 확장부터 제대로 해야겠다는 교훈을 얻었다.