Conceptly
← 전체 목록
📤

Outbox Pattern

데이터 흐름DB 변경과 이벤트 발행을 묶는 정합성 패턴

Outbox Pattern은 비즈니스 상태 변경과 외부 이벤트 발행을 같은 로컬 트랜잭션 안에 묶기 위해, 별도의 outbox 레코드를 함께 저장하는 방식입니다. 애플리케이션은 상태 테이블과 outbox 테이블에 동시에 기록하고, 이후 릴레이 프로세스가 outbox를 읽어 메시지 브로커나 다른 시스템으로 전달합니다. 즉 발행을 즉시 끝내는 대신, 먼저 기록을 안전하게 남기고 나중에 전달하는 구조입니다.

아키텍처 다이어그램

📊 데이터 흐름 다이어그램

점선 애니메이션은 데이터 또는 요청의 흐름 방향을 나타냅니다

왜 필요한가요?

가장 흔한 분산 정합성 문제 중 하나는 dual write입니다. 예를 들어 주문을 DB에 저장한 뒤 브로커에 주문 생성 이벤트를 발행해야 하는데, DB 커밋은 성공하고 메시지 발행은 실패할 수 있습니다. 반대로 메시지는 나갔는데 상태 저장이 실패할 수도 있습니다. 둘을 별도 작업으로 처리하면 성공과 실패 조합이 늘어나고, 결국 다운스트림 시스템은 어떤 변경을 놓치게 됩니다.

왜 이런 방식이 등장했나요?

과거에는 이런 문제를 분산 트랜잭션으로 해결하려는 시도가 많았지만, 실제 마이크로서비스와 클라우드 환경에서는 비용과 제약이 너무 컸습니다. 각 서비스가 자기 저장소를 소유하고 비동기 이벤트로 협력하는 구조가 보편화되면서, 상태 변경과 이벤트 발행을 어떻게 느슨하게 결합하되 유실은 막을지가 실무 핵심 문제가 됐습니다. Outbox Pattern은 그 압력 속에서 널리 자리 잡은 현실적인 해법입니다.

내부적으로 어떻게 동작하나요?

애플리케이션은 하나의 로컬 트랜잭션 안에서 비즈니스 테이블을 갱신하고, 동시에 outbox 테이블에 발행할 이벤트를 씁니다. 커밋이 끝나면 별도 릴레이 프로세스나 CDC가 outbox를 읽어 메시지 브로커로 전달합니다. 전달 성공 여부를 표시하거나 삭제하면서 중복 전송을 관리합니다. 이 과정에서 릴레이는 재시도를 할 수 있으므로, 소비자 쪽은 중복을 견딜 수 있어야 합니다.

경계와 구분

Event Sourcing이 이벤트 자체를 시스템의 원본 기록으로 삼는 구조라면, Outbox는 현재 상태 저장소를 그대로 유지하면서 통합 이벤트 전달만 안정화하는 패턴입니다. Saga가 여러 서비스에 걸친 긴 흐름을 조율하는 것이라면, Outbox는 한 서비스 안에서 상태 변경과 이벤트 발행 시점을 맞추는 문제를 푸는 것입니다. 비동기 통합이 없거나 하나의 저장소 안에서만 끝나는 시스템이라면 필요성이 낮습니다.

언제 쓰나요?

마이크로서비스가 자기 상태를 바꾸고 그 사실을 다른 서비스에 알려야 하는 거의 모든 이벤트 기반 통합에서 등장합니다. 주문 생성, 결제 완료, 회원 상태 변경처럼 한 서비스의 로컬 커밋이 다른 서비스의 후속 작업을 트리거하는 상황이 대표적입니다. 다만 outbox 테이블 정리 정책, 릴레이 지연, 중복 소비 처리까지 같이 설계하지 않으면 패턴 이름만 도입하고 실제 문제는 그대로 남을 수 있습니다.

상태 변경 후 이벤트 발행메시지 유실 방지변경 데이터 전파CDC·폴링 기반 통합