PM2 vs Coolify: 상황에 맞는 Node.js 배포 전략 선택하기
들어가며
Node.js 애플리케이션을 배포할 때, 어떤 도구를 선택해야 할지 고민이 되는 순간이 있습니다. "그냥 PM2 쓰면 되지 않나?"라고 생각하다가도, Coolify나 Docker 같은 컨테이너 기반 도구들이 눈에 들어오기 시작하면 선택이 어려워집니다.
돌이켜 생각해보면, 저도 처음에는 무조건 Docker가 좋다고 생각했습니다. 컨테이너 격리, 재현 가능한 환경, 요즘 트렌드... 하지만 실제로 여러 프로젝트를 운영하면서 "상황에 따라 최선의 선택이 다르다"는 것을 깨닫게 되었습니다.
이 글에서는 PM2와 Coolify를 비교하며, 각각 어떤 상황에서 더 적합한지 살펴보겠습니다.
PM2란 무엇인가
PM2(Process Manager 2)는 Node.js 전용 프로세스 관리자입니다. 애플리케이션을 백그라운드에서 실행하고, 크래시 시 자동 재시작하며, 로그 관리와 클러스터 모드를 지원합니다.
핵심은 단순함입니다. Docker처럼 복잡한 이미지 빌드 과정 없이, 명령어 몇 개로 프로덕션 환경을 구축할 수 있습니다.
# PM2로 앱 실행하기
pm2 start dist/main.js --name "backend"
pm2 status
pm2 logs backend
pm2 restart backend이게 전부입니다. 5개의 명령어만 알면 기본적인 운영이 가능합니다.
Coolify란 무엇인가
Coolify는 셀프 호스팅 PaaS(Platform as a Service)입니다. Heroku나 Vercel과 비슷한 경험을 자체 서버에서 제공하며, Docker 기반으로 애플리케이션을 관리합니다.
Git 저장소를 연결하면 자동으로 빌드하고 배포하며, Traefik을 통한 리버스 프록시와 Let's Encrypt SSL 인증서까지 자동으로 처리해줍니다.
# Coolify 배포 흐름
1. Git push
2. Coolify가 webhook으로 감지
3. Dockerfile 기반 이미지 빌드
4. 컨테이너 배포 + 헬스체크
5. Traefik이 트래픽 라우팅핵심 차이점 비교
복잡도와 학습 곡선
PM2는 Node.js 개발자라면 30분 안에 익힐 수 있습니다. 반면 Coolify는 Docker, 컨테이너 네트워킹, 리버스 프록시에 대한 기본 이해가 필요합니다.
격리와 재현성
Coolify(Docker)의 가장 큰 장점은 완전한 격리입니다. 컨테이너 내부에 필요한 모든 것이 포함되어 있어, "내 컴퓨터에서는 되는데"라는 문제가 발생하지 않습니다.
PM2는 호스트 OS의 Node.js를 공유합니다. 여러 프로젝트가 같은 서버에서 돌아갈 때 Node.js 버전 충돌이 발생할 수 있습니다. 물론 nvm으로 해결할 수 있지만, 추가적인 관리 포인트가 생깁니다.
# Docker 방식
Host Server
└── Docker Engine
├── Container A (Node 18)
└── Container B (Node 20)
# PM2 방식
Host Server (Node 20)
├── PM2
│ ├── Process A
│ └── Process B
└── (Node 버전 공유)리소스 사용량
Docker는 오버헤드가 있습니다. 컨테이너 런타임, 이미지 레이어, 네트워크 설정 등으로 최소 200MB 이상의 추가 메모리가 필요합니다.
PM2는 프로세스 관리자일 뿐이므로 오버헤드가 거의 없습니다. 저사양 서버나 비용에 민감한 환경에서는 이 차이가 의미 있습니다.
배포 속도
Coolify는 매번 Docker 이미지를 빌드합니다. Next.js처럼 빌드 시간이 긴 프로젝트는 배포에 몇 분이 소요될 수 있습니다.
# Coolify 배포
git pull
docker-compose build # 이미지 빌드 (시간 소요)
docker-compose up -d
# PM2 배포
git pull
pnpm install
pnpm build
pm2 reload backend # 거의 즉시PM2의 reload 명령은 무중단 재시작을 지원합니다. 새 프로세스를 먼저 띄우고 기존 프로세스를 종료하는 방식으로 다운타임 없이 배포할 수 있습니다.
실제 운영에서의 차이
헬스체크와 자동 복구
Coolify는 Docker 헬스체크와 Traefik의 조합으로 정교한 트래픽 관리가 가능합니다. 헬스체크 실패 시 자동으로 컨테이너를 재시작하고, 로드밸런서에서 제외합니다.
# Dockerfile 헬스체크 설정
HEALTHCHECK --interval=10s --timeout=3s --start-period=30s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1PM2도 자동 재시작을 지원하지만, 단순히 프로세스 크래시에만 반응합니다. HTTP 응답 기반의 헬스체크를 원한다면 별도의 모니터링 도구가 필요합니다.
// ecosystem.config.js
module.exports = {
apps: [{
name: 'backend',
script: 'dist/main.js',
instances: 2,
exec_mode: 'cluster',
max_memory_restart: '500M', // 메모리 초과 시 재시작
}]
};롤백
Coolify는 이전 이미지로 즉시 롤백할 수 있습니다. 이미지가 레지스트리에 저장되어 있으므로, 문제가 발생하면 이전 버전을 바로 배포할 수 있습니다.
PM2 환경에서는 Git을 활용한 롤백이 일반적입니다. git checkout으로 이전 커밋으로 돌아간 후 다시 빌드하고 재시작해야 합니다.
멀티 서비스 관리
Coolify는 여러 서비스를 독립적으로 관리하기 좋습니다. 각 서비스가 별도의 컨테이너로 분리되어 있고, 웹 UI에서 한눈에 상태를 확인할 수 있습니다.
PM2도 여러 앱을 관리할 수 있지만, 모든 프로세스가 같은 호스트에서 돌아가므로 한 앱의 문제가 다른 앱에 영향을 줄 수 있습니다.
어떤 상황에 무엇을 선택할까
PM2가 더 적합한 경우
저사양 서버/비용 절감
월 5만 원 이하의 VPS에서는 Docker 오버헤드가 부담스러울 수 있습니다. PM2는 최소한의 리소스로 안정적인 운영이 가능합니다.
빠른 프로토타이핑
MVP를 빠르게 검증해야 할 때, Dockerfile 작성하고 이미지 빌드하는 시간이 아깝습니다. PM2로 바로 띄우고 피드백을 받는 게 효율적입니다.
단일 Node.js 앱
복잡한 마이크로서비스가 아니라 단일 앱이라면, 컨테이너 격리의 이점이 크지 않습니다.
Coolify가 더 적합한 경우
여러 서비스를 운영하는 경우
블로그 API, 프론트엔드, 어드민, 스크래퍼 등 여러 서비스를 한 서버에서 운영한다면, Coolify의 통합 관리 기능이 유용합니다.
CI/CD 자동화가 중요한 경우
Git push만으로 자동 배포되는 환경을 원한다면, Coolify가 이미 모든 것을 갖추고 있습니다. PM2로 같은 환경을 만들려면 GitHub Actions 등을 별도로 구성해야 합니다.
팀 협업 환경
여러 명이 배포하고 모니터링하는 환경에서는 Coolify의 웹 UI가 편리합니다. 터미널 접속 없이도 상태 확인과 배포가 가능합니다.
환경 재현성이 중요한 경우
개발, 스테이징, 프로덕션 환경이 정확히 같아야 한다면 Docker 기반이 맞습니다.
하이브리드 접근법
꼭 하나만 선택할 필요는 없습니다. 저는 상황에 따라 다르게 사용합니다.
# 내 프로젝트 운영 현황
개인 블로그 (kichang.info) → Coolify (자동 배포, 여러 서비스)
로컬 개발 서버 → PM2 (빠른 재시작)중요한 것은 도구 자체가 아니라, 프로젝트의 요구사항과 운영 환경에 맞는 선택입니다.
마치며
PM2와 Coolify 모두 훌륭한 도구입니다. 다만, "모든 상황에 최고인 도구"는 없다는 생각이 듭니다.
PM2는 단순함과 가벼움이 장점입니다. Docker나 컨테이너에 익숙하지 않은 환경에서, 빠르게 안정적인 운영 환경을 구축할 수 있습니다.
Coolify는 현대적인 배포 경험을 제공합니다. 자동화, 격리, 확장성이 중요하다면 투자할 가치가 있습니다.
결국, 프로젝트의 규모, 팀의 역량, 클라이언트의 요구사항을 고려해서 선택하면 됩니다. 저도 여전히 두 가지를 병행하며 상황에 맞게 사용하고 있습니다.
관련 글
Coolify 설치 가이드: 우분투 서버에 나만의 PaaS 환경 구축하기
우분투 서버에 오픈소스 PaaS Coolify를 설치하여 나만의 앱 배포 환경을 구축하는 방법을 알아보세요. Docker 기반의 자동화된 배포로 개발 효율성을 극대화하고 비용을 절감할 수 있습니다.
작은 서비스에도 모니터링이 필요한 이유 - NestJS + Prometheus + Grafana Cloud 구축기
작은 서비스도 리소스 제약 때문에 모니터링이 필수입니다. NestJS에 Prometheus와 Grafana Cloud를 연동하여 효율적인 리소스 관리 시스템을 구축하는 방법을 알아보세요.
Liveness와 Readiness: 컨테이너 헬스체크의 두 가지 관점
Docker나 Kubernetes 환경에서 헬스체크를 구현할 때 Liveness와 Readiness의 차이를 이해하고, NestJS Backend와 Next.js Web에서 실제로 구현한 경험을 정리했습니다.