서버 운영
PM2로 Node.js 앱을 서버에서 안정적으로 돌리기
PM2를 그냥 쓰면 재부팅 후 앱이 안 뜨거나 로그가 디스크를 다 먹는 문제가 생긴다. 처음에 해두면 좋은 설정을 정리했다.
PM2는 npm start보다 편하긴 하지만, 기본값 그대로 쓰면 서버를 재부팅했을 때 앱이 안 올라오거나, 로그 파일이 수 기가씩 쌓이는 문제가 생긴다. 처음 세팅할 때 몇 가지를 잡아두면 이후가 편하다.
ecosystem.config.js로 설정 고정하기
pm2 start app.js 대신 설정 파일을 쓰면 환경변수, 인스턴스 수, 로그 경로를 한 곳에서 관리할 수 있다.
// ecosystem.config.js
module.exports = {
apps: [{
name: 'my-app',
script: './src/index.js',
instances: 1,
env: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: '/var/log/pm2/my-app-error.log',
out_file: '/var/log/pm2/my-app-out.log',
time: true
}]
};
time: true는 로그에 타임스탬프를 붙인다. 없으면 나중에 로그를 볼 때 언제 무슨 일이 생겼는지 알기가 힘들다.
재부팅 후 자동 시작 설정
이게 빠지면 서버를 껐다 켤 때마다 수동으로 앱을 올려야 한다.
pm2 start ecosystem.config.js
pm2 save # 현재 프로세스 목록 저장
pm2 startup # 출력된 명령을 복사해서 실행
pm2 startup을 실행하면 OS에 맞는 명령어(예: sudo env PATH=... pm2 startup systemd ...)를 출력해준다. 그걸 그대로 복사해서 실행해야 실제로 등록된다.
로그 rotate 설정
pm2-logrotate 모듈을 설치하지 않으면 로그가 계속 쌓인다. 몇 달 지나면 수십 GB가 되어 있을 수 있다.
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7
pm2 set pm2-logrotate:compress true
50MB가 넘으면 잘라내고, 7개까지만 보관한다. 운영 환경에서는 이 정도면 충분하다.
자주 쓰는 명령 정리
pm2 status # 앱 상태 한눈에 보기
pm2 logs my-app # 실시간 로그 확인
pm2 restart my-app # 재시작 (무중단 아님)
pm2 reload my-app # 무중단 재시작 (cluster 모드일 때)
pm2 monit # CPU/메모리 실시간 모니터
restart와 reload는 다르다. reload는 새 프로세스를 먼저 띄우고 구 프로세스를 내리기 때문에 cluster 모드(instances: 'max' 또는 숫자)일 때만 무중단 배포가 된다.
현재 상태 확인할 때
앱이 이상하게 동작한다 싶으면 pm2 status 먼저 보고, restart 횟수가 이상하게 많으면 에러 로그를 본다.
pm2 logs my-app --err --lines 50
에러 로그 없이 재시작이 반복된다면 메모리 초과(max_memory_restart 설정 가능)나 포트 충돌을 먼저 의심한다.