Actuator + Micrometer + Logback + PLG(Loki/Promtail/Grafana)로 로그·메트릭 기반 모니터링 만들기
서비스를 운영하다 보면 사용자의 동향을 파악하기 위해 GA를 달기도 하지만, 지금 서비스가 어떤 상태인지를 빠르게 파악하는 관측성이 정말 중요해지는데, 이번에 서비스에 Observability(관측성) 기반을 처음부터 구축해보며, 메트릭과 로그를 통합적으로 수집하는 환경을 구성했다.
이번 작업의 핵심은 다음과 같다:
- Spring Actuator로 시스템 상태 노출
- Micrometer + Prometheus로 API 레이턴시, 처리량 측정
- Logback JSON + MDC TraceId로 구조화 로그 생성
1. 의존성 추가
먼저 Gradle에 Spring Boot Actuator와 Micrometer, Logbak을 추가했다
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus:1.13.11'
implementation 'net.logstash.logback:logstash-logback-encoder:7.4'
기존에 액추에이터는 추가되어 있는 상태였는데 메트릭과, 프로메테우스 엔드포인트를 추가로 활성화 시켜줬다
(단, 해당 엔드포인트는 누구나 접근 가능하면 안되기에 SecurityConfig에 path 설정할 예정)
management:
endpoints:
web:
exposure:
include: health, info, metrics, prometheus
2. Micrometer + Prometheus Registry 설정
그리고 공통 태그(custom tags)와 AOP 기반 @Timed 계측을 위해 MetricsConfig를 새로 만들었다.
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags(Environment env) {
return registry -> registry.config().commonTags(
"service", env.getProperty("spring.application.name", "jjinbbang-be"),
"environment", env.getProperty("spring.profiles.active", "default")
);
}
@Bean
public TimedAspect timedAspect(MeterRegistry meterRegistry) {
return new TimedAspect(meterRegistry);
}
이제 아래처럼 컨트롤러 또는 서비스 메서드에 @Timed를 추가하면 자동으로 레이턴시/처리량이 측정된다.
@Timed(value = "map.markers", description = "지도 마커 조회")
public ResponseEntity<?> getMarkers(...) {
...
}
3. Logback JSON 설정 + MDC TraceId 구성
로그를 Loki로 보내려면 JSON 구조화 로그가 필수다. 구조화를 위해 Logback를 활용했는데 logback-spring은 다음과 같댜
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp />
<message />
<loggerName />
<threadName />
<mdc /> <!-- traceId, spanId 등을 여기에 기록 -->
<context />
</providers>
</encoder>
그리고 모든 요청에 자동으로 traceId, spanId, userAgent 등을 넣기 위해 MDC 기반 Trace Logging Filter도 만들었다.
요청 시작 → traceId 생성 → MDC에 저장 → 로그 출력 → 요청 종료 후 clear
이 구조 덕분에 Grafana Explore에서
{service="jjinbbang-be", trace_id="xxx"}
처럼 “요청 단위”로 로그를 추적할 수 있게 되었다.
4. 로그 파일 정책 및 롤링 설정
운영 시 로그 파일은 무한정 커지기 때문에 롤링이 필수다.
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
- 50MB 단위로 압축하여 저장
- 30일 보관
이후 Promtail이 이 경로를 읽어서 Loki로 전송한다.
=> 근데 함정은 그라파나 클라우드에서는 프리티어라 14일만 보관되긴 한다 허허헣 뭐.. 서버에라도 저장해두면 좋으니까..
5. application.yml에 메트릭·액추에이터 설정 추가
실제 동작을 위해 yml에 추가한 핵심 설정은 다음과 같다
management:
metrics:
tags:
application: ${spring.application.name}
distribution:
percentiles-histogram:
http.server.requests: true
endpoint:
health:
show-details: when_authorized
endpoints:
web:
exposure:
include: health, info, metrics, prometheus
prometheus:
metrics:
export:
enabled: true
여기서 중요한 건:
- histogram 활성화 → p95, p99 계산 가능
- /actuator/prometheus 노출
- 필요 최소한의 endpoint만 공개하기
마무리
이제 로그를 점검해보면...?

성공적으로 잘 담겼따..
(뿌듯)
'Project' 카테고리의 다른 글
| 단일 Repository에서 세 개의 서비스를 어떻게 관리할 것인가 (1) | 2026.01.18 |
|---|---|
| [KOSPI FGI] 코스피 공포 탐욕 지수 (KOSPI Fear & Greed Index) 개발기 (0) | 2025.11.23 |
| [찐빵] 옵저버빌리티 설계 (0) | 2025.11.16 |
| [ SWEA Extended #2] SWEA 확장프로그램 제작기 인트로 (0) | 2025.11.15 |