클러스터를 사용한 충돌 내성 Node.js 앱 구축

발행: (2025년 12월 18일 오후 07:00 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

위의 링크에 있는 전체 글을 번역하려면, 번역하고 싶은 본문을 제공해 주세요. 현재는 링크만 포함되어 있어 번역할 내용이 없습니다. 본문을 복사해서 알려주시면 한국어로 번역해 드리겠습니다.

커널

커널은 운영 체제의 핵심 구성 요소입니다 (예: Linux 커널).
그 역할은 다음과 같습니다:

  • 실행 중인 모든 프로그램 관리
  • 각 프로그램에 고유한 메모리 공간 할당
  • 프로그램 간 격리

두 개의 애플리케이션을 실행하고 있다면:

app1 | app2

커널은 이들을 분리하여 서로의 메모리를 오염시킬 수 없게 합니다.
app2가 충돌하면, 커널은 격리된 상태로 충돌이 발생하도록 하여 app1에 영향을 주지 않게 합니다.

그 부분은 대부분의 사람들이 알고 있습니다.

대부분의 사람들이 놓치는 부분

커널은 충돌한 앱을 단순히 종료하는 것이 아니라, 그 앱을 실행한 사람에게 충돌을 보고합니다.
개념적으로는 다음과 같습니다:

int main() {
  return 0; // Let things crash, just don’t let them take everything with them.
}

그래서 전화 회선이 실제로 “끊기지” 않는 것입니다.
그래서 브라우저가 죽지 않는 것처럼 느껴지는 것입니다.

Node.js도 마찬가지

Node.js에서는 클러스터를 사용해 정확히 같은 일을 할 수 있습니다.

  • 클러스터는 스레드가 아닙니다.
  • 실제 OS 프로세스입니다.

클러스터를 포크하면 현재 인스턴스 위에 다른 Node.js 인스턴스를 부팅하는 것과 같습니다.

저는 이것을 항상 사용합니다. 예를 들어, 프로파일러는 워커 클러스터에서 실시간 이벤트를 수신하고 GUI는 메인 프로세스에서 실행됩니다. 워커가 실패해도 UI는 계속 살아 있습니다.

Trace CLI

Reference: How I Built a Graphics Renderer for Node.js

Node.js의 클러스터

간단한 예시입니다: 무작위로 충돌하고 자동으로 재시작되는 클러스터에서 실행되는 서버.

// cluster-demo.js
const cluster = require('cluster');
const os = require('os');

if (cluster.isPrimary) {
  console.log(`primary ${process.pid} is running`);

  const numCPUs = os.cpus().length;

  // fork a couple of workers
  for (let i = 0; i < Math.min(numCPUs, 2); i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died (code=${code}, signal=${signal})`);
    setTimeout(() => {
      console.log('Restarting worker...');
      cluster.fork();
    }, 1000);
  });

  cluster.on('online', (worker) => {
    console.log(`Worker ${worker.process.pid} is online`);
  });

} else {
  console.log(`Worker ${process.pid} started`);

  const http = require('http');

  const server = http.createServer((req, res) => {
    res.writeHead(200);
    res.end(`Hello from worker ${process.pid}`);
  });

  server.listen(3000, () => {
    console.log(`Worker ${process.pid} listening on port 3000`);
  });

  // simulate random crashes
  const crashTimeout = Math.floor(Math.random() * 30000) + 10000;
  setTimeout(() => {
    console.log(`Worker ${process.pid} will crash in 5 seconds...`);
    setTimeout(() => {
      throw new Error(`Simulated crash in worker ${process.pid}`);
    }, 5000);
  }, crashTimeout);

  process.on('SIGTERM', () => {
    console.log(`Worker ${process.pid} shutting down gracefully`);
    server.close(() => process.exit(0));
  });
}

else 블록 내부의 모든 코드는 전용 클러스터 프로세스에서 실행됩니다.

이 예시에서는 두 개의 워커(또는 CPU 수가 두 개 이하인 경우 그 수만큼)를 띄웁니다.

if 블록은 메인 애플리케이션입니다.
그것이 충돌하면—모든 것이 죽습니다.
하지만 워커가 충돌하면? 부모 프로세스가 이를 감지하고 새로운 워커를 부팅합니다.

이것이 전체 요령입니다.

클러스터를 사용해야 할 때

클러스터는 다음과 같은 경우에 매우 강력합니다:

  • 장애 격리
  • 크래시 복구
  • 개별 프로세스 실패에도 지속되는 장기 실행 시스템

Node.js 서비스를 크래시 내성자체 복구 가능하게 만들고 싶을 때 언제든 사용하세요.

나에 대한 더 많은 내용

자세한 내용이 궁금하다면 Node.js 문서를 읽어보는 것이 좋습니다.

기사

저장소

읽어주셔서 감사합니다!

여기서 나를 찾아보세요

Back to Blog

관련 글

더 보기 »