Node.js는 서버 측 및 네트워킹 애플리케이션을 구축하기 위한 오픈 소스 JavaScript 런타임 환경입니다. 이 플랫폼은 Linux, macOS, FreeBSD 및 Windows에서 실행됩니다. Node.js 애플리케이션을 명령 줄에서 실행할 수 있지만, 이 자습서에서는 서비스로 실행하는 데 초점을 맞출 것입니다. 이는 부팅이나 실패 시에 재시작되며 프로덕션 환경에서 사용할 수 있습니다.
이 자습서에서는 단일 Rocky Linux 9 서버에서 프로덕션에 준비된 Node.js 환경을 설정합니다. 이 서버는 PM2에 의해 관리되는 Node.js 애플리케이션을 실행하고 Nginx 역방향 프록시를 통해 애플리케이션에 안전한 액세스를 제공합니다. Nginx 서버는 Let’s Encrypt가 제공하는 무료 인증서를 사용하여 HTTPS를 제공할 것입니다.
전제 조건
이 안내서는 다음을 가정합니다:
- A Rocky Linux 9 server setup, as described in the initial server setup guide for Rocky Linux 9. You should have a non-root user with sudo privileges and an active firewall.
- A domain name pointed at your server’s public IP. This tutorial will use the domain name example.com throughout.
- Nginx가 설치되어 있으며 Rocky Linux 9에 Nginx 설치 방법에서 다루었습니다.
- Nginx가 Let’s Encrypt 인증서를 사용하여 SSL로 구성되었습니다. Rocky Linux 9에서 Let’s Encrypt로 Nginx 보안 설정하는 방법을 통해 프로세스를 안내받을 수 있습니다.
- 서버에 Node.js가 설치되었습니다. Rocky Linux 9에 Node.js 설치하는 방법
필수 작업을 완료하면 서버가 https://example.com/
에서 도메인의 기본 플레이스홀더 페이지를 제공합니다.
단계 1 — Node.js 애플리케이션 생성
Hello World 애플리케이션을 작성해 보겠습니다. 이 예제 애플리케이션은 HTTP 요청에 “Hello World”를 반환합니다. 이 샘플 애플리케이션을 사용하여 Node.js를 시작하고 실행하는 데 도움이 됩니다. 자체 애플리케이션으로 바꿀 수 있습니다. 단지 애플리케이션이 적절한 IP 주소 및 포트에서 수신 대기하도록 수정하십시오.
Rocky Linux 9에 기본으로 제공되는 텍스트 편집기는 vi
입니다. vi
는 매우 강력한 텍스트 편집기이지만 사용 경험이 부족한 사용자에게는 다소 어려울 수 있습니다. Rocky Linux 9 서버의 구성 파일을 편집하는 데 더 사용자 친화적인 편집기인 nano
와 같은 편집기를 설치하면 도움이 될 수 있습니다.
- sudo dnf install nano
이제 nano
또는 선호하는 텍스트 편집기를 사용하여 hello.js
라는 샘플 애플리케이션을 만들어 보세요:
- nano hello.js
다음 코드를 파일에 삽입하세요:
const http = require('http');
const hostname = 'localhost';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World!\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
파일을 저장하고 편집기를 종료하세요. nano
를 사용하는 경우 Ctrl+X
를 누르고, 나오라고 하면 Y
를 입력한 후 Enter 키를 누르세요.
이 Node.js 애플리케이션은 지정된 주소(localhost
)와 포트(3000
)에서 대기하며, 200
HTTP 성공 코드로 “Hello World!”를 반환합니다. localhost
에서 대기하고 있기 때문에 원격 클라이언트는 애플리케이션에 연결할 수 없습니다.
애플리케이션을 테스트하려면 다음을 입력하세요:
- node hello.js
다음과 같은 출력이 표시됩니다:
OutputServer running at http://localhost:3000/
참고: 이 방법으로 Node.js 애플리케이션을 실행하면 애플리케이션이 CTRL+C
를 눌러 종료될 때까지 추가 명령을 차단합니다.
애플리케이션을 테스트하려면 서버에서 다른 터미널 세션을 열고 curl
을 사용하여 localhost
에 연결하세요:
- curl http://localhost:3000
다음 출력이 표시되면 애플리케이션이 올바르게 작동하고 올바른 주소와 포트에서 대기 중입니다:
OutputHello World!
예상한 출력이 표시되지 않으면 Node.js 애플리케이션이 실행되고 올바른 주소와 포트에서 대기하도록 구성되어 있는지 확인하세요.
작동하는 것을 확인한 후 (아직 종료하지 않은 경우) CTRL+C
를 눌러 애플리케이션을 종료하세요.
단계 2 — PM2 설치
이제 PM2를 설치해 보겠습니다. PM2는 Node.js 애플리케이션의 프로세스 관리자로, 애플리케이션을 백그라운드에서 서비스로 실행할 수 있게 해줍니다.
서버에 PM2의 최신 버전을 설치하려면 npm
을 사용하십시오:
- sudo npm install pm2@latest -g
-g
옵션은 npm
이 모듈을 전역적으로 설치하도록 지시하여 시스템 전역에서 사용할 수 있게 합니다.
먼저 백그라운드에서 응용 프로그램인 hello.js
를 실행하는 pm2 start
명령을 사용해 보겠습니다:
- pm2 start hello.js
이렇게 하면 응용 프로그램이 PM2의 프로세스 목록에 추가되며, 각 응용 프로그램을 시작할 때마다 출력됩니다:
Output...
[PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /home/sammy/hello.js in fork_mode (1 instance)
[PM2] Done.
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
위에서 언급한대로 PM2는 파일 이름에서 .js
확장자를 제외한 것을 기반으로 자동으로 App name
을 할당하고 PM2 id
를 지정합니다. PM2는 또한 프로세스의 PID
및 현재 상태, 메모리 사용량 등 다른 정보를 유지 관리합니다.
PM2에서 실행 중인 애플리케이션은 애플리케이션이 충돌하거나 종료되면 자동으로 다시 시작됩니다. 그러나 startup
하위 명령을 사용하여 시스템 부팅 시 애플리케이션을 시작하도록 추가 단계를 수행할 수 있습니다. 이 하위 명령은 PM2와 그 관리 프로세스를 서버 부팅 시 시작하는 시작 스크립트를 생성하고 구성합니다:
- pm2 startup systemd
Output…
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
제공된 명령을 복사하여 실행하십시오 (이는 Node.js 도구를 sudo
로 실행할 때 권한 문제를 피하기 위함입니다).
- sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output…
[ 'systemctl enable pm2-sammy' ]
[PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service
[PM2] Making script booting at startup...
[PM2] [-] Executing: systemctl enable pm2-sammy...
Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service.
[PM2] [v] Command successfully executed.
+---------------------------------------+
[PM2] Freeze a process list on reboot via:
$ pm2 save
[PM2] Remove init script via:
$ pm2 unstartup systemd
지금은 방금 생성된 시스템 서비스를 Rocky Linux의 SELinux 보안 시스템과 호환되도록 편집해야 합니다. nano
또는 선호하는 텍스트 편집기를 사용하여 /etc/systemd/system/pm2-sammy.service
파일을 엽니다:
- sudo nano /etc/systemd/system/pm2-sammy.service
구성 파일의 [Service]
블록에서 PIDFile
설정의 내용을 아래 강조된 대로 /run/pm2.pid
로 대체하고 다른 강조된 Environment
라인을 추가합니다:
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target
[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid
ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill
[Install]
파일을 저장하고 닫습니다. 이제 부팅 시 사용자에 대해 pm2
를 실행하는 systemd unit을 만들었습니다. 이 pm2
인스턴스는 다시 hello.js
를 실행합니다.
systemctl
로 서비스를 시작하세요:
- sudo systemctl start pm2-sammy
systemd unit의 상태를 확인하세요:
- systemctl status pm2-sammy
systemd에 대한 자세한 개요는 Systemd Essentials: Working with Services, Units, and the Journal를 참조하세요.
우리가 다룬 내용 외에도 PM2는 응용 프로그램을 관리하거나 정보를 조회할 수 있는 많은 하위 명령을 제공합니다.
이 명령을 사용하여 응용 프로그램을 중지하세요 (PM2 App name
또는 id
지정):
- pm2 stop app_name_or_id
응용 프로그램을 다시 시작하세요:
- pm2 restart app_name_or_id
현재 PM2에서 관리하는 응용 프로그램 목록을 나열하세요:
- pm2 list
특정 응용 프로그램에 대한 정보를 가져오려면 App name
을 사용하세요:
- pm2 info app_name
PM2 프로세스 모니터는 monit
하위 명령어로 끌어올릴 수 있습니다. 이는 응용 프로그램 상태, CPU 및 메모리 사용량을 표시합니다.
- pm2 monit
인수 없이 pm2
를 실행하면 도움말 페이지와 예제 사용법이 표시됩니다.
Step 3 — 엔진엑스를 역방향 프록시 서버로 설정하기
응용 프로그램이 실행되고 localhost
에서 수신 대기 중이지만 사용자가 액세스할 수 있는 방법을 설정해야 합니다. 이를 위해 엔진엑스 웹 서버를 역방향 프록시로 설정하겠습니다.
사전 필수 자습서에서 엔진엑스 구성을 /etc/nginx/conf.d/your_domain.conf
파일에 설정했습니다. 이 파일을 편집하십시오:
- sudo nano /etc/nginx/conf.d/your_domain.conf
server
블록 내에 기존 location /
블록이 있어야 합니다. 해당 블록의 내용을 다음 구성으로 대체하십시오. 응용 프로그램이 다른 포트에서 수신 대기하도록 설정된 경우 강조된 부분을 올바른 포트 번호로 업데이트하십시오:
server {
...
location / {
proxy_pass http://localhost:3000;
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;
}
...
}
이 설정은 서버를 루트에 대한 요청에 응답하도록 구성합니다. 서버가 your_domain
에서 사용 가능한 경우, 웹 브라우저를 통해 https://your_domain/
에 액세스하면 localhost
의 포트 3000
에서 수신 대기하는 hello.js
에 요청이 전송됩니다.
동일한 서버 블록에 추가적인 location
블록을 추가하여 동일한 서버에 있는 다른 응용 프로그램에 액세스할 수 있습니다. 예를 들어, 다른 Node.js 응용 프로그램을 포트 3001
에서 실행 중인 경우 다음 위치 블록을 추가하여 https://your_domain/app2
를 통해 해당 응용 프로그램에 액세스할 수 있습니다:
server {
...
location /app2 {
proxy_pass http://localhost:3001;
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;
}
...
}
응용 프로그램의 위치 블록을 추가한 후 파일을 저장하고 편집기를 종료합니다.
다음을 입력하여 구문 오류를 도입하지 않았는지 확인합니다:
- sudo nginx -t
Nginx를 다시 시작합니다:
- sudo systemctl restart nginx
Node.js 응용 프로그램이 실행되고 응용 프로그램 및 Nginx 구성이 올바른 경우 이제 Nginx 역방향 프록시를 통해 응용 프로그램에 액세스할 수 있어야 합니다. 서버의 URL(공개 IP 주소 또는 도메인 이름)에 액세스하여 확인해보세요.
결론
축하합니다! 이제 Rocky Linux 9 서버에서 Nginx 역방향 프록시 뒤에서 Node.js 응용 프로그램이 실행 중입니다. 이 역방향 프록시 설정은 공유하려는 다른 응용 프로그램 또는 정적 웹 콘텐츠에 사용자 액세스를 제공할 수 있는 유연성이 있습니다.
다음으로, Docker로 Node.js 애플리케이션을 빌드하는 방법을 살펴볼 수 있습니다.