TestForge | Aidevops | 📊 Plogger ✍️ Blog 📚 Docs
plogger

AI DevOps Korea

AI 서비스 개발, 운영, 성능개선을 하나의 루프로 연결합니다

aidevops.kr에서 LLMOps, RAG, AI Agent, 관측성, 평가, 비용-성능 최적화를 실전 운영 관점으로 정리합니다.

분산 트랜잭션 설계 가이드: Outbox, Inbox, 멱등성, 재처리

· 수정 4월 22일
분산 트랜잭션 설계 가이드: Outbox, Inbox, 멱등성, 재처리 다이어그램
이 그림은 아웃박스 발행, 인박스 중복 제거, 멱등 상태 전이가 함께 동작해 분산 복구를 운영적으로 안전하게 만드는 방식을 보여 줍니다.
분산 시스템에서 실패는 부분적으로 일어납니다. DB 변경은 성공했는데 메시지 발행이 실패할 수 있고, 소비자는 비즈니스 처리를 끝낸 직후 ack 전에 죽을 수 있으며, 재시도 과정에서 같은 메시지가 여러 번 들어올 수도 있습니다.

그래서 분산 트랜잭션 설계의 핵심은 거대한 원자성 환상을 유지하는 것이 아니라, 중복과 재시도와 복구를 운영 가능한 상태로 만드는 것입니다.

왜 2PC가 기본 답이 아닌가

2PC는 강한 원자성을 약속하지만, 현대 서비스 환경에서는 서비스 간 결합도와 인프라 제약, 운영 복잡성을 크게 높입니다.

실무에서 더 자주 필요한 것은 다음입니다.

  • 서비스 내부 경계에서의 로컬 정합성
  • 하위 시스템으로의 신뢰 가능한 전달
  • 중복과 재처리를 안전하게 감당하는 소비자
  • 무엇이 막혔고 지연되었는지 보이는 운영 가시성

Outbox, Inbox, 멱등한 소비자는 이런 현실 문제를 푸는 기본 조합입니다.

Outbox는 DB 변경과 이벤트 발행 사이의 틈을 메웁니다

가장 고전적인 실패 구간은 다음과 같습니다.

  1. 비즈니스 데이터는 커밋됨
  2. 이벤트 발행은 실패함

이 경우 downstream 시스템은 상태 변경을 영원히 모를 수 있습니다.

실전 해법은 다음과 같습니다.

  • 비즈니스 상태 변경과 outbox 레코드 저장을 하나의 로컬 트랜잭션으로 묶음
  • 별도 relay가 outbox를 읽어 비동기로 발행
  • 발행 상태는 별도로 관리

이렇게 하면 트랜잭션이 성공한 이상, “아직 발행해야 할 사실”이 반드시 남습니다.

Inbox는 소비자 측의 중복을 통제합니다

Outbox만으로는 충분하지 않습니다. 소비자는 여전히 같은 메시지를 여러 번 받을 수 있습니다.

대표 원인은 다음과 같습니다.

  • producer 재시도
  • broker 재전달
  • 소비자가 side effect 이후 ack 전에 장애 발생
  • replay 또는 backfill 작업

Inbox는 소비자에게 “이 메시지를 이미 처리했는가”를 판단할 수 있는 영속 기준점을 제공합니다.

멱등성은 선택이 아니라 전제입니다

분산 환경에서 중복 전달은 예외가 아니라 정상입니다. 이를 예외 상황처럼 취급하면 시스템이 쉽게 깨집니다.

소비자는 같은 메시지를 여러 번 받아도 상태를 오염시키지 않아야 합니다. 보통 다음 설계가 필요합니다.

  • 안정적인 메시지 식별자 사용
  • 식별자 기준 처리 결과 저장
  • 최초 성공 처리에서만 side effect 수행
  • “이미 처리됨”과 “실패 후 재시도 중” 상태를 구분

멱등성이 없으면 재시도는 복구 수단이 아니라 장애 증폭기가 됩니다.

순서는 가정이 아니라 명시 대상입니다

