Transactional outbox pattern
Tech
Transactional outbox pattern
On this page

단일 시스템 또는 MSA로 완전히 분리되지 않은 환경에서 서비스를 운영하다 보면, 도메인 간 데이터 의존성에 대한 고민이 깊어집니다.
특히 이커머스처럼 PLP -> PDP -> 주문 -> 배송과 같이 도메인 흐름이 명확히 분리되는 경우, 후속 도메인에서 이전 도메인의 데이터가 반드시 필요해지는 상황이 많아집니다.
도메인 간 데이터 의존의 문제
- 간단한 경우에는 타 도메인을 HTTP API 호출을 통해 데이터를 조회할 수 있습니다.
- 그러나 다음과 같은 상황에서는 문제가 복잡해집니다:
- 복잡한 조건의 필터링
- 다양한 데이터 조합 필요
- 다건 조회 등 API로 처리하기엔 한계가 있음
- 또 하나의 고민은, 필요한 데이터를 도메인 내에 내재화하는 것이 필요해지는 시점입니다.
- 단순한 캐싱이나 별도의 저장소에 저장해두는 형태도 포함됩니다.
메시지 기반 동기화 방식의 필요성
이런 문제를 해결하는 보편적인 방식 중 하나가 바로 Kafka와 같은 메시지 큐를 활용한 비동기 데이터 동기화입니다.
예시: 주문 → 배송 데이터 전달
API 방식의 한계
- 실시간으로 전달할 필요가 없음에도 API 방식은 동기 호출이 필수
- HTTP 프로토콜의 불안정성 (네트워크 오류, 타임아웃 등)
- 실패에 대한 보상 트랜잭션 혹은 롤백 기준 설정의 어려움
메시지 큐 방식의 장점
- 비동기 처리를 통해 호출 실패나 네트워크 이슈에 강함
- 확장성과 유연성 확보 가능
- 후속 도메인에서의 처리 재시도 및 보상 처리가 유리
메시지 발행 보장과 Outbox 패턴
메시지 큐의 도입 시 반드시 고려해야 할 점은 발행의 신뢰성입니다.
단순히 큐에 발행했다고 끝이 아니라, "정말 발행됐는지", "실패 시 다시 발행할 수 있는지"가 중요합니다.
이를 위한 대표적인 방법이 Outbox 패턴입니다.
Outbox 패턴의 개념
- 비즈니스 트랜잭션과 메시지 저장을 하나의 트랜잭션으로 처리
- 예: 주문 저장 + 발행 대상 메시지를
outbox 테이블에 함께 저장
- 예: 주문 저장 + 발행 대상 메시지를
- 이후 별도의 프로세스 또는 이벤트 리스너가
outbox 테이블의 데이터를 확인하고 메시지를 실제로 발행 - 메시지 자체를 “즉시 발행”하지 않고, 발행 대상 건을 명확하게 식별하고 “재발행 가능”한 구조로 만듦
단점: 약간의 실시간성 저하
- 이 방식은 메시지 발행을 완전히 즉시 처리하지 않기에 실시간성은 약간 떨어질 수 있음
- 하지만 데이터 신뢰성과 확장성 측면에서는 매우 강력한 방식
다음 글 예고: @TransactionalEventListener 를 활용한 준실시간 처리
이제 Outbox 패턴을 기반으로 한 구조에서, 실시간성까지 확보하기 위한 방안으로
Spring의 @TransactionalEventListener를 활용한 준실시간 메시지 발행 구조에 대해 알아보겠습니다.