웹사이트 검색

Ubuntu 18.04에서 프로덕션용 Node.js 애플리케이션을 설정하는 방법


소개

Node.js는 서버 측 및 네트워킹 애플리케이션을 구축하기 위한 오픈 소스 JavaScript 런타임 환경입니다. 플랫폼은 Linux, macOS, FreeBSD 및 Windows에서 실행됩니다. 명령줄에서 Node.js 애플리케이션을 실행할 수 있지만 이 자습서에서는 애플리케이션을 서비스로 실행하는 데 중점을 둡니다. 이는 재부팅 또는 실패 시 다시 시작되며 프로덕션 환경에서 사용하기에 안전함을 의미합니다.

이 튜토리얼에서는 단일 Ubuntu 18.04 서버에 프로덕션 준비가 된 Node.js 환경을 설정합니다. 이 서버는 Let’s Encrypt에서 관리하는 Node.js 애플리케이션을 실행합니다.

전제 조건

이 가이드에서는 다음이 있다고 가정합니다.

  • Ubuntu 18.04의 초기 서버 설정 가이드에 설명된 대로 Ubuntu 18.04 서버 설정. sudo 권한과 활성 방화벽이 있는 루트가 아닌 사용자가 있어야 합니다.
  • 전체 example.com.
  • Ubuntu 18.04에 Nginx를 설치하는 방법에 설명된 대로 Nginx가 설치되었습니다.
  • Let’s Encrypt 인증서를 사용하여 SSL로 구성된 Nginx. Ubuntu 18.04에서 Let's Encrypt로 Nginx를 보호하는 방법이 프로세스를 안내합니다.

전제 조건을 완료하면 https://example.com/에서 도메인의 기본 자리 표시자 페이지를 제공하는 서버를 갖게 됩니다.

1단계 — Node.js 설치

NodeSource 패키지 아카이브를 사용하여 Node.js의 최신 LTS 릴리스를 설치하는 것으로 시작하겠습니다.

먼저 콘텐츠에 액세스하려면 NodeSource PPA를 설치합니다. 홈 디렉터리에 있는지 확인하고 curl을 사용하여 Node.js 8.x 아카이브용 설치 스크립트를 검색합니다.

  1. cd ~
  2. curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh

nano 또는 원하는 텍스트 편집기를 사용하여 이 스크립트의 내용을 검사할 수 있습니다.

  1. nano nodesource_setup.sh

스크립트 검사를 마쳤으면 sudo에서 실행합니다.

  1. sudo bash nodesource_setup.sh

PPA가 구성에 추가되고 로컬 패키지 캐시가 자동으로 업데이트됩니다. Nodesource에서 설정 스크립트를 실행한 후 Node.js 패키지를 설치할 수 있습니다.

  1. sudo apt install nodejs

이러한 초기 단계 후에 설치한 Node.js 버전을 확인하려면 다음을 입력하십시오.

  1. nodejs -v
Output
v8.11.3

참고: NodeSource PPA에서 설치할 때 Node.js 실행 파일은 node가 아니라 nodejs입니다.

nodejs 패키지에는 nodejs 바이너리와 노드 모듈용 패키지 관리자인 npm이 포함되어 있으므로 npm 별도.

npm은 홈 디렉터리의 구성 파일을 사용하여 업데이트를 추적합니다. npm을 처음 실행할 때 생성됩니다. 이 명령을 실행하여 npm이 설치되었는지 확인하고 구성 파일을 생성합니다.

  1. npm -v
Output
5.6.0

일부 npm 패키지가 작동하려면(예: 소스에서 코드를 컴파일해야 하는 패키지) build-essential 패키지를 설치해야 합니다.

  1. sudo apt install build-essential

이제 소스에서 코드를 컴파일해야 하는 npm 패키지로 작업하는 데 필요한 도구가 있습니다.

Node.js 런타임이 설치된 상태에서 Node.js 애플리케이션 작성으로 넘어갑시다.

2단계 — Node.js 애플리케이션 만들기

