Contents
see List개요
마이크로서비스 환경에서 관찰성(Observability)은 시스템의 내부 상태를 이해하고 문제를 신속히 진단하는 데 필수적입니다. Spring Boot 3.x는 Micrometer를 기반으로 메트릭, 추적, 로그를 통합 관리하며, Prometheus와 Grafana를 통해 시각화할 수 있습니다. 이 문서에서는 Spring Observability 스택의 완전한 구축 방법을 다룹니다.
의존성 설정
Observability를 위한 핵심 라이브러리를 추가합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>Actuator와 Prometheus 설정
메트릭 엔드포인트를 노출하고 Prometheus가 수집할 수 있도록 구성합니다.
# application.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: always
metrics:
tags:
application: my-app
environment: production
tracing:
sampling:
probability: 1.0 # 개발 환경: 100% 샘플링
zipkin:
tracing:
endpoint: http://localhost:9411/api/v2/spans커스텀 메트릭 수집
비즈니스 메트릭을 직접 정의하여 수집할 수 있습니다.
@Service
@RequiredArgsConstructor
public class OrderService {
private final MeterRegistry meterRegistry;
private final Counter orderCounter;
private final Timer orderProcessingTimer;
@PostConstruct
public void init() {
this.orderCounter = Counter.builder("orders.created")
.tag("type", "online")
.description("Total orders created")
.register(meterRegistry);
this.orderProcessingTimer = Timer.builder("orders.processing.time")
.description("Order processing duration")
.register(meterRegistry);
}
public Order createOrder(OrderRequest request) {
return orderProcessingTimer.recordCallable(() -> {
Order order = processOrder(request);
orderCounter.increment();
// 주문 금액별 메트릭
meterRegistry.gauge("orders.amount",
Tags.of("currency", "USD"),
order.getAmount());
return order;
});
}
}분산 추적 (Distributed Tracing)
Micrometer Tracing으로 마이크로서비스 간 요청 흐름을 추적합니다.
@RestController
@RequiredArgsConstructor
public class ApiController {
private final ObservationRegistry observationRegistry;
private final RestClient restClient;
@GetMapping("/api/users/{id}")
public UserDto getUser(@PathVariable Long id) {
// 자동으로 Span이 생성됨
return Observation.createNotStarted("get-user", observationRegistry)
.lowCardinalityKeyValue("userId", String.valueOf(id))
.observe(() -> {
// 하위 서비스 호출도 자동 추적
UserDto user = restClient.get()
.uri("/users/{id}", id)
.retrieve()
.body(UserDto.class);
// 추가 Span 생성
Observation.createNotStarted("enrich-user", observationRegistry)
.observe(() -> enrichUserData(user));
return user;
});
}
}Prometheus 설정
Prometheus가 Spring Boot 메트릭을 수집하도록 설정합니다.
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
labels:
application: 'my-app'Grafana 대시보드
Grafana에서 Prometheus 데이터소스를 연결하고 JVM, HTTP 요청, 커스텀 메트릭을 시각화합니다.
{
"dashboard": {
"title": "Spring Boot Observability",
"panels": [
{
"title": "JVM Memory",
"targets": [
{
"expr": "jvm_memory_used_bytes{application=\"my-app\"}"
}
]
},
{
"title": "HTTP Request Rate",
"targets": [
{
"expr": "rate(http_server_requests_seconds_count{application=\"my-app\"}[5m])"
}
]
},
{
"title": "Order Processing Time (p95)",
"targets": [
{
"expr": "histogram_quantile(0.95, orders_processing_time_seconds_bucket)"
}
]
}
]
}
}활용 팁
- 메트릭 카디널리티 주의: 고유값이 많은 태그(예: userId)는 메모리 소비가 크므로 low cardinality 데이터만 태그로 사용해야 합니다.
- 샘플링 조정: 프로덕션 환경에서는 tracing.sampling.probability를 0.1(10%)로 낮춰 오버헤드를 줄입니다.
- 알람 설정: Prometheus Alertmanager로 응답 시간 초과, 에러율 임계값 등의 알람을 Slack/Email로 전송할 수 있습니다.
- JVM 메트릭: Actuator는 기본적으로 힙 메모리, GC, 쓰레드 수 등 JVM 메트릭을 자동 수집합니다.
- 로그 통합: Loki를 추가하면 Grafana에서 메트릭과 로그를 함께 조회할 수 있습니다.
마무리
Spring Observability 스택은 Actuator, Micrometer, Prometheus, Grafana의 조합으로 완성됩니다. 메트릭과 추적을 통해 시스템의 병목 지점을 찾고, 장애 발생 시 빠르게 원인을 파악할 수 있습니다. 특히 Micrometer Tracing은 마이크로서비스 환경에서 여러 서비스를 거치는 요청의 전체 흐름을 시각화하여 디버깅을 혁신적으로 개선합니다. 프로덕션 환경에서는 반드시 샘플링 비율을 조정하고, 메트릭 카디널리티를 관리하여 성능 저하를 방지해야 합니다.