2026년 2월 25일
NestJS 모니터링 시스템 구축 (Prometheus, Grafana)
사전 지식Prometheus 환경 세팅Prometheus 설정도커 컴포즈 설정Prometheus UI 접속PromQL 테스트NestJS metrics 생성의존성 설치AppModule 수정도커 컴포즈 설정/metrics 엔드포인트 테스트Node.js 기본 메트릭(defaultMetrics)Prometheus - NestJS 연동PromQL 테스트Grafana 환경 세팅도커 컴포즈 설정Grafana 접속Grafana - Prometheus 연동Grafana 대시보드 확인공개 대시보드 찾기Node.js/NestJS 대시보드 불러오기대시보드 확인참고 자료
사전 지식
Prometheus 환경 세팅
Prometheus 설정
prometheus.ymlglobal: scrape_interval: 15s evaluation_interval: 15s rule_files: # - "first.rules" # - "second.rules" scrape_configs: - job_name: prometheus static_configs: - targets: ['localhost:9090']
- 예제 구성 파일에는 세 가지 구성 블록이 있다.
global: 프로메테우스 서버의 글로벌 설정scrape_interval- 데이터를 수집하는 주기
- Prometheus가 타겟에 가서 메트릭을 긁어오는 간격
- 예시: 15초마다 서버에 가서 현재 CPU, 메모리 등의 값을 가져옴
evaluation_interval- 규칙을 계산하는 주기
- 예시: "CPU가 80% 넘었나?”
rule_files: Prometheus 서버가 로드할 규칙의 위치를 지정- 지금은 주석 처리
scrape_configs: Prometheus가 감시할 서버 목록- 기본값은 Prometheus가 자기 자신을 모니터링
- 왜냐? Prometheus 서버도 메트릭을 제공하는 HTTP 서버이기 때문 (http://localhost:9090/metrics)
- Prometheus는 모든 타겟이 기본적으로
/metrics경로에 메트릭을 노출한다고 가정
도커 컴포즈 설정
docker-compose.ymlprometheus: 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 접속

PromQL 테스트
- 수집 정상 여부 확인
up
결과:
up{job="prometheus", instance="localhost:9090"} 1
- Prometheus HTTP 요청 수
prometheus_http_requests_total
결과:

- 메모리 사용량
process_resident_memory_bytes
결과:

NestJS metrics 생성
nestjs-prometheus
willsoto • Updated 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.ymlapp: 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)
- 프로세스(Process) 메트릭
메트릭 | 현재 값 | 단위 | 의미 |
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 수 |
- 이벤트 루프(Event Loop) 상태
메트릭 | 값 | 단위 | 의미 |
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 | 최대 지연 |
- 활성 리소스/핸들
메트릭 | 값 | 의미 |
nodejs_active_resources_total | 7 | 현재 이벤트루프를 유지하는 리소스 |
nodejs_active_handles_total | 5 | 활성 libuv 핸들 |
nodejs_active_requests_total | 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 |
- GC (Garbage Collection)
종류 | 실행 횟수 | 총 소요 시간 |
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 테스트
- 수집 정상 여부 확인
up
결과:
up{job="app", instance="app:3000"} 1 up{job="prometheus", instance="prometheus:9090"} 1
- NestJS 메트릭 수집 확인 (프로세스 메모리)
process_resident_memory_bytes{job="app"}

- NestJS CPU 사용량 추이(초당 증가량)
rate(process_cpu_seconds_total{job="app"}[1m])

- 이벤트 루프 지연 확인 (ms 단위로 보기)
nodejs_eventloop_lag_p99_seconds{job="app"} * 1000

Grafana 환경 세팅
도커 컴포즈 설정
docker-compose.ymlgrafana: 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 접속
- http://localhost:3002/
- ID:
admin - PW:
admin
- 첫 로그인 시 비밀번호 변경 화면이 뜰 수 있음.

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


Grafana 대시보드 확인
Explore에서 쿼리 테스트
- 왼쪽 메뉴 Explore에서 Prometheus 선택 후 아래 쿼리 실행
up

공개 대시보드 찾기
- 여기서 검색창에
node.js검색
- 원하는 디자인의 대시보드 페이지에 들어가면 Dashboard ID 가 있을텐데 기억해두기

Node.js/NestJS 대시보드 불러오기
Grafana는 Import로 공개 대시보드를 쉽게 가져올 수 있음
- 왼쪽 메뉴 Dashboards → New → Import
- Dashboard ID로 Import
- 예시: 11159
DB_PROMETHEUS는prometheus선택

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