모든 HTTP 요청에 "Hello World\를 반환하는 Hello World 애플리케이션을 작성해 보겠습니다. 이 샘플 애플리케이션은 Node.js를 설정하는 데 도움이 됩니다. 자신의 애플리케이션으로 대체할 수 있습니다. 적절한 IP 주소 및 포트에서 수신 대기하도록 애플리케이션을 수정합니다.

먼저 hello.js라는 샘플 애플리케이션을 만들어 보겠습니다.

  1. cd ~
  2. 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}/`);
});

파일을 저장하고 편집기를 종료합니다.

이 Node.js 애플리케이션은 지정된 주소(localhost)와 포트(3000)에서 수신하고 "Hello World!\를 반환합니다. 200 HTTP 성공 코드로 localhost에서 수신 대기 중이므로 원격 클라이언트는 애플리케이션에 연결할 수 없습니다.

애플리케이션을 테스트하려면 다음을 입력합니다.

  1. node hello.js

다음 출력이 표시됩니다.

Output
Server running at http://localhost:3000/

참고: 이 방식으로 Node.js 애플리케이션을 실행하면 CTRL+C를 눌러 애플리케이션을 종료할 때까지 추가 명령이 차단됩니다.

응용 프로그램을 테스트하려면 서버에서 다른 터미널 세션을 열고 curl을 사용하여 localhost에 연결합니다.

  1. curl http://localhost:3000

다음 출력이 표시되면 애플리케이션이 제대로 작동하고 올바른 주소와 포트에서 수신 대기하는 것입니다.

Output
Hello World!

예상 출력이 표시되지 않으면 Node.js 애플리케이션이 실행 중이고 적절한 주소와 포트에서 수신 대기하도록 구성되어 있는지 확인하세요.

제대로 작동하는지 확인했으면 CTRL+C를 눌러 응용 프로그램을 종료합니다(아직 종료하지 않은 경우).

3단계 - PM2 설치

다음으로 Node.js 애플리케이션용 프로세스 관리자인 PM2를 설치해 보겠습니다. PM2를 사용하면 응용 프로그램을 데몬화하여 백그라운드에서 서비스로 실행할 수 있습니다.

npm을 사용하여 서버에 최신 버전의 PM2를 설치합니다.

  1. sudo npm install pm2@latest -g

-g 옵션은 모듈을 글로벌 설치하도록 npm에 지시하므로 시스템 전체에서 사용할 수 있습니다.

먼저 pm2 start 명령을 사용하여 애플리케이션 hello.js를 백그라운드에서 실행해 보겠습니다.

  1. 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. ┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬───────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼───────┼──────────┤ │ hello │ 0 │ fork │ 1338 │ online │ 0 │ 0s │ 0% │ 23.0 MB │ sammy │ disabled │ └──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴───────┴──────────┘ Use `pm2 show <id|name>` to get more details about an app

보시다시피 PM2는 자동으로 앱 이름(.js 확장자가 없는 파일 이름 기반)과 PM2 id를 할당합니다. PM2는 또한 프로세스의 PID, 현재 상태 및 메모리 사용과 같은 기타 정보를 유지합니다.

PM2에서 실행 중인 응용 프로그램은 응용 프로그램이 충돌하거나 종료되면 자동으로 다시 시작되지만 startup 하위 명령을 사용하여 시스템 시작 시 응용 프로그램이 실행되도록 추가 단계를 수행할 수 있습니다. 이 하위 명령은 서버 부팅 시 PM2 및 해당 관리 프로세스를 시작하는 시작 스크립트를 생성 및 구성합니다.

  1. pm2 startup systemd

결과 출력의 마지막 줄에는 PM2가 부팅 시 시작되도록 설정하기 위해 수퍼유저 권한으로 실행하는 명령이 포함됩니다.

Output
[PM2] Init System found: systemd [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

sammy 대신 사용자 이름을 사용하여 출력에서 명령을 실행합니다.

  1. sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

추가 단계로 PM2 프로세스 목록과 해당 환경을 저장할 수 있습니다.

  1. pm2 save

이제 부팅 시 사용자를 위해 pm2를 실행하는 systemd unit을 만들었습니다. 이 pm2 인스턴스는 hello.js를 실행합니다.

systemctl로 서비스를 시작합니다.

  1. sudo systemctl start pm2-sammy

시스템 장치의 상태를 확인하십시오.

  1. systemctl status pm2-sammy

systemd에 대한 자세한 개요는 Systemd Essentials: Working with Services, Units, and the Journal을 참조하세요.

우리가 다룬 것 외에도 PM2는 애플리케이션에 대한 정보를 관리하거나 조회할 수 있는 많은 하위 명령을 제공합니다.

다음 명령으로 애플리케이션을 중지합니다(PM2 앱 이름 또는 id 지정).

  1. pm2 stop app_name_or_id

애플리케이션을 다시 시작합니다.

  1. pm2 restart app_name_or_id

현재 PM2에서 관리하는 애플리케이션을 나열합니다.

  1. pm2 list

앱 이름을 사용하여 특정 애플리케이션에 대한 정보를 가져옵니다.

  1. pm2 info app_name

PM2 프로세스 모니터는 monit 하위 명령으로 가져올 수 있습니다. 애플리케이션 상태, CPU 및 메모리 사용량이 표시됩니다.

  1. pm2 monit

인수 없이 pm2를 실행하면 사용 예가 있는 도움말 페이지도 표시됩니다.

이제 Node.js 애플리케이션이 PM2에서 실행되고 관리되므로 리버스 프록시를 설정해 보겠습니다.

4단계 - Nginx를 리버스 프록시 서버로 설정

애플리케이션이 실행 중이고 localhost에서 수신 중이지만 사용자가 액세스할 수 있는 방법을 설정해야 합니다. 이를 위해 Nginx 웹 서버를 리버스 프록시로 설정합니다.

전제 조건 자습서에서는 /etc/nginx/sites-available/example.com 파일에서 Nginx 구성을 설정합니다. 편집을 위해 이 파일을 엽니다.

  1. sudo nano /etc/nginx/sites-available/example.com

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;
    }
...
}

이렇게 하면 루트에서 요청에 응답하도록 서버가 구성됩니다. 웹을 통해 https://example.com/에 액세스하는 example.com에서 서버를 사용할 수 있다고 가정합니다. 브라우저는 hello.js에 요청을 보내고 localhost의 포트 3000에서 수신 대기합니다.

동일한 서버 블록에 추가 위치 블록을 추가하여 동일한 서버의 다른 애플리케이션에 대한 액세스를 제공할 수 있습니다. 예를 들어 포트 3001에서 다른 Node.js 애플리케이션을 실행 중인 경우 https://example.com<을 통해 액세스할 수 있도록 이 위치 블록을 추가할 수 있습니다. /마크>/앱2:

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;
    }
...
}

애플리케이션에 대한 위치 블록 추가를 완료했으면 파일을 저장하고 편집기를 종료합니다.

다음을 입력하여 구문 오류가 발생하지 않았는지 확인하십시오.

  1. sudo nginx -t

Nginx를 다시 시작합니다.

  1. sudo systemctl restart nginx

Node.js 애플리케이션이 실행 중이고 애플리케이션과 Nginx 구성이 정확하다고 가정하면 이제 Nginx 리버스 프록시를 통해 애플리케이션에 액세스할 수 있습니다. 서버의 URL(공개 IP 주소 또는 도메인 이름)에 액세스하여 사용해 보십시오.

결론

축하해요! 이제 Ubuntu 18.04 서버의 Nginx 리버스 프록시 뒤에서 실행 중인 Node.js 애플리케이션이 있습니다. 이 리버스 프록시 설정은 사용자가 공유하려는 다른 애플리케이션 또는 정적 웹 콘텐츠에 대한 액세스를 제공할 수 있을 만큼 충분히 유연합니다.