@extends('layouts.app') @section('title', 'PM2 프로세스 관리') @push('styles') @endpush @section('content')
{{-- ============================================================ --}} {{-- 히어로 배너 --}} {{-- ============================================================ --}}
아카데미 PM2 프로세스 관리

PM2 프로세스 관리

Node.js 앱을 24시간 안정적으로 유지하는 프로세스 매니저 — 비개발자를 위한 실전 가이드

⚙️
{{-- ============================================================ --}} {{-- 좌측 고정 목차 (TOC) --}} {{-- ============================================================ --}} {{-- ============================================================ --}} {{-- 우측 콘텐츠 --}} {{-- ============================================================ --}}
{{-- 모바일 목차 --}} {{-- ============================================================ --}} {{-- 1. PM2란? --}} {{-- ============================================================ --}}

1 PM2란? — 왜 PM2를 쓰는가

PM2 = Node.js 프로세스 매니저 ?프로세스(Process)란 현재 실행 중인 프로그램을 뜻한다. 크롬 브라우저를 열면 크롬 프로세스가 생기는 것처럼, Node.js 앱을 실행하면 Node.js 프로세스가 생긴다.

비유: "프로그램이 꺼지면 자동으로 다시 켜주는 비서"

회사에서 중요한 기계가 돌아가고 있다고 상상해보자. 이 기계가 갑자기 멈추면 누군가 와서 다시 켜줘야 한다. PM2는 이 "누군가"의 역할을 자동으로 해주는 프로그램이다. 기계(Node.js 앱)가 멈추면 자동으로 다시 켜주고, 기계의 상태를 계속 감시해준다.

PM2 없이 실행하면 어떤 문제가?

PM2 없이 npm start로 직접 실행하면 다음 문제가 발생한다:

  • 1. 터미널을 닫으면 앱이 꺼진다 — SSH 접속을 끊으면 실행 중이던 앱도 함께 종료된다.
  • 2. 에러가 나면 앱이 중단된다 — 예상치 못한 오류가 발생하면 앱이 멈추고, 누군가 수동으로 다시 켜야 한다.
  • 3. 상태 확인이 어렵다 — 앱이 잘 돌고 있는지, CPU/메모리를 얼마나 쓰는지 알기 어렵다.

PM2가 해결하는 3가지 문제

1

자동 재시작

앱이 에러로 멈추면(crash) PM2가 자동으로 다시 시작해준다. 새벽 3시에 에러가 나도 자동 복구된다.

2

백그라운드 실행

?백그라운드(Background)란 화면에 보이지 않지만 뒤에서 계속 실행되는 것을 뜻한다. 스마트폰에서 음악 앱을 끄지 않고 다른 앱을 사용해도 음악이 계속 나오는 것과 같다.

터미널(SSH)을 닫아도 앱이 꺼지지 않고 계속 실행된다. 서버에 접속하지 않아도 24시간 유지된다.

3

모니터링

앱의 상태, CPU 사용량, 메모리 사용량, 로그를 한눈에 확인할 수 있다. 문제가 생기면 빠르게 원인을 파악할 수 있다.

SAM에서의 역할

SAM 프로젝트에서 PM2는 SAM React (Next.js) 프론트엔드를 운영 서버에서 24시간 유지하는 역할을 한다. 사용자가 SAM 웹사이트에 접속하면, PM2가 관리하는 Next.js 앱이 화면을 보여주는 것이다. PM2가 없으면 서버 관리자가 매번 수동으로 앱을 켜고 감시해야 하지만, PM2 덕분에 이 과정이 완전히 자동화된다.

{{-- ============================================================ --}} {{-- 2. SAM에서 PM2 사용 구조 --}} {{-- ============================================================ --}}

2 SAM에서 PM2 사용 구조

구조 다이어그램

운영 서버(114.203.209.83)에서 사용자의 요청이 처리되는 과정이다. PM2는 Node.js(Next.js) 앱을 관리하며, Nginx가 사용자의 요청을 PM2가 관리하는 앱으로 전달한다.

