IT Best Practise/React

Next.js 애플리케이션 클러스터링 및 로드 밸런싱 설정

GilliLab IT 2025. 6. 16. 17:04
728x90
반응형

Next.js 애플리케이션 클러스터링 및 로드 밸런싱 설정

Next.js 애플리케이션을 PM2를 사용하여 클러스터링하고 로드 밸런싱을 설정하는 방법을 단계별로 자세히 설명하겠습니다. 이를 통해 다중 코어를 활용하여 성능을 최적화하고, 요청을 여러 프로세스에 분산하여 안정적인 프로덕션 환경을 구축할 수 있습니다.


1. PM2와 클러스터링 개요

  • PM2: Node.js 애플리케이션용 프로세스 매니저로, 클러스터 모드를 통해 애플리케이션을 여러 프로세스로 실행하여 다중 코어 CPU를 활용합니다.
  • 클러스터링: PM2의 cluster 모드는 동일한 애플리케이션을 여러 워커 프로세스로 실행하며, 각 프로세스는 독립적으로 요청을 처리합니다.
  • 로드 밸런싱: PM2는 내부적으로 HTTP 요청을 워커 프로세스 간에 분산하여 부하를 균등하게 처리합니다.
  • Next.js와의 호환성: Next.js는 Node.js 기반 서버로 실행되며(npm start), PM2의 클러스터 모드와 잘 호환됩니다.

2. 사전 준비

  1. Node.js 및 PM2 설치

    • 최신 LTS 버전의 Node.js가 설치되어 있는지 확인:
      node -v
      npm -v
    • PM2 설치:
      npm install -g pm2
      pm2 -v
  2. Next.js 애플리케이션 준비

    • Next.js 프로젝트 디렉토리로 이동하여 production 빌드를 생성:
      cd /path/to/your-next-app
      npm install
      npm run build
    • 실행 테스트:
      npm run start
      기본적으로 http://localhost:3000에서 실행됩니다.
  3. 서버 환경

    • Ubuntu/Debian 또는 다른 리눅스 배포판 기반 서버 가정.
    • 방화벽에서 포트 3000(또는 사용자 지정 포트) 허용:
      sudo ufw allow 3000

3. PM2로 클러스터링 설정

PM2의 클러스터 모드를 사용하여 Next.js 애플리케이션을 여러 프로세스로 실행합니다.

3.1. 기본 클러스터 모드 실행

  1. 클러스터 모드로 시작

    • 다음 명령어로 Next.js 애플리케이션을 클러스터 모드로 실행:
      pm2 start npm --name "nextjs-app" -- start -i max
    • 설명:
      • --name "nextjs-app": 애플리케이션 이름 지정.
      • -- start: npm start 명령어 실행.
      • -i max: CPU 코어 수만큼 프로세스 생성(max는 사용 가능한 코어 수 자동 감지).
  2. 상태 확인

    • PM2 프로세스 목록 확인:
      pm2 list
    • 출력 예:
      ┌────┬────────────┬─────────────┬──────┬─────┬──────────┬──────────┐
      │ id │ name       │ mode       │ ↺    │ status │ cpu      │ memory   │
      ├────┼────────────┼─────────────┼──────┼─────┼──────────┼──────────┤
      │ 0  │ nextjs-app │ cluster    │ 0    │ online │ 0%       │ 150mb    │
      │ 1  │ nextjs-app │ cluster    │ 0    │ online │ 0%       │ 150mb    │
      │ 2  │ nextjs-app │ cluster    │ 0    │ online │ 0%       │ 150mb    │
      │ 3  │ nextjs-app │ cluster    │ 0    │ online │ 0%       │ 150mb    │
      └────┴────────────┴─────────────┴──────┴─────┴──────────┴──────────┘
      • mode: cluster와 여러 프로세스(0, 1, 2, 3)가 실행 중임을 확인.
  3. 모니터링

    • 실시간 모니터링:
      pm2 monit
    • CPU, 메모리 사용량, 재시작 횟수 등을 확인 가능.

3.2. 환경 변수 설정

  • Next.js는 NODE_ENV=production과 같은 환경 변수가 필요합니다.
  • 명령어에 직접 추가:
    pm2 start npm --name "nextjs-app" -- start -i max --env NODE_ENV=production --env PORT=3000

3.3. 고급 설정: Ecosystem 파일 사용

