대규모 MSA에서 데이터 일관성은 생존 문제입니다. 전통 2‑PC(분산 트랜잭션)는 느리고, 장애 전파 위험도 큽니다.
그래서 등장한 두 주인공이 Transactional Outbox와 SAGA입니다. 이름은 많이 들었어도 “어느 상황에서 누구를 써야 하지?” 헷갈린다면 이번 글로 확실히 정리해 보세요.
1️⃣ 한 트랜잭션
비즈니스 테이블 수정과 동시에 Outbox 테이블에 발행할 이벤트 레코드를 INSERT
합니다.
→ 같은 DB 트랜잭션이므로 원자성 100 % 확보.
2️⃣ 트랜잭션 커밋
주문·결제 등 비즈니스 데이터와 PENDING 상태 이벤트가 모두 안전하게 저장.
3️⃣ 별도 프로세스가 Outbox 폴링/CDC
PENDING 레코드를 읽어 Kafka·RabbitMQ 등으로 전송 → 성공 시 SENT
표기/삭제.
장점
주의
어디에 적합?
단일 서비스가 “DB 업데이트 후 이 사실을 확실히 알리고 싶을 때”.
예:OrderService
가OrderCreated
이벤트를 정확히 한 번 발행해야 하는 상황.
서비스들끼리 이벤트를 발행·구독하며 다음 단계를 자율적으로 진행.
OrderCreated → PaymentProcessed → ShippingStarted …
실패 이벤트가 돌면 각자 보상 트랜잭션 실행.
중앙 Saga Coordinator가 모든 단계를 명령/지휘.
공통 특징
어디에 적합?
주문 → 결제 → 재고 → 배송 같은 다중 서비스 시나리오에서 “한 덩어리 트랜잭션”처럼 완결돼야 할 때.
물론입니다. SAGA 단계에서 발생하는 이벤트 발행을 Transactional Outbox로 감싸면
“단계 로컬 트랜잭션” + “이벤트 발행”까지 원자성을 확보할 수 있습니다. 결과적 일관성을 유지하면서도 이벤트 유실/중복 위험을 크게 줄이죠.
Q. Outbox 폴링 대신 더 실시간으로 처리할 수 없나요?
A. DB 로그를 읽는 CDC 스트림(Debezium + Kafka Connect 등)이 가장 많이 쓰입니다. 폴링보다 실시간성·DB 부하가 훨씬 낫지만 초기 세팅이 다소 복잡합니다.
Q. 보상 트랜잭션도 실패하면?
A. 멱등성 확보 → 재시도 큐에 넣기 → 반복 실패 시 알림 후 수동 개입이 현실적인 패턴입니다.
Q. 코레오그래피 vs 오케스트레이션, 언제 무엇을?
두 패턴은 경쟁 관계가 아니라 보완 관계입니다. 시스템 특성과 팀 역량에 맞춰 적절히 조합해 보세요.