프로덕션 환경에서 LLM 추론 모니터링 (2026): vLLM, TGI, llama.cpp 를 위한 Prometheus 및 Grafana
프로미스스(Prometheus) 와 그라파나(Grafana) 를 활용한 LLM 모니터링
LLM 추론은 “단순한 또 하나의 API"처럼 보이지만, 지연 시간이 급증하고 대기열이 쌓이며 GPU 메모리가 95% 사용되는데도 명확한 원인을 파악할 수 없게 되면 상황이 달라집니다.
단일 노드 구성을 벗어나거나 처리량 최적화를 시작하는 순간부터 모니터링은 핵심 과제가 됩니다. 그 시점에서 전통적인 API 지표만으로는 부족합니다. 토큰, 배치 동작, 대기열 시간, KV 캐시 압력과 같은 현대 LLM 시스템의 진정한 병목 현상에 대한 가시성이 필요합니다.
이 글은 가시성 및 모니터링 가이드 의 일부로, 모니터링과 가시성의 기본 개념, Prometheus 아키텍처, 프로덕션 모범 사례를 다룹니다. 여기서는 특히 LLM 추론 워크로드 모니터링 에 집중합니다.
(인프라를 결정 중이라면 2026 년 LLM 호스팅 가이드 를 참조하세요. 배치 메커니즘, VRAM 한계, 처리량과 지연 시간의 트레이드오프에 대해 깊이 알고 싶다면 LLM 성능 엔지니어링 가이드 를 확인하세요.)
일반적인 REST 서비스와 달리 LLM 서빙은 토큰, 연속 배치 (continuous batching), KV 캐시 활용률, GPU/CPU 포화 상태, 대기열 역학에 의해 형성됩니다. 페이로드 크기가 동일한 두 요청이라도 max_new_tokens, 동시성, 캐시 재사용에 따라 지연 시간이 극단적으로 달라질 수 있습니다.
이 가이드는 Prometheus 와 Grafana 를 활용한 LLM 추론 모니터링 구축을 위한 실용적이고 프로덕션 중심의 안내서입니다:
- 측정해야 할 항목 (p95/p99 지연 시간, 토큰/초, 대기열 지속 시간, 캐시 활용률, 오류율)
- 일반적인 서버 (vLLM, Hugging Face TGI, llama.cpp) 에서
/metrics를 수집하는 방법 - 백분위수, 포화 상태, 처리량을 위한 PromQL 예제
- Docker Compose 와 Kubernetes 를 활용한 배포 패턴
- 실제 부하 하에서 나타나는 문제 해결
예시는 고의적으로 벤더 중립적입니다. 추후 OpenTelemetry 추적, 자동 확장, 서비스 메시를 추가하더라도 동일한 지표 모델이 적용됩니다.

