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