메인 콘텐츠로 건너뛰기
page thumbnail

Spring Boot와 Kafka, 분산 트랜잭션 관리(DLQ·Saga 패턴) 실전 노하우

요약

Spring Boot와 Kafka 연동 기본 구조

Spring Boot에서 Kafka를 사용할 때는 Kafka Producer가 메시지를 보내고, Kafka Consumer가 메시지를 받아 처리합니다. 설정은 application.yml이나 application.properties에 broker 주소 등 기본 정보를 입력합니다. 필수 의존성은 다음과 같습니다:

A modern, minimalist conceptual illustration showing a server architecture built with Java Spring Boot, visualized as abstract layered components. Integrate flow lines representing data streams moving through Kafka message broker, with a highlighted section illustrating a Dead Letter Queue (DLQ) as a secure buffer for unprocessed messages. Include interconnected icons or nodes demonstrating the Saga pattern for managing distributed transactions. Use cool tones (blues, greys) for a professional, educational atmosphere. No text, no human figures, and only general conceptual symbols. The composition should evoke structured learning in advanced backend development.

<!-- pom.xml 주요 의존성 -->
<dependency>
  <groupId>org.springframework.kafka</groupId>
  <artifactId>spring-kafka</artifactId>
</dependency>

Producer 예시와 Consumer 예시는 아래와 같습니다:

// Producer 예시
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;

public void sendMessage(String topic, String message) {
  kafkaTemplate.send(topic, message);
}

// Consumer 예시
@KafkaListener(topics = "sample-topic")
public void listen(String message) {
  // 메시지 처리 로직
}

Dead Letter Queue(DLQ)의 역할과 처리 방법

Dead Letter Queue(DLQ)는 메시지 처리 중 오류가 발생했을 때, 해당 메시지를 별도의 큐로 옮기는 기능을 제공합니다. DLQ를 활용하면 원인 분석이 쉬워지고, 장애로 인해 유실될 위험이 줄어듭니다. Kafka에서는 Consumer에서 처리 중 실패가 반복될 경우, 직접 DLQ 토픽으로 메시지를 전송하는 방식으로 구현합니다.

DLQ 토픽 사용 예시:

// DLQ 전송 예시
@KafkaListener(topics = "origin-topic")
public void listen(String message) {
  try {
    // 메시지 처리 로직
  } catch (Exception e) {
    kafkaTemplate.send("dlq-topic", message);
  }
}

DLQ 적용 시 설계 고려사항

DLQ는 단순히 예외 발생 메시지를 모으는 큐가 아니라, 사후 분석과 재처리를 고려해야 하는 기능입니다.

  • DLQ 토픽은 원본 메시지와 구분되도록 별도 생성

  • 메시지 구조 선택(메타데이터 포함 여부)

  • DLQ 컨슈머를 통한 재처리 로직

  • 실패 원인 기록과 알림(로그, 모니터링 연동 등)

구현에 따라, DLQ 메시지 수집 후 직접적 재처리 또는 비동기 복구도 가능합니다.

Saga 패턴이란? - 분산 트랜잭션의 해법

Saga 패턴은 여러 서비스가 협력해 하나의 트랜잭션을 처리할 때 사용하는 전략입니다. 각 단계가 독립적으로 커밋되고, 문제가 생기면 보상 작업(undo)을 거쳐 전체 일관성을 맞춥니다. Kafka와 같은 메시지 시스템을 활용하면 각 서비스가 이벤트 받아서 로직을 실행하고, 필요한 경우 보상 이벤트를 발행합니다.

Spring Boot + Kafka 환경에서 Saga 구현 사례

실제 Saga 패턴은 주문 서비스, 결제 서비스, 재고 서비스 등이 연결된 비즈니스에 자주 적용합니다. 예시 흐름

  1. 주문 서비스에서 "주문 생성" 이벤트를 발행

  2. 결제 서비스가 메시지를 받아 결제 처리

  3. 결제 성공하면, 재고 서비스로 메시지 전달해 재고 감소

  4. 특정 서비스에서 실패 발생 시, 이전 단계들에 보상 메시지 전송하여 롤백

핵심 코드 예시:

// 주문 생성 Saga 시작 이벤트
kafkaTemplate.send("order-created", orderPayload);

// 결제 실패 대응 - 보상 트랜잭션 실행
@KafkaListener(topics = "payment-failed")
public void onPaymentFailed(String compensationPayload) {
  // 주문 취소 등 보상 로직
}

실무 적용 시 주요 체크포인트

  • 이벤트 순서 보장(메시지 순서 중요 업무는 파티션/키 설정 신경 쓰기)

  • 보상 트랜잭션 자동화(실패 감지 및 보상 로직 분리)

  • 메시지 유실 방지(DLQ와 모니터링, 장애 복구 전략 마련)

  • 테스트: 장애 상황, 실패/재시도 케이스를 충분히 시뮬레이션

결론 - 안정적 이벤트 기반 트랜잭션을 위한 팁

Spring Boot와 Kafka를 활용하면 확장성 좋은 비동기 구조와 강력한 장애처리가 가능합니다. DLQ와 Saga 패턴을 적극 활용하면 분산 환경에서의 데이터 일관성과 복구 전략을 쉽게 설계할 수 있습니다. 구현 단계마다 메시지 흐름, 장애 대응, 이벤트 취소/보상 방식 설계를 꼼꼼히 점검해야 실무에서 안정적으로 운영할 수 있습니다.