Linux에서 Nginx와 PM2를 사용해 Node.js 배포 — 실용적인 초보자 가이드
Source: Dev.to
위 링크에 있는 글 전체를 번역해 주시면 됩니다. 번역하고 싶은 본문을 제공해 주시겠어요?
(코드 블록, URL, 마크다운 구문 등은 그대로 유지하고, 본문만 한국어로 번역해 드리겠습니다.)
훅: 왜 이 스택이 중요한가
Node.js 애플리케이션을 구축하고 프로덕션 환경에서 안정적으로 실행하고 싶다면, node app.js와 행운을 빌기만으로는 부족합니다. Linux + Nginx + PM2를 사용하는 것은 실용적인 스택으로 다음을 제공합니다:
- 안정성 (Linux)
- 성능 및 SSL 종료 (Nginx)
- 모니터링이 포함된 자동 프로세스 관리 (PM2)
이 글에서는 그 이유와 실제 애플리케이션을 빠르게 배포하기 위한 간결하고 실용적인 방법을 안내합니다.
Context: 대부분의 개발자가 직면하는 문제
새로운 애플리케이션은 간단한 이유로 프로덕션에서 실패합니다: 프로세스가 충돌하고, 포트가 노출되며, SSL이 없고, 서버 재부팅 시 재시작을 설정한 사람이 없을 때 등. 예측 가능한 배포 패턴이 필요합니다:
- 충돌 및 재부팅 후에도 애플리케이션이 계속 실행되도록 유지
- 내부 포트를 공용 인터넷에서 숨김
- HTTPS, 정적 자산, 그리고 트래픽 급증을 처리
Linux VPS에서 Nginx + PM2는 무거운 오케스트레이션 없이 이 모든 문제를 해결합니다.
솔루션 개요
고수준 흐름은 다음과 같습니다:
- Nginx가 포트 80/443을 청취하고 내부 포트(예: 3000)에서 Node 프로세스로 프록시합니다.
- PM2가 실행되어 Node 프로세스를 모니터링하고, 실패 시 재시작하며, 재부팅 후에도 프로세스를 복구할 수 있습니다.
- PM2 ecosystem 파일이 프로세스 구성을 버전 관리합니다.
이는 표준이며 널리 지원되는 도구들로, Ubuntu 및 CentOS와 같은 일반적인 배포판에서 동작합니다.
시작하기 전 빠른 체크리스트
- Linux 서버를 프로비저닝합니다 (소규모 앱에는 1–2 GB RAM이면 충분합니다).
- 서버에 SSH로 접속하여 패키지를 업데이트합니다.
- Node.js (NodeSource 또는 nvm), Nginx, 그리고 PM2를 설치합니다.
- SSL을 발급하기 전에 DNS가 도메인을 서버로 가리키도록 합니다.
- 코드와 ecosystem 설정을 Git에 보관합니다.
Source: …
Implementation: essential steps (short and actionable)
-
Node.js 설치 (NodeSource 또는 nvm) 후 버전 확인:
node -v npm -v -
앱을 업로드하거나 클론하여 전용 폴더(예:
/home/youruser/my-app)에 배치하고 프로덕션 의존성을 설치:cd /home/youruser/my-app npm install --production -
PM2를 전역으로 설치하고 친숙한 이름으로 앱을 시작:
npm install -g pm2 pm2 start app.js --name my-app pm2 startup # init 스크립트 생성 pm2 save # 프로세스 목록 저장 -
Nginx 설치 후 Node 포트(예: 3000)로 프록시하는 서버 블록을 생성. 예시
/etc/nginx/sites-available/my-app:server { listen 80; server_name example.com www.example.com; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } # 선택 사항: 정적 자산을 직접 제공 # location /static/ { # alias /home/youruser/my-app/public/; # } }테스트 및 재로드:
sudo nginx -t sudo systemctl reload nginx -
Let’s Encrypt로 사이트 보안 강화:
sudo apt-get install certbot python3-certbot-nginx # Ubuntu 예시 sudo certbot --nginx -d example.com -d www.example.comcertbot 플러그인이 인증서를 발급하고 HTTPS를 자동으로 설정합니다.
Note: Node 포트를 공개 인터넷에 노출하지 마세요. Nginx가 들어오는 트래픽과 SSL을 처리하도록 합니다.
PM2: 반복 가능하게 만들기
앱과 환경 변수를 설명하기 위해 ecosystem.config.js (또는 .json) 파일을 생성합니다:
module.exports = {
apps: [
{
name: "my-app",
script: "./app.js",
instances: "max", // enable clustering
exec_mode: "cluster",
env: {
NODE_ENV: "development",
PORT: 3000
},
env_production: {
NODE_ENV: "production",
PORT: 3000
}
}
]
};
모든 것을 시작하려면:
pm2 start ecosystem.config.js --env production
pm2 save
베스트 프랙티스: 프로덕션 환경에서 watch: true를 사용하지 마세요; 대신 CI/CD를 통해 재시작을 트리거하세요.
Nginx: 리버스 프록시 기본 및 팁
-
프록시 대상:
http://127.0.0.1:3000(앱의 포트에 맞게 조정하세요). -
일반 헤더:
X-Forwarded-For,Host,X-Forwarded-Proto. -
nginx -t로 재로드하기 전에 설정을 테스트하세요. -
정적 자산에 대해 gzip을 활성화하고 적절한 캐시 헤더를 설정하세요.
-
기본 보안 헤더를 추가하세요:
add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; add_header X-XSS-Protection "1; mode=block"; -
여러 앱을 운영할 경우, 도메인별로 별도의 server 블록을 만들고 각각 자체 내부 포트를 가리키게 하세요.
보안, 모니터링 및 검증
-
방화벽: UFW(Ubuntu) 또는 firewalld(CentOS)를 활성화하고 SSH와 Nginx Full(포트 22, 80, 443)만 허용합니다.
sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw enable -
HTTPS: 자동 발급 및 갱신을 위해 Nginx 플러그인이 포함된 Certbot을 사용합니다.
-
로그 및 모니터링:
pm2 logs pm2 monit로그가 무제한으로 커지는 것을 방지하기 위해 로그 회전을 설치합니다:
pm2 install pm2-logrotate -
로드 테스트:
ab등 유사 도구로 간단히 테스트를 실행하고pm2 monit,top/htop, Nginx 로그를 확인합니다.
빠른 권장 사항
- Node를 비루트 사용자로 실행합니다.
- 비밀 정보를 절대 커밋하지 마세요; 환경 변수 또는 PM2
env블록을 사용합니다. - 정기적으로
npm audit을 실행하고 의존성을 최신 상태로 유지합니다.
어디서 더 배우고 도움을 받을 수 있나요
준비된 참고 자료와 자세한 설명을 보려면 전체 가이드를 확인하세요:
회사 및 추가 리소스:
결론
Node.js를 Linux에 Nginx와 PM2로 배포하면 Docker나 전체 오케스트레이션의 복잡성 없이도 신뢰할 수 있고 유지 보수가 쉬운 기반을 얻을 수 있습니다. 작게 시작하세요:
- Node + PM2를 실행합니다.
- 앞단에 Nginx를 배치합니다.
- HTTPS를 추가합니다.
- 나중에 ecosystem 파일과 CI로 자동화합니다.
이 패턴은 인디 프로젝트, MVP, 초기 단계 SaaS와 같은 대부분의 프로덕션 요구 사항을 충족합니다.