본문으로 건너뛰기
김신건의 로그

[Pattern] Saga: 분산 트랜잭션의 보상 흐름

· 수정 · 📖 약 1분 · 588자/단어 #saga #distributed-transaction #microservices #backend
Saga pattern, Choreography saga, Orchestration saga, compensating transaction, long-running transaction

정의

Saga = 여러 service 의 로컬 트랜잭션연결한 긴 흐름. 한 단계 실패 시 이전 단계의 보상 (compensating) 트랜잭션 으로 논리적 롤백.

IMPORTANT

Saga 는 ACID 트랜잭션이 아니다. 분산 환경에서 2PC (XA) 가 비현실적이라 eventually consistent + 보상 으로 대체.

시나리오: 주문

sequenceDiagram
    autonumber
    participant O as Order Service
    participant P as Payment Service
    participant I as Inventory Service
    participant S as Shipping Service

    O->>O: T1: 주문 생성 (pending)
    O->>P: T2: 결제 요청
    P-->>O: 결제 완료
    O->>I: T3: 재고 차감
    I-->>O: 차감 완료
    O->>S: T4: 배송 요청
    S-->>O: 배송 시작
    O->>O: T5: 주문 confirmed

실패 시 보상:

sequenceDiagram
    O->>P: T2 결제
    P-->>O: ✓
    O->>I: T3 재고
    I-->>O: 실패 (재고 부족)
    O->>P: C2: 결제 환불 (보상)
    O->>O: C1: 주문 취소 (보상)
단계Compensating
T1 주문 생성C1 주문 취소
T2 결제C2 환불
T3 재고 차감C3 재고 복원
T4 배송C4 배송 취소

두 스타일: Choreography vs Orchestration

1. Choreography (이벤트 기반)

flowchart LR
    O[Order] -->|OrderCreated| P[Payment]
    P -->|PaymentSucceeded| I[Inventory]
    I -->|StockReserved| S[Shipping]
    S -->|Shipped| O
    P -->|PaymentFailed| O
    I -->|StockUnavailable| P
  • 각 service 가 event 듣고 자기 일.
  • 중앙 제어자 없음.
  • 유연, 낮은 결합.
  • 흐름 추적 어려움 (어디까지 갔는지).

2. Orchestration (중앙 코디네이터)

flowchart LR
    Coord[Saga Orchestrator] --> O[Order]
    O -->|성공| Coord
    Coord --> P[Payment]
    P -->|성공| Coord
    Coord --> I[Inventory]
    I -->|실패| Coord
    Coord -->|보상| P
    Coord -->|보상| O
  • 중앙 상태 기계.
  • 흐름 명확.
  • 결합도 약간 높음 (orchestrator 가 모든 service 안)
  • 문제 추적 쉬움.
항목ChoreographyOrchestration
결합도낮음약간 높음
흐름 추적어려움쉬움
디버깅어려움쉬움
적합단순 흐름 (3-4 단계)복잡 흐름 (5+ 단계)
운영 도구event tracer상태 기계 시각화

TIP

3-4 단계까지는 choreography, 그 이상은 orchestration 이 일반 권장. Netflix 도 Conductor 라는 orchestrator 사용.

보상 트랜잭션의 함정

flowchart TD
    Q[보상이 *항상 가능* 한가?]
    Q --> X1["✗ 이메일 발송 (취소 불가)"]
    Q --> X2["✗ SMS / push 알림"]
    Q --> X3["✗ 외부 API 호출 (paypal 환불 한도)"]
    Q --> Sol1["→ 가능한 단계만 saga 안"]
    Q --> Sol2["→ 비가역 단계는 saga *마지막* 으로"]

CAUTION

비가역 작업 (이메일, push, 외부 API) 은 saga 가 commit 결정 후 실행. 그 전에 실행하면 보상 불가.

멱등성 + Idempotency Key

각 단계 / 보상은 멱등 (idempotent) 해야 한다. 자세한 건 idempotency-keys.

# 보상 시
async def compensate_payment(saga_id, payment_id):
    if already_refunded(saga_id):
        return                       # 멱등
    await payment_service.refund(payment_id, key=saga_id)

Saga 상태 저장

flowchart LR
    Orch[Orchestrator] --> Store[(Saga State Store)]
    Store --> SQL[(PostgreSQL)]
    Store --> Stream[(Kafka)]
    Store --> SF[(Step Functions)]
Store특징
PostgreSQL (DB)트랜잭션 친화
Kafka topicevent log 자연 통합
AWS Step Functionsmanaged orchestrator
Temporal워크플로 엔진
CamundaBPMN 표준

Temporal / Step Functions (워크플로 엔진)

flowchart LR
    SDK["Application code<br/>(workflow + activity)"] --> Temporal[Temporal Server]
    Temporal --> StateDB[(상태 DB)]
    Temporal --> Workers["Workers<br/>(activity 실행)"]
  • 워크플로 코드durable execution.
  • retry / timeout / sleep언어 native 처럼.
  • 마치 함수 호출 같은데 분산 + 영속.

흔한 함정

WARNING

  1. 모든 분산 흐름 = saga = 단순 async event 가 충분한데도 복잡한 saga. 진짜 보상 필요한 흐름에만.
  2. 보상 없거나 미구현 = “해피 패스만 만들고 실패는 운영자 처리”. 1년 뒤 데이터 불일치 폭증.
  3. Choreography 의 순환 의존성 = A → B → C → A 같은 흐름. 디버깅 지옥.
  4. 상태 저장 안 함 = orchestrator 다운 시 진행 잃음. event log 또는 DB 필수.

관련 위키

이 글의 용어 (5개)
[Distributed Systems] 분산 트랜잭션: 2PC, Saga, Outboxdistributed-systems
정의 분산 트랜잭션 은 여러 service / DB / 메시지 큐에 걸친 작업을 ACID 처럼 묶는 문제. 마이크로서비스 / 이벤트 기반 아키텍처의 핵심 도전. 3가지 접근: 1…
[Pattern] Event Sourcing: 상태 대신 이벤트 누적distributed-systems
정의 Event Sourcing = 현재 상태 대신 과거 이벤트 시퀀스 를 저장. 현재 상태 = event 모두 replay 한 결과. 핵심 약속 - 과거 모든 변화 기록. 감사…
[Pattern] Idempotency Keys: 중복 요청 안전 처리distributed-systems
정의 Idempotency = 같은 요청을 N번 보내도 결과가 1번과 동일. 분산 시스템 / 결제 / API 의 안전망. [!IMPORTANT] 네트워크는 항상 timeout /…
[Pattern] Microservices vs Monolith: 언제 분리, 언제 통합distributed-systems
정의 | | Monolith | Modular Monolith | Microservices | |---|---|---|---| | 배포 단위 | 1개 | 1개 (모듈 명확) | …
[Pattern] Outbox Pattern: DB + 메시지의 원자성distributed-systems
정의 Outbox Pattern = DB 변경 + 메시지 발행 의 원자성 보장. 이중 쓰기 (dual write) 문제 의 표준 해결. 문제: Dual Write | 시나리오 |…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기