Micrometer·Prometheus·Grafana로 스프링 부트 서비스 모니터링 대시보드 만들기
운영 중인 서비스에서 장애가 터졌을 때, 가장 먼저 보는 것은 로그지만
“지금 시스템이 얼마나 버티고 있는지”를 알려주는 것은 결국 메트릭과 대시보드입니다.
이 글은 스프링 부트 애플리케이션을 기준으로 Micrometer → Prometheus → Grafana로 이어지는
관측성(Observability) 파이프라인을 한 번에 구축하는 과정을 정리합니다.
단순히 “설치 방법”을 나열하는 것이 아니라,
어떤 메트릭을 왜 수집해야 하는지, 대시보드에서 무엇을 봐야 하는지까지 운영 관점에서 설명합니다.

1. 관측성 파이프라인 전체 구조 이해
먼저 큰 흐름부터 정리해 보겠습니다.
스프링 부트 애플리케이션 내부에서는 Micrometer가 메트릭을 수집하고,
이 메트릭을 /actuator/prometheus 엔드포인트로 노출합니다.
Prometheus는 이 엔드포인트를 주기적으로 스크레이핑(scraping)해 시계열 데이터베이스에 쌓고,
Grafana가 PromQL 쿼리를 통해 데이터를 조회해 대시보드로 시각화합니다.
즉, 흐름은 다음과 같습니다.
애플리케이션 → Micrometer → /actuator/prometheus → Prometheus → Grafana
2. 스프링 부트에서 Micrometer 활성화하기
2-1) 의존성 추가
스프링 부트 2.x/3.x에서는 Actuator와 Micrometer가 거의 기본값처럼 연동됩니다.
Prometheus로 내보내기 위해서는 다음 의존성이 필요합니다.
// build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
}
2-2) application.yml 설정
Actuator 엔드포인트와 Prometheus 노출 설정을 활성화합니다.
운영에서는 보안상 IP 필터링, BasicAuth, 별도 게이트웨이 등으로 보호하는 것을 권장합니다.
management:
endpoints:
web:
exposure:
include: health,info,prometheus
endpoint:
health:
show-details: always
metrics:
tags:
application: my-service
이제 애플리케이션을 실행하면 /actuator/health, /actuator/prometheus 엔드포인트를
브라우저 또는 curl로 확인할 수 있습니다.
2-3) 커스텀 비즈니스 메트릭 추가
기본 제공되는 JVM/HTTP 메트릭만으로는 부족할 때가 많습니다.
예를 들어, “주문 생성 API 호출 수” 같은 비즈니스 메트릭을 추가해 보겠습니다.
@RestController
@RequiredArgsConstructor
public class OrderController {
private final Counter orderCreatedCounter;
@Bean
public Counter orderCreatedCounter(MeterRegistry registry) {
return Counter.builder("order_created_total")
.tag("service", "my-service")
.description("Total number of created orders")
.register(registry);
}
@PostMapping("/orders")
public ResponseEntity<Void> createOrder(@RequestBody OrderRequest req) {
// ... 주문 생성 로직 ...
orderCreatedCounter.increment();
return ResponseEntity.ok().build();
}
}
이렇게 등록한 메트릭은 order_created_total이라는 이름으로 Prometheus에 노출되며,
나중에 Grafana에서 주문 수 추이, 피크 타임 등을 시각화하는 데 사용할 수 있습니다.

3. Prometheus 설정: /actuator/prometheus 스크레이핑
3-1) Docker Compose로 Prometheus 띄우기
Prometheus는 단일 바이너리로도 실행 가능하지만,
테스트와 운영 모두에서 Docker Compose 구성이 가장 관리하기 편합니다.
version: "3.9"
services:
prometheus:
image: prom/prometheus:v2.54.0
container_name: prometheus
restart: always
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prom_data:/prometheus
volumes:
prom_data:
3-2) prometheus.yml에서 스프링 부트 타겟 등록
global:
scrape_interval: 15s
scrape_configs:
- job_name: "spring-boot-app"
metrics_path: "/actuator/prometheus"
static_configs:
- targets: ["host.docker.internal:8080"]
여기서 targets는 Prometheus 컨테이너 기준에서 보이는 스프링 부트 애플리케이션 주소입니다.
로컬 개발 환경에서는 host.docker.internal:8080을 자주 사용하고,
운영 환경에서는 서비스 디스커버리 또는 내부 DNS 이름을 사용하는 경우가 많습니다.
Prometheus 웹 UI(http://localhost:9090)에 접속해 Status → Targets를 보면
스크레이핑 상태가 UP인지 확인할 수 있습니다.
4. Grafana에서 대시보드 만들기
4-1) Grafana Docker Compose 예시
services:
grafana:
image: grafana/grafana:11.0.0
container_name: grafana
restart: always
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
volumes:
grafana_data:
컨테이너가 기동되면 http://localhost:3000으로 접속해
기본 계정(admin/admin)으로 로그인 후 비밀번호를 변경합니다.
그 다음 Configuration → Data sources에서 Prometheus를 추가하고,
URL에 http://prometheus:9090 (Compose 네트워크 기준 이름)을 입력합니다.
4-2) 자주 쓰는 PromQL 쿼리 예시
이제 Grafana의 패널에서 PromQL을 작성해 보면 됩니다.
대표적인 예시는 다음과 같습니다.
# HTTP 요청 수 (5분 단위 증가율)
sum(rate(http_server_requests_seconds_count[5m])) by (uri, status)
# JVM 힙 사용량
jvm_memory_used_bytes{area="heap"}
# 주문 생성 수 (커스텀 메트릭)
sum(rate(order_created_total[5m]))
패널 타입은 시계열(Time series), Stat, Gauge 등을 적절히 섞어 사용합니다.
예를 들어, 전체 요청 수는 시계열, 에러 비율은 Stat, JVM 사용량은 Gauge로 표현하면
대시보드가 한눈에 들어오기 쉬워집니다.

