Sleuth와 Zipkin으로 분산 트레이싱 - 마이크로서비스의 요청 흐름 가시화

마이크로서비스 환경에서는 하나의 요청이 여러 서비스를 거쳐 처리됩니다. 예를 들어 주문 API를 호출하면, 주문 서비스 → 결제 서비스 → 사용자 서비스로 연속 호출이 일어날 수 있습니다. 이때 요청 흐름이 어디서 지연되었는지, 어느 서비스에서 오류가 발생했는지를 추적하는 것이 바로 분산 트레이싱(Distributed Tracing)입니다.

 

분산 트레이싱이란?

분산 트레이싱은 여러 서비스에 걸친 요청 흐름을 추적하여, 요청 단위 성능 병목 구간과 오류 원인을 파악하는 기술입니다. 각 요청에는 고유한 Trace ID가 부여되며, 요청이 다른 서비스로 전달될 때마다 Span이라는 하위 단위로 세분화되어 기록됩니다.

이러한 Trace/Span 정보를 수집하고 시각화하기 위한 도구로는 SleuthZipkin이 널리 사용됩니다.

 

Sleuth와 Zipkin의 역할

  • Spring Cloud Sleuth: 각 서비스에 Trace ID / Span ID를 자동으로 생성하고 로깅에 삽입하는 클라이언트 라이브러리
  • Zipkin: Sleuth에서 생성한 Trace 정보를 수집, 저장, 시각화하는 서버

즉, Sleuth는 데이터를 생성하고 Zipkin은 그 데이터를 “보는 창” 역할을 합니다.

 

1. Sleuth 적용하기

의존성 추가 (Gradle)

implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-starter-zipkin'

application.yml 설정

spring:
  application:
    name: order-service
  sleuth:
    sampler:
      probability: 1.0   # 모든 요청 트레이싱 (운영환경에서는 0.1~0.2 추천)
  zipkin:
    base-url: http://localhost:9411
    sender:
      type: web

위 설정은 모든 요청을 Zipkin 서버로 전송하도록 설정합니다. 운영 환경에서는 트래픽 과부하를 방지하기 위해 probability 값을 0.1 이하로 낮추는 것이 좋습니다.

 

2. Zipkin 서버 실행하기

Docker로 실행

가장 간단하게 Zipkin을 실행하는 방법은 Docker를 사용하는 것입니다.

docker run -d -p 9411:9411 openzipkin/zipkin

실행 후 브라우저에서 http://localhost:9411로 접속하면 Zipkin UI를 확인할 수 있습니다.

 

Zipkin 수집 데이터 구조

Zipkin은 각 요청을 다음과 같은 구조로 기록합니다:

  • Trace ID: 전체 요청 단위 식별자
  • Span ID: 각 서비스 내부 작업(메서드 호출 등) 단위
  • Parent Span ID: 상위 호출 관계
  • Timestamp: 시작 시각
  • Duration: 실행 시간(ms)

이 데이터를 기반으로 Zipkin UI는 요청 흐름을 트리 형태로 시각화합니다.

 

3. 서비스 간 트레이싱 연동

Sleuth는 HTTP 헤더를 통해 Trace 정보를 자동으로 전달합니다. 즉, RestTemplate 또는 FeignClient를 사용할 경우 별도의 추가 코드 없이 Trace ID가 전파됩니다.

@RestController
@RequiredArgsConstructor
public class OrderController {

    private final RestTemplate restTemplate;

    @GetMapping("/order")
    public String createOrder() {
        String userInfo = restTemplate.getForObject("http://USER-SERVICE/user", String.class);
        return "Order created for " + userInfo;
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

이때 Sleuth는 HTTP 요청 헤더에 다음 정보를 추가합니다:

X-B3-TraceId
X-B3-SpanId
X-B3-ParentSpanId
X-B3-Sampled

각 서비스는 이 헤더를 이용해 동일한 Trace ID를 공유하므로, Zipkin에서 전체 요청 흐름을 하나의 트레이스로 확인할 수 있습니다.

 

4. Zipkin UI에서 확인

Zipkin UI에 접속하면 아래와 같은 항목을 확인할 수 있습니다:

  • 서비스 목록(Service): 트레이싱된 서비스 이름
  • 요청 트레이스(Trace): 요청 단위 상세 흐름
  • 타임라인(Timeline): 서비스별 호출 순서와 소요 시간
  • Dependency 그래프: 서비스 간 호출 관계 시각화

이를 통해 “어떤 서비스가 느린가”, “장애가 어디서 발생했는가”를 직관적으로 파악할 수 있습니다.

 

5. 로그와 트레이스 통합

Sleuth는 로그에도 Trace ID를 자동으로 삽입합니다.

2025-11-02 12:31:02.351  INFO [order-service,traceId=8a12f8b92f7a1d23,spanId=8a12f8b92f7a1d23] ...

이 덕분에 로그를 통해서도 동일한 요청의 흐름을 쉽게 추적할 수 있습니다. ELK(Elasticsearch + Logstash + Kibana) 환경과 연계하면, Zipkin과 함께 더욱 강력한 모니터링 체계를 구축할 수 있습니다.

 

6. 실무에서의 최적 구성

  • 샘플링 비율 조정: 트래픽이 많은 서비스에서는 0.1~0.3 수준으로 조정
  • Zipkin 저장소: 기본 In-Memory 외에 MySQL, Elasticsearch 등 외부 스토리지 사용
  • 보안 설정: Zipkin UI 접근 제한 및 HTTPS 적용
  • 로그 수집 시스템 통합: Sleuth 로그를 중앙화 시스템으로 연동
  • Grafana/Prometheus 연계: 트레이스 지표를 시각화 및 알림 설정

 

주의할 점

  • 모든 요청을 트레이싱하면 Zipkin 서버 과부하 발생 가능 → 샘플링 제어 필수
  • 분산 환경에서는 시간 동기화(NTP) 필수 — 서비스 간 타임라인 오류 방지
  • Trace ID는 개인정보와 연관되지 않도록 설계
  • Zipkin 서버 장애 시 서비스에는 영향이 없지만, 트레이스 데이터 손실 가능

 


 

Sleuth와 Zipkin은 마이크로서비스의 요청 흐름을 가시화하여, 성능 병목과 장애 지점을 빠르게 찾아내는 핵심 도구입니다. 특히 운영 환경에서는 로그 + 트레이스 + 모니터링을 통합한 관측성(Observability) 체계를 구축해야 합니다.