반응형

 

 

Improving Event Reliability in a Saga Orchestrator with the Outbox Pattern 

 

 

지금 진행 중인 프로젝트는 이커머스 도메인을 기반으로 한 MSA 아키텍처 구조의 프로젝트이다. 

주문 생성과 주문 취소와 같은 핵심 비즈니스 흐름은 여러 서비스에 걸쳐 진행되기 때문에 하나의 흐름으로 제어하기 위해 

사가 오케스트레이터 패턴을 적용하였다. 

 

사가 오케스트레이터는 각 단계의 성공과 실패를 상태로 관리하고 있고, 

다음 단계의 처리를 이벤트 기반으로 트리거하는 역할을 하고 있다 

사가 테이블에는 "어디까지 진행되었는지"에 대한 상태 정보가 저장되고, 

동시에 Kafka 이벤트를 통해 다음 서비스가 실행되는 구조로 설계되어 있다. 

 

초기 설계에서는 사가 테이블에 상태를 저장하고, 

그와 별도로 Kafka 이벤트를 발행하는 방식으로 구현하였다. 

사가의 상태 데이터가 정상적으로 저장되고 있었고, 데이터 자체에도 문제가 없어보였다. 

 

그런데 여기서 만약 이벤트 발행 과정에서 문제가 발생한다면 사가가 기록하고 있는 상태와 실제 시스템의 진행 상태는

일치하다고 볼 수 있을까 라는 의문이 생겼다. 

 

 

기존 구조가 부족한 이유


 

초기 MVP설계 단계에서 사가 오케스트레이터의 설계는 단순하게 했다. 

사가 테이블에 현재 상태를 저장하고, 다음 단계를 실행하기 위해 Kafka 이벤트를 발행하는 구조이다. 

 

사가 테이블 상태변경하고 Kafka 이벤트를 발행하고 다음 서비스가 이벤트를 구독하여 작업 수행하는 것이 

표면적으로 보면 사가 테이블의 데이터는 정상적으로 저장되고 있었고 Kafka 메시지도 대부분 정상적으로 발행 되었다. 

 

사가 테이블의 상태와 실제 다음 서비스가 실행되었는지도 논리적으로 같은 사실이 되어야 하는데 기존 구조에서는

이 두 가지가 서로 다른 시세틈, 서로 다른 실패 지점에 놓여있는 상황이 발생했다. 

 

 

상태는 저장되었지만, 상태 변화는 전달되지 않은 경우


 

상태 불일치 예시 

 

- 사가 테이블 상태 : PAYMENT_COMPLETED

- Kafka 이벤트 : X 발행 실패 

- 재고 서비스 : 이벤트 수신 X 

 

사가 오케스트레이터 입장에서는 이미 결제가 완료된 주문으로 인식하고 있다. 

하지만 실제 시스템에서는 그 이후 단계가 전혀 실행되지 않았다. 

 

이 상황의 문제는 단순히 "카프카가 실패했다"가 아니라 

 

- 사가는 이미 다음 단계를 기대하는 상태

- 하지만 다음 단계는 아무것도 모르고 있음

- 재시도 기준도, 복구 기준도 사라졌다. 

 

사가의 상태와 시스템의 실제 진행 상태가 분리된다. 이 지점이 기존 구조의 본질적인 한계이다. 

 

 

아웃박스 패턴 적용 전 시퀀스 다이어그램 


 

 

- 사가 상태 저장과 이벤트 발행이 원자적이지 않다. 

- 실패 시 어느 지점에서 멈췄는지 알 수 없다.

- 사가 재기동 시에도 복구 근거가 없다. 

 

 

아웃박스 패턴이 등장하게 된 이유 


 

Kafka에 보냈는지를 신뢰하지 않는다. 

대신 보내야 한다는 사실을 DB에 남겨둔다. 

 

사가의 상태 변경과 이벤트 발행 의도를 같은 트랜잭션 경계 안에 둔다. 

 

 

아웃박스 패턴 적용 후 시퀀스 다이어그램


 

 

- 사가 상태와 이벤트 발행 의도가 항상 함께 존재하게 된다.

- Kafka 장애 시에도 이벤트는 유실되지 않는다.

- 재기동 후에도 어디까지 진행되었는지 명확해진다. 

 

 

아웃박스 패턴의 핵심 개념 


 

비즈니스 데이터 변경과 이벤트 기록을 하나의 DB 트랜잭션으로 묶는다. 

 

그리고 Kafka에 바로 이벤트를 보내지 않고, 먼저 Outbox 테이블에 이벤트를 저장하는 개념이다. 

 

 

아웃박스 패턴을 적용했을 때의 흐름


 

1. 사가 서비스에서 주문 상태 변경

2. 같은 트랜잭션에서 outbox_event 테이블에 이벤트를 저장

3. 트랜잭션 커밋

4. 별도 퍼블리셔(폴링 or CDC)가 Outbox를 읽어 Kafka로 발행

5. 발행 성공 시 Outbox 상태 변경한다. 

 

이로 인해 DB기준으로 이벤트 유실이 사라지고, 사가 상태와 이벤트의 정합성이 보장된다.

 Kafka 장애 시에도 재발행이 가능해진다. 

 

 

정리


 

아웃박스 패턴은 Kafka를 안정화하기 보다는 사가 오케스트레이터의 상태 의미를 완성시키기 위한 패턴이라고 생각한다. 

 

728x90
반응형