사용자 브라우저 (크롬, 사파리 등) ┌─────────────────────────────────────┐ Nginx (웹서버, 포트 80/443) - 사용자 요청을 받아서 전달하는 역할 └────────────────┬────────────────────┘ │ 프록시 (요청 전달) ┌─────────────────────────────────────┐ PM2Node.js (Next.js, 포트 3000) - SAM 프론트엔드 화면 생성 - PM2가 이 앱을 감시/관리 └────────────────┬────────────────────┘ │ API 호출 ┌─────────────────────────────────────┐ API 서버 (Laravel, PHP) - 데이터 처리 & DB 접근 └─────────────────────────────────────┘
요약: 사용자가 SAM에 접속하면 Nginx가 요청을 받고, PM2가 관리하는 Next.js 앱이 화면을 생성하고, 필요한 데이터는 API 서버에서 가져온다.

PM2 사용 환경

운영 서버 (114.203.209.83)

PM2를 사용한다. 서버에 Node.js와 PM2가 직접 설치되어 있으며, sam-react라는 이름으로 Next.js 앱을 관리한다.

로컬 Docker 환경 (내 PC)

PM2를 사용하지 않는다. 로컬에서는 Docker 컨테이너가 React 앱을 실행하므로 PM2가 필요 없다. npm run dev로 개발 서버를 실행한다.

{{-- ============================================================ --}} {{-- 3. 자주 쓰는 PM2 명령어 --}} {{-- ============================================================ --}}

3 자주 쓰는 PM2 명령어

참고: 아래 명령어들은 모두 운영 서버에 SSH로 접속한 후 실행한다. 로컬(내 PC)에서는 사용하지 않는다.
{{-- pm2 list --}}

pm2 list — 실행 중인 앱 목록 확인

현재 PM2가 관리하고 있는 모든 앱의 상태를 표 형태로 보여준다. 앱 이름, 상태(online/errored/stopped), CPU 사용량, 메모리 사용량을 한눈에 확인할 수 있다.

$ pm2 list ┌────┬──────────────┬─────────────┬─────────┬──────────┬───────────┐ │ id │ name │ mode │ status │ cpu │ memory │ ├────┼──────────────┼─────────────┼─────────┼──────────┼───────────┤ │ 0 │ sam-react │ fork │ online │ 0.1% │ 120.5 MB │ └────┴──────────────┴─────────────┴─────────┴──────────┴───────────┘
상태 의미: online = 정상 실행 중, errored = 에러 발생, stopped = 수동으로 중지됨
{{-- pm2 start / restart --}}

pm2 start / pm2 restart — 앱 시작 & 재시작

start는 새로운 앱을 PM2에 등록하고 실행한다. restart는 이미 등록된 앱을 껐다가 다시 켠다.

# 새 앱 시작 (PM2에 처음 등록할 때) $ pm2 start npm --name sam-react -- start # 해석: npm start 명령을 "sam-react"라는 이름으로 PM2에 등록하여 실행 # 이미 등록된 앱 재시작 (배포 후 주로 사용) $ pm2 restart sam-react # 해석: sam-react 앱을 껐다가 다시 켠다 (코드 변경 반영)
실무 팁: 배포 시에는 보통 pm2 restart sam-react만 사용한다. pm2 start는 최초 1회만 실행하면 된다.
{{-- pm2 stop / delete --}}

pm2 stop / pm2 delete — 앱 중지 & 삭제

stop은 앱 실행을 중지하지만 PM2 목록에는 남아있다. delete는 PM2 목록에서 완전히 제거한다.

# 앱 중지 (목록에는 남아있음, 나중에 pm2 start로 다시 실행 가능) $ pm2 stop sam-react # 앱 삭제 (PM2 목록에서 완전히 제거) $ pm2 delete sam-react # 삭제 후 다시 사용하려면 pm2 start로 새로 등록해야 한다
주의: pm2 stop을 실행하면 SAM 프론트엔드가 접속 불가해진다. 유지보수 목적 외에는 실행하지 않는다.
{{-- pm2 logs / monit --}}

pm2 logs / pm2 monit — 로그 & 모니터링

logs는 앱의 실시간 출력(로그)을 보여준다. 에러 원인 파악에 필수적이다. monit은 CPU, 메모리, 로그를 한 화면에서 실시간으로 볼 수 있는 대시보드이다.

# 실시간 로그 보기 (Ctrl+C로 종료) $ pm2 logs sam-react 0|sam-react | ▲ Next.js 14.x 0|sam-react | - Local: http://localhost:3000 0|sam-react | ✓ Ready in 2.3s # 최근 100줄만 보기 $ pm2 logs sam-react --lines 100 # 실시간 모니터링 대시보드 (Ctrl+C로 종료) $ pm2 monit # CPU, 메모리, 로그를 한 화면에서 실시간 확인
실무 팁: 앱에 문제가 생기면 가장 먼저 pm2 logs sam-react를 실행하여 에러 메시지를 확인한다.
{{-- pm2 save / startup --}}