더 세밀한 제어를 위해 ecosystem.config.js 파일을 사용하는 것이 좋습니다.

  1. Ecosystem 파일 생성

    • 프로젝트 루트에 ecosystem.config.js 파일 생성:
      nano ecosystem.config.js
  2. 파일 작성

    module.exports = {
      apps: [
        {
          name: "nextjs-app",
          script: "npm",
          args: "start",
          cwd: "/path/to/your-next-app", // 프로젝트 경로
          instances: "max", // CPU 코어 수만큼 프로세스 생성
          exec_mode: "cluster", // 클러스터 모드
          env: {
            NODE_ENV: "production",
            PORT: 3000,
          },
          env_production: {
            NODE_ENV: "production",
            PORT: 3000,
          },
          max_memory_restart: "1G", // 메모리 초과 시 재시작
          autorestart: true, // 충돌 시 자동 재시작
          watch: false, // 파일 변경 감지 비활성화 (프로덕션용)
          log_date_format: "YYYY-MM-DD HH:mm:ss", // 로그 타임스탬프 형식
        },
      ],
    };
    • 주요 옵션:
      • instances: "max": CPU 코어 수만큼 프로세스 실행.
      • exec_mode: "cluster": 클러스터 모드 활성화.
      • env: 환경 변수 설정.
      • max_memory_restart: 메모리 사용량 제한.
      • watch: false: 프로덕션에서는 파일 감지 비활성화.
  3. 애플리케이션 시작

    pm2 start ecosystem.config.js
  4. 설정 저장

    • 부팅 시 자동 실행을 위해 설정 저장:
      pm2 save

4. 로드 밸런싱 설정

PM2의 클러스터 모드는 자체적으로 로드 밸런싱을 제공합니다.

4.1. PM2의 로드 밸런싱 동작

  • PM2는 마스터 프로세스가 HTTP 요청을 워커 프로세스에 라운드-로빈 방식으로 분산.
  • 별도의 외부 로드 밸런서(예: Nginx) 없이도 기본적인 부하 분산 가능.
  • 클러스터 모드(-i max) 활성화 시 자동으로 적용.

4.2. 로드 밸런싱 최적화

  1. 워커 수 조정

    • CPU 코어 수에 따라 워커 수를 설정:
      pm2 start ecosystem.config.js -i 4 # 4개 워커
    • max 대신 특정 숫자를 사용하여 메모리 사용량 조절 가능.
  2. 포트 충돌 방지

    • Next.js는 기본적으로 단일 포트(3000)에서 실행되며, PM2 클러스터 모드는 동일 포트를 공유.
    • 포트 충돌이 없도록 ecosystem.config.js에서 PORT 명시.
  3. 성능 모니터링

    • 요청 분산 상태 확인:
      pm2 monit
    • 각 워커의 CPU/메모리 사용량을 관찰하여 부하 분산 확인.

5. 리버스 프록시 설정 (선택 사항)

PM2 클러스터링은 내부 로드 밸런싱을 제공하지만, 외부 요청을 처리하려면 Nginx를 리버스 프록시로 설정하는 것이 일반적입니다.

  1. Nginx 설치

    sudo apt update
    sudo apt install nginx
  2. Nginx 설정

    • 설정 파일 생성:

      sudo nano /etc/nginx/sites-available/nextjs-app
    • 설정 추가:

      server {
          listen 80;
          server_name your-domain.com; # 도메인 또는 IP
      
          location / {
              proxy_pass http://localhost:3000; # PM2가 실행 중인 포트
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
              proxy_set_header Host $host;
              proxy_cache_bypass $http_upgrade;
          }
      }
  3. Nginx 활성화 및 재시작

    sudo ln -s /etc/nginx/sites-available/nextjs-app /etc/nginx/sites-enabled/
    sudo nginx -t # 설정 테스트
    sudo systemctl restart nginx
  4. SSL 설정 (선택 사항)

    • Let’s Encrypt로 HTTPS 활성화:
      sudo apt install certbot python3-certbot-nginx
      sudo certbot --nginx -d your-domain.com

6. 부팅 시 자동 실행 설정

PM2가 시스템 재부팅 시 자동으로 시작되도록 설정합니다.

  1. PM2 부팅 설정

    pm2 startup
    • 출력된 명령어를 실행하여 systemd에 PM2 등록:
      sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u <user> --hp /home/<user>
  2. 현재 프로세스 저장

    pm2 save
  3. 확인

    • 서버 재부팅 후 PM2 프로세스 확인:
      pm2 list

