2 min read

Saga Orchestration vs Choreography 선택 기준

분산 트랜잭션에서 장애 복구, 추적성, 팀 구조를 고려한 사가 패턴 선택 가이드

Saga Orchestration vs Choreography 선택 기준 thumbnail

도입

분산 트랜잭션을 다루는 조직에서는 Saga 패턴을 도입하는 순간 장애 모델 자체가 달라진다. 문제는 Orchestration과 Choreography를 기술 취향으로 고르는 경우가 많다는 점이다. 이 글은 팀 구조, 변경 빈도, 장애 대응 방식 기준으로 두 모델을 선택하는 실무 기준을 제시한다.

Saga Orchestration vs Choreography 선택 기준 커버
Wikimedia Commons 기반 무료 이미지

문제 정의

Saga 구조를 잘못 선택하면 정상 시나리오는 동작해도 예외 시나리오에서 복구 시간이 급격히 늘어난다.

  • 도메인 이벤트가 무분별하게 확장되어 이벤트 흐름을 추적할 수 없다.
  • 보상 트랜잭션이 서비스별로 흩어져 장애 시 누락 가능성이 높다.
  • 운영팀이 전체 플로우 가시성을 확보하지 못해 MTTR이 증가한다.

선택 기준은 단순하다. 흐름이 복잡하고 정책 변경이 잦으면 Orchestration, 서비스 독립성과 느슨한 결합이 더 중요하면 Choreography가 유리하다.

핵심 개념

관점설계 기준검증 포인트
중앙 제어오케스트레이터 단일 흐름 관리실패 지점 추적 난이도
분산 자율이벤트 기반 상태 전이서비스 독립 배포 빈도
보상 전략명시적 compensation 정의누락/중복 보상률
관측성Saga 인스턴스 단위 추적복구 평균 시간

도메인 단위로 선택해도 된다. 결제/정산처럼 규칙이 복잡한 흐름은 Orchestration, 알림/분석 파이프라인은 Choreography를 혼합 적용하는 방식이 실무에서 자주 쓰인다.

코드 예시 1: Orchestrator 상태 전이

type SagaStep = "reserve" | "pay" | "ship";

export class OrderSagaOrchestrator {
  async execute(orderId: string) {
    try {
      await this.reserveInventory(orderId);
      await this.capturePayment(orderId);
      await this.requestShipping(orderId);
      return { status: "COMPLETED" };
    } catch (error) {
      await this.compensate(orderId);
      return { status: "COMPENSATED", reason: String(error) };
    }
  }

  private async compensate(orderId: string) {
    await this.refundPayment(orderId);
    await this.releaseInventory(orderId);
  }
}

코드 예시 2: Choreography 이벤트 소비자

export async function onPaymentCaptured(event: { orderId: string; amount: number }) {
  await publish("shipping.requested", { orderId: event.orderId });
}

export async function onShippingFailed(event: { orderId: string }) {
  await publish("payment.refund.requested", { orderId: event.orderId });
}

export async function onPaymentRefunded(event: { orderId: string }) {
  await publish("inventory.release.requested", { orderId: event.orderId });
}

아키텍처 흐름

Mermaid diagram rendering...

Clean Architecture 레이어 구조

Saga는 애플리케이션 레이어의 유즈케이스로 두고, 각 서비스 호출은 어댑터 레이어로 분리하면 보상 로직 테스트가 쉬워진다.

Layer책임적용 방식
Entities주문 상태 모델OrderAggregate
Use CasesSaga 흐름 제어ExecuteOrderSaga
Interface AdaptersPayment/Inventory 포트PaymentGatewayAdapter
Frameworks메시지 브로커/DBKafka, PostgreSQL

인프라 구성도

Mermaid diagram rendering...

트레이드오프

  • Orchestration은 흐름 가시성이 높지만 중앙 컴포넌트 장애가 전체 처리량에 영향을 준다.
  • Choreography는 결합도가 낮지만 이벤트 스키마 관리 실패 시 복잡도가 빠르게 증가한다.
  • 혼합 전략은 유연하지만 팀이 두 모델을 모두 이해해야 하므로 온보딩 비용이 든다.

정리

Saga 선택의 정답은 하나가 아니다. 도메인 복잡도와 운영 조직 역량을 기준으로 모델을 나누고, 보상 시나리오를 테스트 가능한 구조로 고정하면 분산 트랜잭션 리스크를 크게 줄일 수 있다.

이미지 출처

  • Cover: source link
  • License: CC BY-SA 4.0 / Author: Sandra Fauconnier and Alex Stinson
  • Note: Wikimedia Commons 무료 라이선스 이미지를 다운로드 후 1600px 기준 JPG로 최적화했습니다.

댓글