분산 설계가 실패하는 흔한 이유 중 하나는 글로벌 순서를 기대하는 것입니다. 실제로 필요한 것은 대부분 전체 순서가 아니라 특정 비즈니스 키 기준의 의미 있는 순서입니다.

팀은 최소한 다음을 정해야 합니다.

  • 어떤 엔터티 또는 비즈니스 키에서 순서가 중요한가
  • 계정 단위인지, 주문 단위인지, 전역 순서인지
  • 순서 뒤바뀜을 어떻게 감지하고 처리할 것인가

대부분의 시스템에서 전역 순서는 비싸고 불필요합니다. 비즈니스 일관성에 필요한 최소 순서를 지키는 것이 더 중요합니다.

재시도는 정책이어야 합니다

재시도는 막연히 여러 번 시도한다고 좋아지지 않습니다. 경계와 관측이 있어야 효과가 있습니다.

실전 재시도 정책에는 보통 다음이 포함됩니다.

  • exponential backoff
  • 최대 재시도 횟수
  • 반복 실패 시 dead-letter 분리
  • 일시 오류와 영구 오류 구분
  • correlation ID 기반 추적

그냥 “될 때까지 재시도”하면, 적체와 지연이 숨어서 더 큰 장애로 번지는 경우가 많습니다.

현실적인 처리 흐름

실무에서는 다음과 같은 흐름이 자주 쓰입니다.

  1. Service A가 비즈니스 테이블과 outbox 이벤트를 한 트랜잭션으로 저장
  2. Outbox relay가 이벤트를 브로커로 발행
  3. Service B가 이벤트를 수신
  4. Inbox에서 메시지 ID를 확인
  5. 처음 보는 메시지라면 비즈니스 처리 후 성공 기록
  6. 이미 처리된 메시지라면 안전하게 종료

이 흐름은 실패를 없애지 않습니다. 대신 실패를 복구 가능하게 만듭니다.

관측 가능성은 정합성의 일부입니다

분산 트랜잭션 설계는 메시지가 어디에서 막히는지 볼 수 없다면 불완전합니다.

최소한 다음은 관측해야 합니다.

  • outbox 적체량과 적체 시간
  • relay 발행 실패율
  • inbox 중복률
  • retry 횟수
  • dead-letter 유입량
  • 최초 쓰기부터 최종 소비까지의 end-to-end latency

이 지표가 없으면 데이터 정합성 이슈는 대부분 늦게 발견됩니다.

흔한 실수

다음 패턴은 실제 운영에서 자주 문제를 만듭니다.

  • outbox는 도입했지만 소비자 멱등성은 구현하지 않음
  • 메시지 ID는 저장하지만 처리 상태를 구분하지 않음
  • 브로커의 exactly-once 기능이 곧 비즈니스 exactly-once라고 오해함
  • 영구 검증 실패와 일시 인프라 실패를 같은 retry 정책으로 다룸
  • dead-letter 재처리 절차가 없음

패턴 자체가 좋아도 운영 전략이 모호하면 결국 흔들립니다.

체크리스트

운영 준비가 되었다고 하려면 최소한 다음 질문에 답할 수 있어야 합니다.

  • 메시지 타입별 idempotency key는 무엇인가?
  • processed, failed, retrying 상태를 어떻게 구분하는가?
  • 어떤 순서가 비즈니스적으로 중요한가?
  • dead-letter를 어떻게 안전하게 재처리하는가?
  • stuck outbox record는 어떻게 탐지하는가?
  • 하나의 비즈니스 액션을 서비스 간에 추적할 수 있는가?

마무리

좋은 분산 트랜잭션 설계는 중복과 재시도가 사라진 시스템이 아닙니다. 중복과 재시도와 순서 가정과 관측 가능성이 실패 상황에서도 안전하도록 설계된 시스템이 좋은 설계입니다.

그것이 분산 환경에서 말하는 실전 정합성의 기준입니다.

Continue Reading

다음으로 읽기 좋은 글

다음 탐색

이 주제를 시스템 관점으로 더 이어서 보기