Study/Kafka

[Kafka] Transactional OUTBOX Pattern을 활용한 이벤트 처리

hongeeii 2025. 3. 15.
728x90
반응형

트랜잭셔널 아웃박스 패턴이란?

마이크로서비스 아키텍처에서 이벤트 기반 아키텍처를 도입할 때 가장 큰 문제 중 하나는 데이터베이스 트랜잭션과 메시지 브로커(Kafka 등) 간의 원자성을 보장하는 것입니다. 일반적인 서비스에서는 다음과 같은 시나리오가 발생할 수 있습니다:

  1. 서비스에서 데이터베이스에 데이터를 저장한다.
  2. Kafka 또는 메시지 브로커에 이벤트를 발행한다.

이 과정에서 만약 1번 작업은 성공했지만 2번 작업에서 장애가 발생하면 데이터는 저장되었지만 이벤트가 발행되지 않는 불일치 상태가 발생할 수 있습니다. 이를 해결하는 방법 중 하나가 트랜잭셔널 아웃박스(Transactional Outbox) 패턴입니다.

트랜잭셔널 아웃박스 패턴의 동작 방식

트랜잭셔널 아웃박스 패턴은 데이터베이스의 트랜잭션을 활용하여 이벤트 발행의 원자성을 보장합니다. 핵심 개념은 다음과 같습니다:

  1. Outbox 테이블 추가: 이벤트 데이터를 저장할 별도의 테이블(outbox)을 생성합니다.
  2. 트랜잭션 내에서 이벤트 저장: 애플리케이션은 비즈니스 데이터를 저장할 때, 동시에 Outbox 테이블에 이벤트를 삽입합니다.
  3. 별도 프로세스로 이벤트 발행: 이벤트 발행 프로세스(Outbox Poller)가 주기적으로 Outbox 테이블을 조회하여 Kafka에 메시지를 발행하고, 성공적으로 처리된 이벤트는 Outbox 테이블에서 삭제합니다.

이 방식을 사용하면 데이터 저장과 이벤트 발행을 하나의 트랜잭션으로 묶을 수 있으므로 일관성을 유지할 수 있습니다.

트랜잭셔널 아웃박스 패턴의 구현 방법

Outbox 테이블 스키마 예시

CREATE TABLE outbox (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    aggregate_id VARCHAR(255) NOT NULL,
    aggregate_type VARCHAR(255) NOT NULL,
    event_type VARCHAR(255) NOT NULL,
    payload TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    status ENUM('PENDING', 'PROCESSED') DEFAULT 'PENDING'
);

데이터 저장 시 Outbox 테이블 업데이트 (Spring Boot + JPA)

@Transactional
public void saveOrder(Order order) {
    orderRepository.save(order);
    
    OutboxEvent outboxEvent = new OutboxEvent(order.getId(), "OrderCreated", new Gson().toJson(order));
    outboxRepository.save(outboxEvent);
}

Kafka로 이벤트 발행하는 Outbox Poller (Spring Batch 또는 Scheduler 활용)

@Scheduled(fixedRate = 5000)
public void processOutboxEvents() {
    List<OutboxEvent> events = outboxRepository.findByStatus("PENDING");
    
    for (OutboxEvent event : events) {
        kafkaTemplate.send("order-events", event.getPayload());
        event.setStatus("PROCESSED");
        outboxRepository.save(event);
    }
}

장점과 고려 사항

장점

✅ 데이터베이스 트랜잭션을 활용하여 데이터 정합성을 보장할 수 있음 ✅ Kafka 장애가 발생해도 이벤트 손실을 방지할 수 있음 ✅ 기존 애플리케이션 로직을 크게 변경하지 않고도 이벤트 기반 아키텍처 도입 가능

고려 사항

🔹 Outbox 테이블이 너무 커지지 않도록 정기적인 정리(archiving) 필요 🔹 Polling 방식의 경우 지연(latency) 이 발생할 수 있음 → CDC (Change Data Capture) 방식 고려 가능 🔹 Idempotency(중복 이벤트 처리) 에 대한 대비 필요

결론

Kafka 트랜잭셔널 아웃박스 패턴은 이벤트 기반 아키텍처에서 데이터 정합성을 유지하면서도 메시지 발행의 안정성을 높이는 강력한 방법입니다. 특히 마이크로서비스 환경에서 도입 시 기존 서비스의 데이터 모델을 크게 변경하지 않고도 이벤트 기반 처리를 할 수 있다는 점에서 유용합니다.

이 패턴을 잘 활용하면 데이터 정합성과 이벤트 일관성을 보장하면서도 Kafka 기반의 이벤트 시스템을 안정적으로 운영할 수 있습니다. 🚀

728x90
반응형

'Study > Kafka' 카테고리의 다른 글

Spring Boot Kafka RebalanceListener 예시  (0) 2023.12.07
Spring Boot Kafka Consumer 전략  (0) 2023.12.07
Spring Boot Kafka Producer 설정  (0) 2023.12.07
springboot에서 kafka 연동  (2) 2023.12.07
Kafka Topic  (0) 2023.12.07

추천 글