Node.js 멀티코어 활용: Worker Threads vs Cluster 모듈

문제 상황

대용량 CSV 파싱 및 데이터 변환 API를 개발하던 중 단일 스레드로는 처리 속도가 너무 느렸다. 서버는 8코어였지만 Node.js 프로세스 하나만 100%를 찍으며 나머지 코어는 놀고 있었다.

Cluster 모듈 시도

먼저 익숙한 Cluster 모듈로 접근했다.

const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster) {
  const numCPUs = os.cpus().length;
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  require('./server');
}

여러 워커 프로세스가 포트를 공유하며 요청을 분산 처리했다. 동시 요청이 많을 때는 효과적이었지만, 단일 요청 내 무거운 작업은 여전히 느렸다.

Worker Threads로 전환

Node 12부터 안정화된 Worker Threads를 적용했다. 하나의 요청 내에서 작업을 여러 청크로 나눠 병렬 처리했다.

const { Worker } = require('worker_threads');

function processChunk(data) {
  return new Promise((resolve, reject) => {
    const worker = new Worker('./worker.js', { workerData: data });
    worker.on('message', resolve);
    worker.on('error', reject);
  });
}

const chunks = splitData(largeData, 8);
const results = await Promise.all(chunks.map(processChunk));

단일 요청 처리 시간이 약 60% 단축되었다.

결론

  • Cluster: 다중 요청 분산, PM2 같은 프로세스 매니저와 유사
  • Worker Threads: 단일 요청 내 CPU 작업 병렬화, 메모리 공유 가능

우리 케이스는 Worker Threads가 적합했다. 다만 워커 생성 비용이 있으니 워커 풀을 만들어 재사용하는 방식으로 개선할 예정이다.

Node.js 멀티코어 활용: Worker Threads vs Cluster 모듈