LLM 추론을 다르게 모니터링해야 하는 이유
전통적인 API 모니터링 (RPS, p95 지연 시간, 오류율) 은 필요하지만 충분하지 않습니다. LLM 서빙은 추가적인 차원을 더합니다:
1) 지연 시간은 두 가지 의미를 가집니다
- E2E 지연 시간: 요청 수신 → 최종 토큰 반환까지의 시간.
- 토큰 간 지연 시간: 디코딩 중 토큨당 소요 시간 (스트리밍 UX 에 매우 중요).
일부 서버는 두 가지를 모두 노출합니다. 예를 들어, TGI 는 요청 지속 시간과 평균 토큨당 시간을 히스토그램으로 노출합니다.
2) 처리량은 요청이 아닌 토큰 단위입니다
5 토큰을 반환하는 “빠른” 서비스와 500 토큰을 반환하는 서비스는 비교할 수 없습니다. “RPS” 대신 종종 “토큰/초“가 필요합니다.
3) 대기열이 제품입니다
연속 배치를 실행한다면, 대기열 깊이가 판매하는 것이 됩니다. 대기열 지속 시간과 대기열 크기를 모니터링하면 사용자 기대치를 충족하는지 알 수 있습니다.
4) 캐시 압력은 장애의 전조입니다
KV 캐시 부족 (또는 분할) 은 종종 갑작스러운 지연 시간 급증과 타임아웃으로 나타납니다. vLLM 은 KV 캐시 사용량을 게이지로 노출합니다.
LLM 추론 모니터링을 위한 지표 체크리스트
이를 북극성으로 삼으세요. 첫날부터 모든 것이 필요하지는 않지만, 결국 대부분 필요하게 될 것입니다.
황금 신호 (LLM 스타일)
- 트래픽: 초당 요청 수, 초당 토큰 수
- 오류: 오류율, 타임아웃, OOM, 429 (속도 제한)
- 지연 시간: p50/p95/p99 요청 지속 시간; 프리필 vs 디코딩 지연 시간; 토큰 간 지연 시간
- 포화 상태: GPU 활용률, 메모리 사용량, KV 캐시 사용량, 대기열 크기
Prometheus 외부의 GPU 메모리 사용량, 온도, 활용률에 대한 저수준 가시성 (디버깅 또는 단일 노드 설정용) 이 필요하다면 Linux / Ubuntu GPU 모니터링 애플리케이션 가이드 를 참조하세요.
지표 외의 더 넓은 LLM 가시성 (추적, 구조화된 로그, 합성 테스트, GPU 프로파일링, SLO 설계 포함) 에 대한 자세한 내용은 LLM 시스템 가시성 가이드 를 참조하세요.
유용한 차원 (라벨)
라벨 카디널리티를 낮게 유지하세요. 좋은 라벨:
model,endpoint,method(prefill/decode),status(success/error),instance
피해야 할 라벨:
- 원본
prompt, 원본user_id, 요청 ID — 이는 시리츠 수를 폭발시킵니다.
지표 노출: 내장 /metrics 엔드포인트 (vLLM, TGI, llama.cpp)
가장 쉬운 방법은: 서버가 이미 노출하는 지표를 사용하는 것입니다.
vLLM: Prometheus 호환 /metrics
vLLM 은 Prometheus 호환 /metrics 엔드포인트 (Prometheus 지표 로거를 통해) 를 노출하고 실행 중인 요청 및 KV 캐시 사용량과 같은 게이지를 포함한 서버/요청 지표를 vllm: 접두사로 게시합니다.
컨테이너 설정, OpenAI 호환 서빙, 처리량 중심 런타임 튜닝에 대해서는 vLLM 빠른 시작: 고성능 LLM 서빙 를 참조하세요.
일반적으로 볼 수 있는 예시 지표:
vllm:num_requests_runningvllm:num_requests_waitingvllm:kv_cache_usage_perc
Hugging Face TGI: 대기열 + 요청 히스토그램이 있는 /metrics
TGI 는 /metrics 에서 대기열 크기, 요청 지속 시간, 대기열 지속 시간, 평균 토큨당 시간 등 프로덕션급 지표를 많이 노출합니다.
주목할 만한 지표:
tgi_queue_size(게이지)tgi_request_duration(히스토그램, e2e 지연 시간)tgi_request_queue_duration(히스토그램)tgi_request_mean_time_per_token_duration(히스토그램)
운영 설정 (Docker, GPU, 시작 플래그, 빈 또는 오해의 소지가 있는 수집으로 나타나는 실패) 은 TGI - Text Generation Inference - 설치, 구성, 문제 해결 에서 다루고 있습니다.
llama.cpp 서버: 지표 엔드포인트 활성화
llama.cpp 서버는 플래그 (예: --metrics) 로 활성화해야 하는 Prometheus 호환 지표 엔드포인트를 지원합니다.
설치 경로, 핵심 런타임 플래그, OpenAI 호환 서버 사용에 대해서는 CLI 및 서버를 사용한 llama.cpp 빠른 시작 을 참조하세요.
프록시 뒤에 llama.cpp 를 실행 중이라면, 가능한 경우 직접 서버를 수집하세요 (프록시 수준 지연 시간이 실제 추론 동작을 가리는 것을 방지).
Prometheus 설정: 추론 서버 수집
이 예제는 다음을 가정합니다:
- vLLM:
http://vllm:8000/metrics - TGI:
http://tgi:8080/metrics - llama.cpp:
http://llama:8080/metrics - 빠른 피드백을 위해 조정된 수집 간격
prometheus.yml
global:
scrape_interval: 5s
evaluation_interval: 15s
scrape_configs:
- job_name: "vllm"
metrics_path: /metrics
static_configs:
- targets: ["vllm:8000"]
- job_name: "tgi"
metrics_path: /metrics
static_configs:
- targets: ["tgi:8080"]
- job_name: "llama_cpp"
metrics_path: /metrics
static_configs:
- targets: ["llama:8080"]
Prometheus 가 처음이거나 수집 설정, 익스포터, 릴레이블링, 경고 규칙에 대한 더 깊은 설명이 필요하다면 Prometheus 모니터링 설정 가이드 를 참조하세요.
프로 팁: “서비스 라벨” 추가
여러 모델/복제본을 실행한다면 대시보드를 위해 안정적인 service 라벨을 포함하도록 릴레이블링을 추가하세요.
relabel_configs:
- target_label: service
replacement: "llm-inference"
복사/붙여넣기 가능한 PromQL 예제
요청률 (RPS)
sum(rate(tgi_request_count[5m]))
vLLM 의 경우 버전마다 이름이 다를 수 있지만 패턴은 동일합니다: sum(rate(<counter>[5m])).
오류율 (%)
*_success 카운터가 있다면 실패 비율을 계산합니다:
1 - (
sum(rate(tgi_request_success[5m]))
/
sum(rate(tgi_request_count[5m]))
)
히스토그램 지표의 p95 지연 시간 (Prometheus)
Prometheus 히스토그램은 버킷된 카운트이므로, 버킷의 rate()에 대해 histogram_quantile() 을 사용하세요. Prometheus 는 이 모델과 히스토그램 대 요약의 트레이드오프를 문서화합니다.
histogram_quantile(
0.95,
sum by (le) (rate(tgi_request_duration_bucket[5m]))
)
p99 대기열 시간
histogram_quantile(
0.99,
sum by (le) (rate(tgi_request_queue_duration_bucket[5m]))
)
평균 토큨당 시간 (토큰 간 지연 시간)
histogram_quantile(
0.95,
sum by (le) (rate(tgi_request_mean_time_per_token_duration_bucket[5m]))
)
토큰 간 지연 시간은 종종 디코딩 병목 현상과 메모리 대역폭에 의해 제한되며, 이는 LLM 성능 최적화 가이드 에서 자세히 다룹니다.
대기열 깊이 (순간)
max(tgi_queue_size)
vLLM KV 캐시 활용률 (순간)
max(vllm:kv_cache_usage_perc)
Grafana 대시보드: 실제 온콜에 도움이 되는 패널
Grafana 는 히스토그램을 여러 가지 방식 (백분위수, 히트맵, 버킷 분포) 으로 시각화할 수 있습니다. Grafana Labs 는 Prometheus 히스토그램 시각화에 대한 자세한 가이드를 제공합니다.
최소한의 고신호 대시보드 레이아웃:
1 행 — 사용자 경험
- p95 요청 지연 시간 (시계열)
- p95 토큰 간 지연 시간 (시계열)
- 오류율 (시계열 + 통계)
2 행 — 용량 및 포화 상태
- 대기열 크기 (시계열)
- 실행 중 vs 대기 중인 요청 (스택)
- KV 캐시 사용률 % (게이지)
3 행 — 처리량
- 초당 요청 수
- 생성된 토큰/요청 (p50/p95)
스트리밍을 사용한다면, 사용 가능한 경우 “첫 번째 토큰 지연 시간 (TTFT)” 패널을 추가하세요.
예시 Grafana 쿼리
- p95 지연 시간 패널: 위의
histogram_quantile(0.95, …)쿼리 - 히트맵 패널: 버킷 레이트 (
*_bucket) 를 히트맵으로 그래프화 (Grafana 는 이 방식을 지원)
배포 옵션 1: Docker Compose (빠른 로컬 + 단일 노드)
로컬, 자체 호스팅, 클라우드 기반 추론 아키텍처 중 무엇을 선택할지 고민 중이라면, 전체 분석은 LLM 호스팅 비교 가이드 에서 확인하세요.
다음과 같은 폴더를 생성하세요:
monitoring/
docker-compose.yml
prometheus/
prometheus.yml
grafana/
provisioning/
datasources/datasource.yml
dashboards/dashboards.yml
dashboards/
llm-inference.json
docker-compose.yml
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning
- ./grafana/dashboards:/var/lib/grafana/dashboards
ports:
- "3000:3000"
depends_on:
- prometheus
Docker 대신 수동 Grafana 설치를 선호한다면 Ubuntu 에서 Grafana 설치 및 사용 가이드 를 참조하세요.
Grafana 데이터소스 프로비저닝 (grafana/provisioning/datasources/datasource.yml)
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
대시보드 프로비저닝 (grafana/provisioning/dashboards/dashboards.yml)
apiVersion: 1
providers:
- name: "LLM"
folder: "LLM"
type: file
disableDeletion: true
options:
path: /var/lib/grafana/dashboards
배포 옵션 2: Kubernetes (Prometheus Operator + ServiceMonitor)
kube-prometheus-stack (Prometheus Operator) 을 사용한다면 ServiceMonitor 를 통해 수집 대상에 접근합니다.
Kubernetes, 단일 노드 Docker, 관리형 추론 제공업체 간의 인프라 트레이드오프에 대해서는 2026 년 LLM 호스팅 가이드 를 참조하세요.
1) 추론 배포를 Service 로 노출
apiVersion: v1
kind: Service
metadata:
name: tgi
labels:
app: tgi
spec:
selector:
app: tgi
ports:
- name: http
port: 8080
targetPort: 8080
2) ServiceMonitor 생성
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: tgi
labels:
release: kube-prometheus-stack
spec:
selector:
matchLabels:
app: tgi
endpoints:
- port: http
path: /metrics
interval: 5s
vLLM 과 llama.cpp 서비스에 대해 반복하세요. 복제본을 추가함에 따라 깔끔하게 확장됩니다.
3) 경고: SLO 스타일 규칙 (예시)
다음은 좋은 시작 경고입니다:
- 높은 p95 지연 시간 (버닝 레이트)
- 대기열 시간 p99 과도하게 높음 (사용자 대기)
- 오류율 > 1%
- 지속적인 KV 캐시 사용률 > 90% (용량 절벽)
예시 규칙 (p95 요청 지속 시간):
- alert: LLMHighP95Latency
expr: histogram_quantile(0.95, sum by (le) (rate(tgi_request_duration_bucket[5m]))) > 3
for: 10m
labels:
severity: page
annotations:
summary: "TGI p95 지연 시간 > 3 초 (10 분)"
문제 해결: LLM 스택에서 발생하는 일반적인 Prometheus + Grafana 실패
1) Prometheus 대상이 “DOWN”
증상
- Prometheus UI → Targets 에서
DOWN표시 - “context deadline exceeded” 또는 연결 거부
확인 사항
- 서버가 실제로
/metrics를 노출하고 있나요? - 잘못된 포트? 잘못된 스키마 (http vs https)?
- Kubernetes: Service 가 팟을 선택하고 있나요? ServiceMonitor 라벨
release가 올바른가요?
빠른 테스트
curl -sS http://tgi:8080/metrics | head
2) 지표를 수집할 수 있지만 패널이 비어 있음
가장 흔한 원인
- 잘못된 지표 이름 (서버 버전 변경)
- 대시보드가
_bucket을 기대하지만 게이지/카운터만 있음 - 짧은 창 (예:
[1m]) 에 비해 Prometheus 수집 간격이 너무 길어 노이즈 발생
해결 방법
- Grafana Explore 를 사용하여 지표 접두사 (예:
tgi_/vllm:) 검색 - 범위 창을
[1m]→[5m]로 증가
3) 히스토그램 백분위수가 “평평하거나” 잘못 표시됨
Prometheus 히스토그램은 올바른 집계 필요:
rate(metric_bucket[5m])사용- 그런 다음
sum by (le)(및 선택적으로 다른 안정적인 라벨) - 그런 다음
histogram_quantile()
Prometheus 는 버킷 모델과 서버 측 양분 계산 (quantile calculation) 을 문서화합니다.
Grafana 의 히스토그램 시각화 가이드에는 실용적인 패널 패턴이 포함됩니다.
4) 카디널리티 폭발 (Prometheus 메모리 급증)
증상
- Prometheus RAM 사용량 증가
- “too many series” 오류
일반적인 근본 원인
- 커스텀 익스포터에서
prompt,user_id, 요청 ID 를 라벨로 추가했습니다.
해결 방법
- 높은 카디널리티 라벨 제거
- 저 카디널리티 라벨 (model, endpoint, status) 로 사전 집계
- 라벨 대신 로그/추적을 사용한 요청별 디버깅 고려
5) “지표는 있지만 느린 이유가 모르겠어요”
지표는 필요하지만 때로는 상관관계가 필요합니다:
- 요청 메타데이터 (모델, 토큰 수, TTFT) 가 포함된 구조화된 로그 추가
- 게이트웨이 + 추론 서버 주위에 추적 (OpenTelemetry) 추가
- 지원되는 경우 예시 (exemplars) 를 사용하여 지연 시간 급증에서 추적으로 이동
좋은 워크플로우: Grafana 대시보드 급증 -> Explore 클릭 -> 인스턴스/모델로 좁힘 -> 해당 기간의 로그/추적 확인.
이는 가시성 및 모니터링 아키텍처 가이드 에 설명된 고전적인 지표 -> 로그 -> 추적 모델을 따릅니다.
6) vLLM / 멀티프로세스 지표 특이점
서빙 스택이 여러 프로세스에서 실행되는 경우, Prometheus 멀티프로세스 구성이 필요할 수 있습니다 (프로세스가 지표를 노출하는 방식에 따라 다름). vLLM 문서에서는 Prometheus 폴링을 위해 /metrics 를 통한 지표 노출을 강조합니다. 배포 시 서버의 지표 모드를 확인하세요.
실용적인 “1 일차” 대시보드 및 경고 세트
프로덕션에서도 작동하는 간결한 설정을 원한다면 다음으로 시작하세요:
대시보드 패널
- p95 요청 지연 시간
- p95 평균 토큨당 시간
- 대기열 크기
- p95 대기열 지속 시간
- 오류율
- KV 캐시 사용률 %
경고
- p95 요청 지연 시간 > X (10 분간)
- p99 대기열 지속 시간 > Y (10 분간)
- 오류율 > 1% (5 분간)
- KV 캐시 사용률 > 90% (15 분간)
- Prometheus 대상 다운 (항상)
관련 가시성 가이드
- 가시성 가이드: Prometheus, Grafana 및 프로덕션 모니터링
- Prometheus 모니터링: 설정 및 모범 사례
- Ubuntu 에서 Grafana 설치 및 사용: 완전한 가이드
관련 LLM 인프라 가이드
마무리
Prometheus + Grafana 는 추론 상태에 대한 “항상 켜져 있는” 뷰를 제공합니다. 기본 사항을 갖춘 후, 다음 큰 성과는 일반적으로 다음과 같습니다:
- 모델/테넌트별 SLO
- 요청 성형 (최대 토큰, 동시성 제한)
- 대기열 시간과 KV 캐시 여유량에 연결된 자동 확장
모니터링과 가시성의 차이, Prometheus 기본 개념, 프로덕션 패턴에 대한 더 넓은 설명은 가시성 가이드 를 참조하세요.