pm2 save / pm2 startup — 서버 재부팅 대비 ?pm2 save는 현재 PM2가 관리하는 앱 목록을 파일로 저장한다. pm2 startup은 서버가 부팅될 때 PM2를 자동으로 시작하도록 시스템에 등록한다. 이 두 명령을 함께 사용하면 서버 재부팅 후에도 앱이 자동으로 살아난다.

서버가 재부팅되면 PM2도 함께 꺼진다. 재부팅 후 앱이 자동으로 살아나게 하려면 아래 두 명령을 실행해야 한다.

# 현재 프로세스 목록 저장 (재부팅 후 자동 복구용) $ pm2 save [PM2] Saving current process list... [PM2] Successfully saved in /home/pro/.pm2/dump.pm2 # 부팅 시 PM2 자동 시작 설정 (최초 1회만 실행) $ pm2 startup # 시스템 서비스로 등록 — 서버 켜질 때 PM2가 자동 실행된다
중요: PM2에 새 앱을 추가하거나 삭제한 후에는 반드시 pm2 save를 실행해야 한다. 그래야 서버 재부팅 후에도 변경된 목록이 유지된다.
{{-- 명령어 요약 표 --}}

PM2 명령어 요약표

명령어 설명 사용 예시
pm2 list 실행 중인 앱 목록 확인 앱 이름, 상태, CPU/메모리 표시
pm2 start 앱 시작 pm2 start npm --name sam-react -- start
pm2 restart 앱 재시작 pm2 restart sam-react
pm2 stop 앱 중지 pm2 stop sam-react
pm2 delete 앱 삭제 (목록에서 제거) pm2 delete sam-react
pm2 logs 실시간 로그 보기 pm2 logs sam-react
pm2 monit 실시간 모니터링 대시보드 CPU, 메모리, 로그 실시간 확인
pm2 save 현재 프로세스 목록 저장 서버 재부팅 후 자동 복구용
pm2 startup 부팅 시 PM2 자동 시작 설정 시스템 서비스로 등록
{{-- ============================================================ --}} {{-- 4. SAM 배포와 PM2 --}} {{-- ============================================================ --}}

4 SAM 배포와 PM2

배포 흐름

SAM React 코드를 수정한 후, 사용자에게 반영하기까지의 전체 흐름이다. deploy.sh 스크립트가 이 과정을 자동으로 처리한다.

배포 흐름 (deploy.sh가 자동으로 처리) ① 로컬에서 코드 수정 & git commit ② ./deploy.sh 실행 ├──▶ ③ git pull (최신 코드 받기) ├──▶ ④ npm run build (로컬에서 빌드) ├──▶ ⑤ .next 폴더 압축 → 서버 업로드 ├──▶ ⑥ 서버에서 압축 해제 └──▶ ⑦ pm2 restart sam-react (앱 재시작!) → 사용자가 새 화면을 볼 수 있게 됨
핵심: deploy.sh 스크립트가 마지막 단계에서 자동으로 pm2 restart sam-react를 호출한다. 따라서 배포 시 수동으로 PM2 명령을 실행할 필요가 없다.

서버에서 빌드하지 않는 이유

서버 빌드 금지!

SAM 운영 서버의 스펙은 2코어 CPU, 3.8GB RAM이다. Next.js 빌드(npm run build)는 메모리를 많이 사용하는 작업으로, 이 스펙에서 실행하면 20분 이상 소요되거나 메모리 부족으로 실패한다. 그래서 빌드는 로컬(내 PC)에서 하고, 빌드된 결과물(.next 폴더)만 서버에 올리는 방식을 사용한다.

올바른 방법 (로컬 빌드)

# 로컬(내 PC)에서 $ npm run build # 빌드 결과물을 서버로 전송 # PM2 재시작

잘못된 방법 (서버 빌드)

# 서버에서 직접 빌드 — 금지! $ ssh 서버 $ npm run build # → 메모리 부족, 서버 먹통 위험!
{{-- ============================================================ --}} {{-- 5. 트러블슈팅 --}} {{-- ============================================================ --}}

5 트러블슈팅 — "이럴 땐 어떻게?"

{{-- 문제 1 --}}
1

Process or Namespace sam-react not found