5. 운영 관점에서 꼭 고려해야 할 것들
5-1) 메트릭 태그(cardinality) 폭발 주의
Prometheus의 가장 큰 함정 중 하나가 label cardinality 폭발입니다.
예를 들어, 사용자 ID, 세션 ID 같은 값을 태그로 넣으면
메트릭 시계열 개수가 기하급수적으로 늘어나 스토리지와 조회 성능에 큰 부담을 줍니다.
태그에는 상대적으로 변화가 적은 값(서비스 이름, 인스턴스, 환경, 지역 등)만 두고,
빠르게 변하는 값은 로그나 트레이싱에 맡기는 것이 좋습니다.
5-2) 알람 조건은 “수치” + “기간”으로 정의
Grafana Alert 또는 Alertmanager를 사용할 때는
단일 시점 값이 아니라, 일정 기간 동안의 추세를 기준으로 알림을 설계해야 합니다.
예를 들어, “5분 동안 HTTP 5xx 비율이 5% 이상인 경우”와 같이
노이즈를 줄이면서도 실제 장애를 놓치지 않는 조건이 중요합니다.
5-3) 대시보드는 팀원 전체가 이해할 수 있어야 한다
운영 대시보드는 “예쁘게 만드는 것”보다
누가 봐도 같은 해석을 할 수 있는 구조가 더 중요합니다.
페이지 상단에는 전체 트래픽·에러·지연시간을 배치하고,
중간에는 주요 API, 하단에는 JVM/DB/외부 연동 상태를 배치하는 식으로
위에서 아래로 내려갈수록 자세한 정보를 보는 흐름을 만드는 것이 좋습니다.
6. 정리 및 체크리스트
- 스프링 부트에서 Micrometer + Prometheus Registry 활성화했는가?
- /actuator/prometheus 엔드포인트를 Prometheus에서 정상 스크레이핑하는가?
- 비즈니스 메트릭(주문수, 로그인수 등)을 최소 1개 이상 정의했는가?
- Grafana 대시보드에서 트래픽·에러·지연시간을 한 화면에서 볼 수 있는가?
- 알람 조건과 책임자(누가 볼 것인가)가 명확하게 정의되어 있는가?
Micrometer·Prometheus·Grafana 조합은 한 번 패턴을 잡아두면
새로운 서비스가 추가될 때도 거의 같은 구조를 복사해 쓸 수 있습니다.
이 글에서 정리한 관측성 파이프라인을 기반으로,
운영 중인 서비스의 가시성과 안정성을 한 단계 끌어올릴 수 있기를 바랍니다.
👉 1편: Ubuntu 24.04에서 Nginx로 무료 SSL(HTTPS) 적용
👉 5편: Gradle 빌드 최적화로 빌드 50% 줄이기
👉 6편: Spring Security 6 JWT 로그인/리프레시 토큰
👉 7편: JPA N+1 완전 정복: 자동 감지부터 fetch join·EntityGraph·batch_size 실전 해결 전략
👉 8편: Docker로 PostgreSQL 운영(백업/복구/업그레이드)
'Database & Storage' 카테고리의 다른 글
| SQL 쿼리 정렬과 주석 달기 실전 가이드 — 초보 개발자도 읽히는 쿼리 쓰는 법 (1) | 2025.11.07 |
|---|---|
| Loki + Promtail + Grafana로 로그 수집·검색·알림: 가벼운 ELK 대안 구축(단일 서버 → 다중 서버 확장) (0) | 2025.10.28 |
| 다운타임 없는 DB 마이그레이션 완전 가이드: PostgreSQL & MySQL(Online DDL, gh-ost/pt-osc, Expand→Migrate→Contract) (0) | 2025.10.28 |
| Testcontainers로 DB 통합테스트: Docker 이미지까지 자동 띄우는 실전 가이드 (0) | 2025.10.10 |
| Docker로 PostgreSQL 운영하기: 백업·복구·업그레이드 실전 가이드 (0) | 2025.10.09 |