SOFTMOA TECHNOLOGY

Spring Observability: Micrometer와 Grafana 통합 모니터링

소프트모아가 정리한 기술 기록입니다.

Contents
작성일 2026. 02. 11.

개요

마이크로서비스 환경에서 관찰성(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은 마이크로서비스 환경에서 여러 서비스를 거치는 요청의 전체 흐름을 시각화하여 디버깅을 혁신적으로 개선합니다. 프로덕션 환경에서는 반드시 샘플링 비율을 조정하고, 메트릭 카디널리티를 관리하여 성능 저하를 방지해야 합니다.

Share this

Spring

Have a questions?

견적 및 기술문의

mobile : 010-7931-4813

Contact Form