PM2는 Node.js 애플리케이션을 위한 프로덕션 프로세스 관리자로, 애플리케이션을 항상 활성 상태로 유지하고 성능을 모니터링합니다.
PM2는 Node.js 애플리케이션을 위한 오픈소스 프로세스 관리자입니다. 이는 애플리케이션을 데몬으로 실행하고, 클러스터 모드를 지원하며, 로드 밸런싱과 모니터링 기능을 제공하여 서버 환경에서 Node.js 애플리케이션을 안정적으로 운영할 수 있도록 돕습니다.
PM2가 제공하는 핵심 기능들은 다음과 같습니다.
PM2는 애플리케이션의 생명 주기를 관리하여 안정적인 운영을 보장합니다.
PM2의 클러스터 모드는 Node.js 애플리케이션의 성능과 가용성을 향상시키는 데 매우 중요합니다.
PM2는 애플리케이션의 성능을 실시간으로 파악하고 로그를 체계적으로 관리하는 기능을 제공합니다.
PM2를 시스템에 설치하고 간단한 명령어로 애플리케이션을 실행하는 방법을 알아봅니다.
PM2는 npm을 통해 전역으로 설치합니다. 전역 설치는 어떤 디렉토리에서든 pm2
명령어를 사용할 수 있게 해줍니다.
# 전역 설치: PM2를 시스템 어디서든 사용할 수 있도록 설치합니다. npm install -g pm2 # 버전 확인: 설치가 제대로 되었는지 확인하고 현재 PM2 버전을 출력합니다. pm2 --version
PM2를 사용하여 Node.js 애플리케이션을 시작하고 관리하는 기본적인 명령어들입니다.
# 애플리케이션 시작: 'app.js' 파일을 PM2를 통해 백그라운드에서 실행합니다. pm2 start app.js # 이름 지정하여 시작: 애플리케이션에 'my-app'이라는 식별하기 쉬운 이름을 부여하여 실행합니다. pm2 start app.js --name "my-app" # 클러스터 모드로 시작: 시스템의 모든 CPU 코어를 활용하여 최대 인스턴스 수만큼 애플리케이션을 실행합니다. pm2 start app.js -i max # 특정 포트로 시작: 애플리케이션에 인수를 전달하여 '3000'번 포트로 시작하도록 합니다. '--' 뒤의 인수는 애플리케이션 자체로 전달됩니다. pm2 start app.js -- --port 3000
ecosystem.config.js
파일을 사용하여 PM2 애플리케이션을 보다 세밀하게 설정할 수 있습니다. 이 파일은 여러 애플리케이션과 환경별 설정을 정의하는 데 유용합니다.
다음은 일반적인 ecosystem.config.js
파일의 구조와 각 속성에 대한 설명입니다.
module.exports = { apps: [{ // 이 배열 안에 관리할 애플리케이션들의 설정을 정의합니다. name: 'baduk-metaverse', // 애플리케이션의 고유 이름입니다. 'pm2 list'에서 이 이름으로 표시됩니다. script: 'server.js', // 실행할 애플리케이션의 메인 스크립트 파일 경로입니다. instances: 'max', // 실행할 인스턴스(워커 프로세스)의 수입니다. 'max'는 CPU 코어 수만큼 생성합니다. exec_mode: 'cluster', // 실행 모드입니다. 'cluster'는 로드 밸런싱을 지원하는 클러스터 모드입니다. env: { // 기본 환경 변수 설정입니다. NODE_ENV: 'development', // 개발 환경임을 나타내는 Node.js 환경 변수입니다. PORT: 3000 // 애플리케이션이 사용할 포트 번호입니다. }, env_production: { // 'pm2 start --env production' 명령어로 실행 시 적용될 환경 변수입니다. NODE_ENV: 'production', // 프로덕션 환경임을 나타냅니다. PORT: 3000 // 프로덕션 환경에서 사용할 포트입니다. }, // 로그 설정 log_file: './logs/combined.log', // 모든 로그(stdout + stderr)가 기록될 파일 경로입니다. out_file: './logs/out.log', // 표준 출력(console.log)이 기록될 파일 경로입니다. error_file: './logs/error.log', // 에러 출력(console.error)이 기록될 파일 경로입니다. log_date_format: 'YYYY-MM-DD HH:mm:ss Z', // 로그 파일에 기록될 시간 형식입니다. // 자동 재시작 설정 autorestart: true, // 애플리케이션이 종료될 경우 자동으로 재시작할지 여부입니다. (기본값: true) watch: false, // 파일 변경 감지 여부입니다. 개발 시에는 'true'로 설정할 수 있지만, 프로덕션에서는 성능 저하를 일으킬 수 있어 'false'가 권장됩니다. max_memory_restart: '1G', // 프로세스 메모리 사용량이 이 값을 초과하면 재시작합니다. 메모리 누수 방지에 유용합니다. // 환경 변수 파일 env_file: '.env' // '.env' 파일에서 환경 변수를 로드합니다. }] };
이 설정 파일을 사용하여 애플리케이션을 시작하려면 다음 명령어를 사용합니다:
pm2 start ecosystem.config.js # 기본 환경 변수(env)로 시작 pm2 start ecosystem.config.js --env production # 'env_production'에 정의된 환경 변수로 시작
PM2는 실행 중인 애플리케이션 프로세스를 효과적으로 제어하고 상태를 확인하는 다양한 명령어를 제공합니다.
실행 중인 애플리케이션을 중지, 재시작, 삭제하는 명령어입니다.
# 애플리케이션 중지: 'my-app'이라는 이름의 애플리케이션을 중지합니다. pm2 stop my-app # 애플리케이션 재시작: 'my-app' 애플리케이션을 재시작합니다. 코드 변경 후 적용할 때 유용합니다. pm2 restart my-app # 애플리케이션 삭제: 'my-app' 애플리케이션을 PM2 목록에서 제거하고 완전히 중지시킵니다. pm2 delete my-app # 모든 애플리케이션 중지: PM2가 관리하는 모든 애플리케이션을 중지합니다. pm2 stop all # 모든 애플리케이션 재시작: PM2가 관리하는 모든 애플리케이션을 재시작합니다. pm2 restart all
실행 중인 애플리케이션의 상태, 로그, 상세 정보를 확인하는 명령어입니다.
# 실행 중인 프로세스 목록: PM2가 관리하는 모든 애플리케이션의 간략한 상태(ID, 이름, 모드, 상태, CPU, 메모리 등)를 보여줍니다. pm2 list # 상세 정보 확인: 'my-app' 애플리케이션의 상세한 정보(환경 변수, 로그 경로, 재시작 횟수 등)를 출력합니다. pm2 show my-app # 로그 확인: 'my-app' 애플리케이션의 표준 출력 및 에러 로그를 실시간으로 스트리밍하여 보여줍니다. pm2 logs my-app # 실시간 로그 모니터링: 'my-app'의 로그를 실시간으로 확인하며, 최신 100줄을 보여줍니다. pm2 logs my-app --lines 100
PM2는 애플리케이션과 시스템의 상태를 시각적으로 모니터링할 수 있는 강력한 도구를 제공합니다.
PM2에는 터미널 기반의 실시간 모니터링 대시보드가 내장되어 있습니다.
# 실시간 모니터링 대시보드: PM2가 관리하는 모든 프로세스의 CPU, 메모리 사용량, 로그 등을 실시간으로 보여주는 대시보드를 실행합니다.
pm2 monit
애플리케이션의 성능 관련 정보를 확인하고 관리하는 명령어들입니다.
# CPU/메모리 사용량 확인: 'my-app' 애플리케이션의 CPU 및 메모리 사용량을 포함한 상세 정보를 확인합니다. (위 'pm2 show'와 중복되지만, 성능 관점에서 다시 언급) pm2 show my-app # 로그 파일 크기 확인 및 정리: 모든 애플리케이션의 로그 파일을 비웁니다. 로그 파일이 너무 커졌을 때 공간 확보에 유용합니다. pm2 flush # 웹 기반 메트릭 확인: PM2 Web UI를 통해 웹 브라우저에서 PM2가 관리하는 프로세스의 메트릭을 확인할 수 있습니다. pm2 web
PM2는 다양한 모듈을 설치하여 시스템 및 애플리케이션 메트릭을 확장할 수 있습니다.
# PM2 서버 모니터링 활성화: 서버의 CPU, 메모리, 디스크, 네트워크 등 시스템 자원 사용량을 모니터링하는 모듈을 설치합니다. pm2 install pm2-server-monit # 커스텀 메트릭 추가: 애플리케이션 특정 메트릭을 수집하고 PM2 대시보드에서 볼 수 있도록 하는 모듈을 설치합니다. pm2 install pm2-custom-metrics
PM2를 이용하여 시스템 재부팅 시 애플리케이션이 자동으로 시작되도록 설정하고, 배포 과정을 자동화할 수 있습니다.
서버가 재부팅될 때 PM2가 관리하는 애플리케이션들이 자동으로 다시 시작되도록 설정합니다.
# PM2 시작 스크립트 생성: 현재 운영체제(예: systemd, Upstart)에 맞는 PM2 시작 스크립트를 생성하고 등록합니다. 이 명령어를 실행하면 사용법이 안내됩니다. pm2 startup # 현재 실행 중인 앱들을 저장: 현재 PM2에 의해 관리되고 있는 모든 애플리케이션의 목록과 상태를 저장합니다. 'pm2 startup'으로 생성된 스크립트는 이 저장된 목록을 사용하여 재부팅 시 앱을 시작합니다. pm2 save # 저장된 앱들을 복원: 이전에 'pm2 save'로 저장된 애플리케이션 목록을 불러와 다시 실행합니다. pm2 resurrect
애플리케이션 배포 과정을 자동화하기 위한 간단한 쉘 스크립트 예시입니다. 이 스크립트는 새로운 코드를 가져오고, 의존성을 설치하며, PM2를 통해 애플리케이션을 재시작하는 과정을 자동화합니다.
#!/bin/bash # deploy.sh # 이 스크립트는 새로운 코드를 배포하고 애플리케이션을 재시작하는 과정을 자동화합니다. echo "🚀 배포 시작..." # 기존 프로세스 중지: 현재 실행 중인 'baduk-metaverse' 애플리케이션을 중지합니다. pm2 stop baduk-metaverse # 코드 업데이트: Git 저장소에서 최신 코드를 가져옵니다. (예: main 브랜치) git pull origin main # 의존성 설치: 'package.json'에 정의된 Node.js 모듈들을 새로 설치하거나 업데이트합니다. npm install # 프로덕션 환경으로 시작: 'ecosystem.config.js'에 정의된 'env_production' 환경으로 애플리케이션을 시작합니다. pm2 start ecosystem.config.js --env production # 상태 확인: 모든 PM2 애플리케이션의 현재 상태를 확인하여 배포가 성공적으로 이루어졌는지 검증합니다. pm2 list echo "✅ 배포 완료!"
PM2 사용 중 발생할 수 있는 일반적인 문제들과 그 해결 방법을 안내합니다.
애플리케이션이 너무 많은 메모리를 사용하거나 메모리 누수가 발생할 때 나타나는 문제입니다.
pm2 show
명령어를 통해 특정 애플리케이션의 현재 메모리 사용량을 확인합니다.# 메모리 사용량 확인
pm2 show my-app
ecosystem.config.js
또는 pm2 start
명령어에 max_memory_restart
옵션을 추가하여 특정 메모리 사용량을 초과하면 자동으로 재시작하도록 설정합니다.# 메모리 제한 설정: 애플리케이션이 1GB 메모리를 초과하면 자동으로 재시작합니다. pm2 start app.js --max-memory-restart 1G
애플리케이션 로그 파일이 과도하게 커져 디스크 공간을 많이 차지하는 문제입니다.
pm2 flush
명령어로 모든 애플리케이션의 로그 내용을 지웁니다.# 로그 파일 정리
pm2 flush
pm2-logrotate
모듈을 설치하여 로그 파일이 일정 크기가 되면 자동으로 압축하거나 삭제하도록 규칙을 설정합니다.# 로그 로테이션 설정: PM2 로그 로테이션 모듈을 설치합니다. pm2 install pm2-logrotate
애플리케이션이 반복적으로 충돌하여 PM2에 의해 자동으로 재시작되는 문제입니다.
pm2 list
에서 restarts
횟수가 지속적으로 증가합니다.pm2 show
명령어로 특정 애플리케이션의 재시작 횟수를 확인합니다.# 재시작 횟수 확인
pm2 show my-app
# 로그에서 에러 확인: 'my-app' 애플리케이션의 에러 로그만 확인합니다. pm2 logs my-app --err
애플리케이션이 이미 사용 중인 포트를 사용하려고 할 때 발생하는 문제입니다.
netstat
명령어를 사용하여 특정 포트를 사용 중인 프로세스를 확인합니다.# 사용 중인 포트 확인: '3000'번 포트를 사용 중인 프로세스를 확인합니다. netstat -tulpn | grep :3000
# 다른 포트로 실행: '3001'번 포트로 'app.js'를 시작합니다. pm2 start app.js -- --port 3001
PM2를 이용하여 Node.js 애플리케이션의 성능을 극대화하는 방법을 알아봅니다.
Node.js의 단일 스레드 모델 한계를 극복하기 위해 PM2의 클러스터 모드를 활용하는 방법입니다. ecosystem.config.js
에서 instances: 'max
와
exec_mode: 'cluster를 설정하는 것 외에, 애플리케이션 코드 자체에서 클러스터 모드를 지원하도록 구성할 수도 있습니다.
// server.js에서 클러스터 모드 지원: Node.js의 'cluster' 모듈을 직접 사용하여 마스터-워커 구조를 구현합니다. const cluster = require('cluster'); // Node.js 내장 'cluster' 모듈을 불러옵니다. const numCPUs = require('os').cpus().length; // 시스템의 CPU 코어 수를 가져옵니다. if (cluster.isMaster) { // 현재 프로세스가 마스터(부모) 프로세스인지 확인합니다. console.log(`마스터 프로세스 ${process.pid} 실행 중`); // 워커 프로세스 생성: CPU 코어 수만큼 워커(자식) 프로세스를 생성합니다. 각 워커는 애플리케이션의 독립적인 인스턴스가 됩니다. for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { // 워커 프로세스가 종료될 때 발생하는 이벤트를 감지합니다. console.log(`워커 ${worker.process.pid} 종료`); cluster.fork(); // 종료된 워커를 대체할 새로운 워커를 생성하여 고가용성을 유지합니다. }); } else { // 워커 프로세스에서 서버 실행: 현재 프로세스가 워커인 경우, 실제 Node.js 서버 애플리케이션을 실행합니다. require('./server.js'); // 예를 들어, Express 앱이 정의된 'server.js' 파일을 로드합니다. }
PM2를 사용할 경우, ecosystem.config.js
의 exec_mode: 'cluster
와
instances: 'max 설정을 통해 이 모든 것을 PM2가 자동으로 처리해주므로, 위와 같은 코드를 직접 작성할 필요는 없습니다. 하지만 Node.js의 클러스터 모드 동작 방식을 이해하는 데 도움이 됩니다.
Node.js 애플리케이션의 메모리 사용량을 주기적으로 관리하여 메모리 누수를 방지하고 안정성을 높이는 방법입니다.
// 주기적인 메모리 정리: Node.js의 가비지 컬렉션(GC)을 수동으로 트리거하여 사용되지 않는 메모리를 해제합니다. setInterval(() => { if (global.gc) { // 'global.gc'는 Node.js를 '--expose-gc' 플래그와 함께 실행했을 때만 사용 가능합니다. global.gc(); // 가비지 컬렉션을 명시적으로 실행합니다. console.log('🧹 가비지 컬렉션 실행'); } else { console.log('가비지 컬렉션은 --expose-gc 플래그가 필요합니다.'); } }, 60000); // 1분(60000 밀리초)마다 가비지 컬렉션을 시도합니다.
주의: global.gc()
는 Node.js를 –expose-gc
플래그와 함께 실행해야만 사용할 수 있습니다. 프로덕션 환경에서는 이 기능을 신중하게 사용해야 하며, 일반적으로 Node.js의 자동 가비지 컬렉션에 의존하는 것이 권장됩니다. PM2의 max_memory_restart
옵션이 더 안전하고 일반적인 메모리 관리 방법입니다.
PM2를 이용하여 더욱 복잡한 배포 시나리오나 운영 환경에 맞게 애플리케이션을 설정하는 방법을 알아봅니다.
PM2 클러스터 모드는 자체적인 로드 밸런싱을 제공하지만, 외부 로드 밸런서(예: Nginx)와 함께 사용할 경우 각 인스턴스를 특정 포트에 바인딩할 수 있습니다.
ecosystem.config.js
에서 instances
수를 지정하여 PM2가 자동으로 여러 인스턴스를 실행하고 요청을 분산하도록 합니다.# 로드 밸런서 설정: 'ecosystem.config.js'에 정의된 애플리케이션을 4개의 인스턴스로 실행하여 PM2가 로드 밸런싱을 처리하도록 합니다. pm2 start ecosystem.config.js -i 4
# 특정 포트로 바인딩: 각 PM2 인스턴스를 고유한 포트(3001, 3002 등)에서 실행하여 외부 로드 밸런서가 이들 포트로 요청을 전달할 수 있도록 합니다. pm2 start server.js --name "baduk-1" -- --port 3001 pm2 start server.js --name "baduk-2" -- --port 3002
ecosystem.config.js
파일 내에서 개발, 스테이징, 프로덕션 등 다양한 환경에 따라 다른 변수들을 설정하고 관리할 수 있습니다.
// ecosystem.config.js: 다양한 환경에 따른 설정 예시 module.exports = { apps: [{ name: 'baduk-metaverse', script: 'server.js', instances: 'max', env: { // 기본 환경 (예: 개발 환경) NODE_ENV: 'development', PORT: 3000 }, env_staging: { // 'pm2 start --env staging' 시 적용될 환경 NODE_ENV: 'staging', PORT: 3001 }, env_production: { // 'pm2 start --env production' 시 적용될 환경 NODE_ENV: 'production', PORT: 3000 } }] };
이 설정을 사용하면, 단일 설정 파일로 여러 환경에 맞는 애플리케이션을 쉽게 관리할 수 있습니다. 예를 들어, pm2 start ecosystem.config.js –env production
명령어를 실행하면 env_production
블록의 설정이 활성화됩니다.
애플리케이션이 정상적으로 작동하는지 외부 시스템이 확인할 수 있도록 헬스체크 엔드포인트를 구현하는 것은 매우 중요합니다. PM2는 직접적인 헬스체크 기능을 제공하지 않으므로, 애플리케이션 코드 내에서 구현해야 합니다.
// Express.js 기반의 헬스체크 엔드포인트 예시 // 이 코드는 애플리케이션이 정상적으로 응답하는지 확인할 수 있는 '/health' 경로를 만듭니다. app.get('/health', (req, res) => { res.status(200).json({ // HTTP 상태 코드 200 (OK)과 JSON 응답을 보냅니다. status: 'ok', // 애플리케이션 상태 timestamp: new Date().toISOString(), // 현재 시간 uptime: process.uptime() // 프로세스 실행 시간 (초 단위) }); });
이러한 헬스체크 엔드포인트는 로드 밸런서나 컨테이너 오케스트레이션 도구(예: Kubernetes)가 애플리케이션의 상태를 모니터링하고 비정상적인 인스턴스를 트래픽에서 제외하거나 재시작하는 데 활용됩니다.
PM2와 관련된 주요 기술 용어들을 간략히 설명합니다.
PM2와 관련된 추가 정보를 얻을 수 있는 문서들입니다.
— 이 페이지는 자동으로 생성되었습니다.