Windows server에서 Node.js 기반 API 서버 구동 - waegari/waegari.github.io GitHub Wiki
이 문서에서는 Windows Server 환경에서 NodeJS 기반 API 서버를 nginx, pm2를 통해 구동하고, GitHub Actions을 활용하여 자동 배포하는 시스템을 구축하는 방법을 설명합니다.
- Windows Server (운영체제)
- Node
-
nginx
- 고성능・저메모리 웹서버 구축
- 리버스 프록시 기능을 통해 보안 강화
-
PM2 (프로세스 관리 도구)
- pm2로 node.js 프로세스를 관리
- 자동 로드 밸런싱
- 무중단 배포
-
win-acme
- ssl 인증서 무료 발급 및 자동 갱신
- GitHub Actions self-hosted runner
- 자동 배포
D:\프로젝트 루트\
├── dist\
├── src\
├── ecosystem.config.js # pm2 관련 설정
├── package.json # nestJS 관련 설정
└── ...
D:\actions-runner\ # Github Actions
D:\배포 관련 설정\
├── deploy.ps1 # Github Actions에 의해 실행될 PowerShell 스크립트
└── ...
D:\pm2-resurrect.bat # pm2 resurrect 명령어
- 오픈소스 웹서버 애플리케이션
- 경량 & 고성능 지향
- HTTP 서버, 리버스 프록시, 로드밸런싱 등 기능
- 설치
- nginx 다운로드 페이지에서 windows용 nginx를 다운로드
- 원하는 경로에서 압축 풀기
- nginx.conf 설정
- 설정이 완료되면
nginx.exe
를 실행(수정 후에는 반드시 nginx 종료 후 재실행) - nginx를 windows 서비스로 등록
http {
include mime.types;
default_type application/octet-stream;
# 로그 포맷 설정
log_format custom '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "auth: " "$http_authorization"';
access_log logs/access.log custom;
sendfile on;
keepalive_timeout 65;
# http(포트번호: 80) 요청은 https로 리다이렉션
server {
listen 80;
server_name 도메인.com www.도메인.com;
return 301 https://$host$request_uri
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# https
server {
listen 443 ssl;
server_name 도메인.com www.도메인.com;
ssl_certificate 인증서/파일/경로/인증서.pem;
ssl_certificate_key 인증서/파일/경로/키.pem;
# www 없는 도메인을 www가 있는 도메인으로 리다이렉트
if ($host = "도메인.com") {
return 301 https://www.도메인.com$request_uri;
}
location /경로(예: api)/ {
proxy_pass http://localhost:API서버_포트번호;
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;
# CORS 헤더
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
}
location /api2/ {
proxy_pass http://localhost:IIS_API서버_2_포트번호;
proxy_http_version 1.1;
proxy_set_header Host $proxy_host; # 중요! proxy_pass의 호스트를 사용(IIS_API서버_2_포트번호)
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
# CORS 헤더
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# 정적 파일 serve
location / {
root ./관리자페이지_html_파일_등_경로;
index index.html;
try_files $uri $uri/ /index.html;
}
}
}
-
시스템 재부팅 시에도 별도 조치 없이 웹서버가 자동 실행되도록 NGINX를 windows 서비스로 등록.
-
NSSM(Non-Sucking Service Manager) 활용
-
- NSSM 다운로드 후 압축 해제
- PowerShell 또는 CMD에서 nssm이 위치한 경로로 이동 후 다음 명령어 실행:
nssm install nginx
- GUI 창이 뜨면:
-
Application Path:
nginx_설치_경로\nginx.exe
-
Startup directory:
nginx_설치_경로
-
Service name:
nginx
- [Install service] 클릭 → 성공 메시지 확인
-
Application Path:
-
-
services.msc
를 실행해 목록에nginx
가 있는지 확인 - 재부팅 후에도 자동으로 nginx가 실행됨
-
- 클러스터 모드를 활용하면 싱글 스레드 방식인 Node.js를 다수 CPU에서 동작하도록 할 수 있음
- autorestart: 오류 발생 시 재시작
- API 서버 코드 변경 후 서버 재시작이 필요할 때 무중단 배포가 가능
-
ecosystem.config.js
설정module.exports = { apps: [ { name: '프로세스_이름', script: 'dist/main.js', instances: 0, exec_mode: 'cluster', autorestart: true, watch: false, env: { // (.env 관련 설정 등) }, }, ], };
작업 스케줄러를 사용해 PM2를 시스템 종료 이전 상태로 자동 복원 (Linux에서는 systemd 같은 init 시스템 사용)
-
- 먼저 애플리케이션을
pm2 start ecosystem.config.js
등으로 실행한 뒤, 다음 명령어로 현재 상태 저장:pm2 save
- 배포 관련 스크립트에도
pm2 save
명령어를 추가
- 먼저 애플리케이션을
-
-
경로 예시:
D:\pm2-resurrect.bat
⚠️ 환경 변수 설정: Windows에서는 PM_HOME을 pm2가 설치된 경로로 설정해야 함(기본 경로는\etc
로, Linux용)- 오류 발생 시 echo 명령어 등으로 log 파일 저장해 문제의 원인을 확인
- 스크립트 예:
@echo off set PM2_HOME=C:\Users\Administrator\.pm2 cd C:\Users\Administrator echo %DATE% %TIME% running pm2 resurrect >> pm2-resurrect.log call pm2 resurrect >> pm2-resurrect.log 2>&1
-
경로 예시:
-
-
작업 스케줄러 (taskschd.msc)
실행 - 새 작업 만들기:
-
이름 예:
PM2 Auto Start
- 트리거: 컴퓨터 시작 시(단, 지연 시간 30~60초 추천: Windows 환경에서는 하드웨어 성능에 따라 '즉시 실행' 설정 시 작업 스케줄러가 정상 동작하지 않을 가능성 있음.)
-
동작:
- 프로그램/스크립트:
D:\pm2-resurrect.bat
- 시작 위치:
C:\Users\Administrator
(pm2가 설치된 경로)
- 프로그램/스크립트:
-
일반 설정:
- "사용자의 로그온 여부와 관계없이 실행"
- "가장 높은 권한으로 실행" 체크
-
-
-
pm2 list
명령으로 서버 재부팅 후에도 프로세스가 유지되는지 확인
-
- GitHub Actions Runner를 통해 API 서버에 최신 코드를 자동 배포하는 시스템 구축
- 반복적이고 비효율적인 수동 배포 작업을 없앰
-
git push
, pull request 등이 트리거가 됨
- repository owner로서 로그인 > Settings > Actions > Runners > "New self-hosted runner"
- OS: Windows, Architecture: x64 선택
- 관리자 권한 powershell에서 가이드에 따라 아래 명령어 실행:
-
단, 아래 스크립트는 2025.4.14. 기준. github에서 제공하는 가이드를 참고하세요(
New Self-hosted runner
버튼을 누르면 나타남)# 1. Create a folder under the drive root mkdir D:\actions-runner && cd D:\actions-runner # Download the latest runner package Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v2.323.0/actions-runner-win-x64-2.323.0.zip -OutFile actions-runner-win-x64-2.323.0.zip # Optional: Validate the hash if((Get-FileHash -Path actions-runner-win-x64-2.323.0.zip -Algorithm SHA256).Hash.ToUpper() -ne '해시 문자열'.ToUpper()){ throw 'Computed checksum did not match' } # Extract the installer Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD/actions-runner-win-x64-2.323.0.zip", "$PWD") # 2. 등록 # Create the runner and start the configuration experience ./config.cmd --url https://github.com/your-org/your-repo --token <발급된_토큰> # !!!이후 등록 절차에 따라 windows 서비스로 등록할 때 반드시 Administrator 등 관리자 계정으로 등록할 것!!!
- 등록 여부 확인:
- Github에서 Settings > Acrions > Runners
- Runner 목록 확인
- 추가한 Runner의 Status가 'Idle'이면 등록 성공
-
{디바이스 이름}\Administrator
로 등록 시 "서비스로 로그온 허용" 권한 필요 (secpol.msc
에서 설정)- 해당 계정이 "서비스로 로그온 허용" 정책에 포함되어 있어야 함
- 설정 방법
-
secpol.msc
(로컬 보안 정책) 실행 - 로컬 정책 → 사용자 권한 할당 클릭
- 서비스로 로그온 항목 더블클릭
-
{디바이스 이름}\Administrator
가 목록에 없다면 추가 - powershell에서
net localgroup Administrators
입력해 계정이 로컬 관리자 그룹에 포함됐는지 확인
-
- 또는 run.cmd 수동 실행 + 작업 스케줄러 사용 가능(비추천)
-
경로 예:
D:\deploy\deploy.ps1
$projectPath = "D:\nodejs\your-api" Write-Host "✅ 자동 배포 시작" cd $projectPath git fetch origin git reset --hard origin/main npm ci npm run build pm2 restart ecosystem.config.js pm2 save Write-Host "🚀 배포 완료"
프로젝트_루트/.github/workflows/deploy.yml
- 아래 workflow에는 배포 성공/실패 여부를 메일로 전송하는 작업이 포함되어 있음(
-name: Send success email
이하)- 아래 코드를 사용하여 메일 전송 작업 추가 시 Github repository secrets 설정 필요:
- Github Settings > Secrets and variables > Actions > Secrets 탭에서
New repository secret
버튼을 눌러 추가- e.g.
SMTP_ADDRESS
에smtp.gmail.com
할당
- e.g.
- Github Settings > Secrets and variables > Actions > Secrets 탭에서
name: Deploy to Windows Server on: push: branches: - main jobs: deploy: runs-on: self-hosted steps: - name: Run deploy script shell: powershell run: | powershell.exe -ExecutionPolicy Bypass -File "deploy_스크립트_파일_경로\deploy.ps1" - name: Send success email if: success() uses: dawidd6/action-send-mail@v3 with: server_address: ${{ secrets.SMTP_ADDRESS }} server_port: ${{ secrets.SMTP_PORT }} secure: true username: ${{ secrets.SMTP_USER }} password: ${{ secrets.SMTP_PASS }} subject: "(서버 이름) API 서버 배포 성공" to: ${{ secrets.DEV_EMAILS }} from: GitHub Actions <${{ secrets.SMTP_USER }}> body: | ✅ 배포가 성공적으로 완료되었습니다. - 브랜치: ${{ github.ref_name }} - 커밋: ${{ github.event.head_commit.message }} - 작성자: ${{ github.event.head_commit.author.name }} - 시간: ${{ github.event.head_commit.timestamp }} - name: Send failure email if: failure() uses: dawidd6/action-send-mail@v3 with: server_address: ${{ secrets.SMTP_ADDRESS }} server_port: ${{ secrets.SMTP_PORT }} secure: true username: ${{ secrets.SMTP_USER }} password: ${{ secrets.SMTP_PASS }} subject: "(서버 이름) API 서버 배포 실패" to: ${{ secrets.DEV_EMAILS }} from: GitHub Actions <${{ secrets.SMTP_USER }}> body: | ❌ 배포에 실패했습니다. - 브랜치: ${{ github.ref_name }} - 커밋: ${{ github.event.head_commit.message }} - 작성자: ${{ github.event.head_commit.author.name }} - 시간: ${{ github.event.head_commit.timestamp }}
- 아래 코드를 사용하여 메일 전송 작업 추가 시 Github repository secrets 설정 필요:
git add .
git commit -m "🚀 자동 배포 테스트"
git push origin main
- GitHub Actions → Actions 탭 →
✅ succeeded
- 서버에서
pm2 list
로 Node.js 프로세스가 정상 동작하는지 확인 - API 호출 결과 비교, 버전 번호 확인 등을 통해 새 코드가 반영됐는지 확인
이상으로 Windows Server 환경에서 Node.js 기반 API 서버 구축 및 자동 배포 시스템 구축 방법에 대한 설명을 마칩니다. 이 문서의 내용을 따라 설정하면 안정적이고 보안이 강화된 서버 환경을 구축할 수 있습니다.