7. 로그 및 모니터링

  1. 로그 확인

    • PM2 로그 확인:
      pm2 logs nextjs-app
    • 로그 파일 경로: ~/.pm2/logs/.
  2. 로그 회전

    • PM2 로그 회전 모듈 설치:
      pm2 install pm2-logrotate
    • 설정 조정:
      pm2 set pm2-logrotate:max_size 100M
      pm2 set pm2-logrotate:retain 7
  3. 모니터링

    • 실시간 모니터링:
      pm2 monit
    • PM2 Plus(유료)로 웹 대시보드 사용 가능.

8. 배포 및 업데이트

  1. 코드 업데이트

    • 새로운 코드 배포:
      git pull
      npm install --production
      npm run build
  2. 무중단 배포

    • PM2로 프로세스 재시작(제로 다운타임):
      pm2 reload ecosystem.config.js
    • reload는 기존 프로세스를 유지하면서 새 프로세스를 시작.
  3. 롤백

    • 문제가 발생하면 이전 커밋으로 되돌리고 재배포:
      git checkout <previous-commit>
      npm install
      npm run build
      pm2 reload ecosystem.config.js

9. 최적화 및 주의사항

  1. 메모리 관리

    • max_memory_restart 설정으로 메모리 초과 방지:
      max_memory_restart: "1G";
    • Next.js는 SSR/ISR 사용 시 메모리 사용량이 높을 수 있으므로 모니터링 필수.
  2. 클러스터링 주의점

    • 워커 수는 CPU 코어 수를 초과하지 않도록 설정(instances: "max" 권장).
    • 과도한 워커는 메모리 오버헤드 발생 가능.
  3. Next.js 특화 고려사항

    • Dynamic Routes 및 API: 클러스터 모드에서 상태 공유(예: 세션)는 Redis 같은 외부 스토리지 사용.
    • Static Export: 정적 사이트인 경우 클러스터링 불필요, Nginx로 정적 파일 서빙 추천.
  4. 보안

    • PM2 실행 사용자 권한 최소화:
      sudo chown -R <user>:<user> /path/to/your-next-app
    • 방화벽으로 불필요한 포트 차단.

10. 예제 Ecosystem 파일

아래는 완전한 ecosystem.config.js 예제입니다:

module.exports = {
  apps: [
    {
      name: "nextjs-app",
      script: "npm",
      args: "start",
      cwd: "/path/to/your-next-app",
      instances: "max",
      exec_mode: "cluster",
      env: {
        {
          NODE_ENV: "production",
          PORT: 3000,
          API_KEY: "your-api-key",
        },
      },
      env_production: {
        {
        NODE_ENV: "production",
        PORT: 3000,
        API_KEY: "your-api-key",
      },
      },
      max_memory_restart: "1G",
      autorestart: true,
      watch: false,
      log_date_format: "YYYY-MM-DD HH:mm:ss",
      error_log_file: "/path/to/your-app/.pm2/logs/nextjs-app-error.log",
      out_log_file: "/path/to/your-app/.pm2/logs/nextjs-app-out.log",
      merge_logs: true,
      kill_timeout: 3000,
    },
  ]
},
};

10. 문제 해결

  • 포트 충돌:
    • netstat -tuln | grep 3000으로 포트 점유 확인.
    • ecosystem.config.js에서 PORT 명시.
  • 프로세스 죽음:
    • pm2 logs로 오류 확인.
    • 메모리 초과 시 max_memory_restart 조정.
  • 로드 밸런싱 불균형:
    • pm2 monit으로 워크 요청 분산 확인.
    • Nginx 사용 시 upstream 설정으로 추가 로드 밸런싱 가능.
  • 결론:
    PM2를 사용한 Next.js 클러스터링과 로드 밸런싱은 간단한 설정으로 성능을 크게 향상시킬 수 있습니다. ecosystem.config.js를 활용하여 환경을 세밀히 조정하고, Nginx와 결합하면 고급 프로덕션 환경을 구축할 수 있습니다.

Keywords:

Next.js, PM2, Clustering, Load Balancing, Node.js, 클러스터링, 로드 밸런싱, 배포, 모니터링, 보안

728x90
반응형