$ pm2 restart sam-react [PM2][ERROR] Process or Namespace sam-react not found

원인:

PM2에 sam-react라는 앱이 등록되어 있지 않다. PM2가 재설치되었거나, pm2 delete로 삭제된 경우 발생한다.

해결:

# Next.js 프로젝트 폴더로 이동 $ cd /home/webservice/react # PM2에 앱을 새로 등록하고 시작 $ pm2 start npm --name sam-react -- start # 목록 저장 (재부팅 대비) $ pm2 save
{{-- 문제 2 --}}
2

PM2 앱 상태가 errored

$ pm2 list │ 0 │ sam-react │ fork │ errored │ 0% │ 0 B │

원인:

Node.js 앱(Next.js)에 에러가 발생하여 실행이 중단된 상태이다. 코드 오류, 의존성 문제, 환경 변수 누락 등이 원인일 수 있다.

해결:

# 1. 먼저 에러 로그를 확인한다 $ pm2 logs sam-react --lines 50 # 2. 에러 원인을 파악한 후 수정 # 3. 앱 재시작 $ pm2 restart sam-react # 4. 상태 확인 (online이면 정상) $ pm2 list
{{-- 문제 3 --}}
3

서버 재부팅 후 앱이 안 뜸

$ pm2 list ┌────┬──────┬──────┬──────┬─────┬────────┐ │ id │ name │ mode │ ... │ ... │ ... │ └────┴──────┴──────┴──────┴─────┴────────┘ (목록이 비어있음)

원인:

이전에 pm2 save를 실행하지 않아서, PM2가 재부팅 후 어떤 앱을 실행해야 하는지 모르는 상태이다.

해결:

# 1. Next.js 프로젝트 폴더로 이동 $ cd /home/webservice/react # 2. 앱 다시 시작 $ pm2 start npm --name sam-react -- start # 3. 반드시 저장! (다음 재부팅에 대비) $ pm2 save # 4. (선택) 부팅 시 PM2 자동 시작 확인 $ pm2 startup
{{-- 문제 4 --}}
4

포트 3000 이미 사용 중

?포트(Port)는 네트워크에서 프로그램을 식별하는 번호이다. 아파트 호수처럼, 한 서버 안에서 여러 프로그램이 각자 다른 포트 번호를 사용한다. Next.js는 기본적으로 포트 3000을 사용한다.
$ pm2 start npm --name sam-react -- start Error: listen EADDRINUSE: address already in use :::3000

원인:

이전에 실행했던 Node.js 프로세스가 아직 포트 3000을 점유하고 있다. PM2에서 제대로 종료되지 않은 잔여 프로세스가 남아있는 경우 발생한다.

해결:

# 1. 기존 앱을 PM2에서 완전히 제거 $ pm2 delete sam-react # 2. 혹시 남아있는 Node.js 프로세스 확인 $ ss -tulnp | grep :3000 # 3. 다시 시작 $ cd /home/webservice/react $ pm2 start npm --name sam-react -- start # 4. 목록 저장 $ pm2 save
{{-- ============================================================ --}} {{-- 6. PM2 vs 다른 방법 비교 --}} {{-- ============================================================ --}}

6 PM2 vs 다른 방법 비교

Node.js 앱을 실행하는 여러 방법을 비교한 표이다. PM2가 모든 면에서 우수하기 때문에 SAM에서 PM2를 선택했다.

실행 방법 백그라운드 실행 자동 재시작 모니터링 로그 관리
npm start X X X X
nohup npm start & ?nohup은 터미널을 닫아도 프로세스가 종료되지 않게 하는 명령어이다. &는 백그라운드 실행을 의미한다. O X X X
screen / tmux ?screentmux는 터미널 세션을 유지해주는 도구이다. 터미널을 닫아도 세션이 유지되지만, 자동 재시작이나 모니터링 기능은 없다. O X X X
PM2 O O O O

결론

npm start는 개발 중에만 사용하는 방법이다. 실제 서비스를 운영할 때는 백그라운드 실행, 자동 재시작, 모니터링, 로그 관리를 모두 지원하는 PM2가 최적의 선택이다. SAM에서도 이러한 이유로 PM2를 사용하여 Next.js 프론트엔드를 안정적으로 운영하고 있다.

{{-- Hover Preview --}}
{{-- Lightbox --}} @include('components.academy-glossary', ['domain' => 'pm2-guide']) @endsection @push('scripts') @endpush