2026년 2월 25일

NestJS 모니터링 시스템 구축 (Prometheus, Grafana)

사전 지식

 

Prometheus 환경 세팅

Prometheus 설정

prometheus.yml
global: scrape_interval: 15s evaluation_interval: 15s rule_files: # - "first.rules" # - "second.rules" scrape_configs: - job_name: prometheus static_configs: - targets: ['localhost:9090']
  • 예제 구성 파일에는 세 가지 구성 블록이 있다.
 
  1. global: 프로메테우스 서버의 글로벌 설정
      • scrape_interval
        • 데이터를 수집하는 주기
        • Prometheus가 타겟에 가서 메트릭을 긁어오는 간격
        • 예시: 15초마다 서버에 가서 현재 CPU, 메모리 등의 값을 가져옴
      • evaluation_interval
        • 규칙을 계산하는 주기
        • 예시: "CPU가 80% 넘었나?”
        •  
  1. rule_files: Prometheus 서버가 로드할 규칙의 위치를 지정
      • 지금은 주석 처리
       
  1. scrape_configs: Prometheus가 감시할 서버 목록
      • 기본값은 Prometheus가 자기 자신을 모니터링
      • Prometheus는 모든 타겟이 기본적으로 /metrics 경로에 메트릭을 노출한다고 가정
 

도커 컴포즈 설정

docker-compose.yml
prometheus: image: prom/prometheus ports: - '9090:9090' volumes: - ./infra/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus
 
실행:
docker compose up prometheus -d
 

Prometheus UI 접속

notion image
 

PromQL 테스트

  1. 수집 정상 여부 확인
    1. up
      결과:
      up{job="prometheus", instance="localhost:9090"} 1
 
  1. Prometheus HTTP 요청 수
    1. prometheus_http_requests_total
      결과:
      notion image
 
  1. 메모리 사용량
    1. process_resident_memory_bytes
      결과:
      notion image
 

NestJS metrics 생성

nestjs-prometheus
willsotoUpdated Feb 25, 2026
 

의존성 설치

npm install @willsoto/nestjs-prometheus prom-client
 

AppModule 수정

import { Module } from "@nestjs/common"; import { PrometheusModule } from "@willsoto/nestjs-prometheus"; @Module({ imports: [PrometheusModule.register()], }) export class AppModule {}
 

도커 컴포즈 설정

docker-compose.yml
app: volumes: - .:/app - /app/node_modules ports: - '3000:3000'
 
실행:
docker compose up app -d
 

/metrics 엔드포인트 테스트

# HELP process_cpu_user_seconds_total Total user CPU time spent in seconds. # TYPE process_cpu_user_seconds_total counter process_cpu_user_seconds_total 3.92215 # ... 중략
 

Node.js 기본 메트릭(defaultMetrics)

  1. 프로세스(Process) 메트릭
    1. 메트릭
      현재 값
      단위
      의미
      process_cpu_user_seconds_total
      3.92
      seconds
      사용자 영역 CPU 사용 시간
      process_cpu_system_seconds_total
      1.20
      seconds
      시스템 영역 CPU 사용 시간
      process_cpu_seconds_total
      5.12
      seconds
      전체 CPU 사용 시간
      process_resident_memory_bytes
      130,191,360
      bytes
      실제 물리 메모리 사용량
      process_virtual_memory_bytes
      925,908,992
      bytes
      가상 메모리
      process_heap_bytes
      407,281,664
      bytes
      힙 전체 크기
      process_open_fds
      24
      count
      열린 파일 디스크립터 수
      process_max_fds
      1,048,576
      count
      최대 허용 fd 수
 
  1. 이벤트 루프(Event Loop) 상태
    1. 메트릭
      단위
      의미
      nodejs_eventloop_lag_seconds
      0.0064
      seconds
      현재 이벤트 루프 지연
      nodejs_eventloop_lag_mean_seconds
      0.0118
      seconds
      평균 지연
      nodejs_eventloop_lag_p99_seconds
      0.0154
      seconds
      99% 지연
      nodejs_eventloop_lag_max_seconds
      0.0517
      seconds
      최대 지연
 
  1. 활성 리소스/핸들
    1. 메트릭
      의미
      nodejs_active_resources_total
      7
      현재 이벤트루프를 유지하는 리소스
      nodejs_active_handles_total
      5
      활성 libuv 핸들
      nodejs_active_requests_total
      1
      활성 요청 수
 
  1. 힙 메모리 상태
    1. 메트릭
      단위
      nodejs_heap_size_total_bytes
      50,823,168
      bytes
      nodejs_heap_size_used_bytes
      46,498,680
      bytes
      nodejs_external_memory_bytes
      2,668,963
      bytes
 
  1. GC (Garbage Collection)
    1. 종류
      실행 횟수
      총 소요 시간
      minor
      3회
      0.019s
      major
      3회
      0.079s
      incremental
      3회
      0.084s
 

Prometheus - NestJS 연동

prometheus.yml 수정
scrape_configs: - job_name: prometheus metrics_path: /metrics static_configs: - targets: ['prometheus:9090'] - job_name: app metrics_path: /metrics static_configs: - targets: ['app:3000']
 

PromQL 테스트

  1. 수집 정상 여부 확인
    1. up
      결과:
      up{job="app", instance="app:3000"} 1 up{job="prometheus", instance="prometheus:9090"} 1
 
  1. NestJS 메트릭 수집 확인 (프로세스 메모리)
    1. process_resident_memory_bytes{job="app"}
      notion image
       
  1. NestJS CPU 사용량 추이(초당 증가량)
    1. rate(process_cpu_seconds_total{job="app"}[1m])
      notion image
 
  1. 이벤트 루프 지연 확인 (ms 단위로 보기)
    1. nodejs_eventloop_lag_p99_seconds{job="app"} * 1000
      notion image

 

Grafana 환경 세팅

 

도커 컴포즈 설정

docker-compose.yml
grafana: image: grafana/grafana ports: - "3002:3000" volumes: - grafana_data:/var/lib/grafana depends_on: - prometheus volumes: prometheus_data: grafana_data:
 
실행:
docker compose up grafana -d
 

Grafana 접속

  • 첫 로그인 시 비밀번호 변경 화면이 뜰 수 있음.
 
notion image
 

Grafana - Prometheus 연동

 
Prometheus Data Source 추가
  1. Grafana 접속 → 왼쪽 메뉴 Connections(또는 톱니바퀴 Settings) → Data sources
  1. Add data source → Prometheus 선택
  1. URL 입력
    1. http://prometheus:9090
  1. Save & test
      • docker-compose 네트워크 안에서 Grafana가 Prometheus를 접근할 때는 localhost가 아니라 서비스명(prometheus) 를 써야 함.
      • Successfully queried the Prometheus API. 안내 메시지가 뜨는지 확인
        • notion image
 
notion image
 

Grafana 대시보드 확인

Explore에서 쿼리 테스트
  • 왼쪽 메뉴 Explore에서 Prometheus 선택 후 아래 쿼리 실행
up
notion image
 

공개 대시보드 찾기

  • 여기서 검색창에 node.js 검색
 
notion image
 

Node.js/NestJS 대시보드 불러오기

Grafana는 Import로 공개 대시보드를 쉽게 가져올 수 있음
  1. 왼쪽 메뉴 Dashboards → New → Import
  1. Dashboard ID로 Import
      • 예시: 11159
  1. DB_PROMETHEUSprometheus 선택
notion image
 

대시보드 확인

제대로 설정이 됐다면 아래와 같이 대시보드 화면이 잘 나오는 것을 볼 수 있음
 
notion image
 

참고 자료