252. 사가 패턴 (Saga Pattern)
핵심 인사이트 (3줄 요약)
- 본질: 사가 패턴은 분산 환경에서 여러 서비스에 걸친 긴 트랜잭션을 관리하기 위해, 각 단계마다 보상 트랜잭션(Compensating Transaction)을 정의하여 부분 실패 시 이전 단계를 역순으로 취소하는 분산 트랜잭션 관리 기법이다.
- 가치: 2단계 커밋(2PC)의 블로킹 문제를 피하면서, 마이크로서비스 간 데이터 일관성을 결과적 일관성(Eventual Consistency) 수준으로 보장한다.
- 융합: 마이크로서비스 아키텍처에서 서비스 간 트랜잭션 관리를 위한 표준 패턴으로, 이벤트 기반 아키텍처, 보상 트랜잭션, CQRS와 밀접하게 연관된다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
개념 정의
사가 패턴은 1987년 Hector Garcia-Molina와 Kenneth Salem이 발표한 개념으로, 분산 환경에서长年全球 트랜잭션을 관리하기 위한 방법론이다. 전체를 하나의 원자적 트랜잭션으로 묶는 대신, 각 단계의 보상(Compensation)을 미리 정의하여 어떤 단계에서 실패하면 이전 단계의 보상을 역순으로 실행한다.
필요성
마이크로서비스 환경에서는 여러 서비스에 데이터를跨서 작업이 필요한 경우가 많다. 그러나 2PC는 블로킹 문제와 코디네이터 실패 시 전체 교착 위험이 있어 대규모 분산 환경에서는 비실용적이다. 사가는 이 문제를 보상 트랜잭션으로 해결한다. 금융 시스템의 송금, 전자상거래의 주문 처리, 예약 시스템 등跨서비스业务流程에서 필수적으로 활용된다.
배경
전통적 RDBMS의 ACID 트랜잭션은 단일 데이터베이스 내 원자성을 보장하지만, 서비스가 분리된 마이크로서비스架构에서는 각 서비스가 독립적인 데이터베이스를 보유한다. 이 경우 글로벌 트랜잭션의 원자성을 보장하기 위해 2PC를 사용하지만, 코디네이터의 장애나 네트워크 분단 시 전체 시스템이 블로킹되는 문제가 있다. 사가 패턴은 이러한 한계를 인식하고, 원자성 대신 결과적 일관성을 제공하는 대안적 접근법이다.
비유
사가 패턴은 여행사의 예약 시스템과 같다. 각 여행사에서는 항공편, 호텔, 보험을 개별 예약하고, 어느 하나가 실패하면 이전 예약을 역순으로 취소하여 전체 일관성을 유지한다. 모든 예약을 동시에 확정 짓는 것이 아니라, 각 단계의 보상을 미리 준비하는 것이 핵심이다.
📢 섹션 요약: 사가 패턴은 분산 환경에서 완전한 원자성 대신, 각 단계의 보상을 미리 정의하여 부분 실패 시 역순 보상을 수행하는-eventual consistency 기반의 트랜잭션 관리 패턴이다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
Saga 동작 구조
┌───────────────────────────────────────────────────────────────────────────┐
│ 사가 패턴 동작 과정 │
├───────────────────────────────────────────────────────────────────────────┤
│ │
│ [정상 흐름] │
│ │
│ Step 1: 항공권 예약 ──▶ 성공 │
│ │ │
│ ▼ │
│ Step 2: 호텔 예약 ──▶ 성공 │
│ │ │
│ ▼ │
│ Step 3: 보험 가입 ──▶ 성공 │
│ │ │
│ ▼ │
│ 완료 │
│ │
│ [실패 및 보상 흐름] │
│ │
│ Step 1: 항공권 예약 ──▶ 성공 │
│ │ │
│ ▼ │
│ Step 2: 호텔 예약 ──▶ 실패 발생 │
│ │ │
│ ▼ │
│ Compensate Step 1: 항공권 예약 취소 ──▶ 성공 │
│ │ │
│ ▼ │
│ 실패 처리 │
│ │
└───────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설]
사가의 핵심은 사전 보상 정의이다. 각 단계에서 실패할 경우를 대비하여, 해당 단계의
undo 연산을 미리 정의한다. 호텔 예약이 실패하면, 이미 성공한 항공권 예약을 취소하는
보상 트랜잭션을 실행한다. 중요한 점은 사가가 원자성을 보장하지 않는다는 것이다.
전체가 성공하거나, 보상까지 모두 완료된 결과적 일관성만을 보장한다. 중간에 보상
자체도 실패하면 별도의 비즈니스 수준 처리가 필요하다.
Saga vs 2PC 비교
┌─────────────────────────────────────────────────────────────────────────────┐
│ Saga vs 2PC 핵심 비교 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┬─────────────────────┬─────────────────────┐ │
│ │ 구분 │ Saga │ 2PC │ │
│ ├────────────────┼─────────────────────┼─────────────────────┤ │
│ │ Blocking │ 없음 │ 있음 │ │
│ ├────────────────┼─────────────────────┼─────────────────────┤ │
│ │ 원자성 │ 결과적 일관성 │ 완전한 원자성 │ │
│ ├────────────────┼─────────────────────┼─────────────────────┤ │
│ │ 복구 방식 │ 보상 트랜잭션 │ 자동 UNDO/REDO │ │
│ ├────────────────┼─────────────────────┼─────────────────────┤ │
│ │ 지연 시간 │ 각 단계별 독립 대기 │ 전체 대기 │ │
│ ├────────────────┼─────────────────────┼─────────────────────┤ │
│ │ 코디네이터 │ 불필요 또는 단순 │ 필수 (장애 시 복구) │ │
│ │ 장애 위험 │ 낮음 │ 높음 │ │
│ ├────────────────┼─────────────────────┼─────────────────────┤ │
│ │ 적합 시나리오 │ 긴 트랜잭션, MSA │ 단일 DB, 금융 트랜잭션│ │
│ └────────────────┴─────────────────────┴─────────────────────┘ │
│ │
│ 핵심 결론: │
│ 2PC는 단일 DB 또는 신뢰할 수 있는 네트워크에서 강한 일관성이 필요한 경우 │
│ Saga는 네트워크 분단이 발생할 수 있는 MSA 환경에서 가용성과 유연성이 │
│ 필요한 경우에 적합하다. │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 2PC는 모든 참여자가 준비 상태에서 커밋 또는 롤백을 동시에 결정하는 방식이다. 커밋 결정 전까지 모든 참여자가 블로킹되며, 코디네이터 장애 시 참여자가 영구적으로 기다릴 수 있다. 반면 사가는 각 단계가 독립적으로 보상을 정의하므로 블로킹이 없고, 단계별 실패에 대한 대응이 명확하다. 그러나 결과적 일관성만을 보장하므로, 완전한 원자성이 필요한 금융 거래 등에는 부적합할 수 있다.
Saga 구현 방식
┌─────────────────────────────────────────────────────────────────────────────┐
│ Saga 구현 방식: 코레오그래피 vs 오케스트레이션 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ [코레오그래피 방식] │
│ │
│ ┌──────────┐ 이벤트 ┌──────────┐ 이벤트 ┌──────────┐ │
│ │ 서비스 A │ ───────▶ │ 서비스 B │ ───────▶ │ 서비스 C │ │
│ │航空권 예약│ │호텔 예약 │ │보험 가입 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ▲ ▲ │ │
│ │ 보상 이벤트 │ 보상 이벤트 │ │
│ └──────────────────────────┴──────────────────────────┘ │
│ │
│ 장점: 서비스 간 결합도 낮음, 확장성 우수 │
│ 단점: 흐름 파악 어려움, 디버깅 복잡 │
│ │
│ [오케스트레이션 방식] │
│ │
│ ┌──────────────────┐ │
│ │ Saga 오케스트레이터│ │
│ │ (중앙 조정자) │ │
│ └────────┬─────────┘ │
│ │ │
│ ┌──────────────┼──────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 서비스 A │ │ 서비스 B │ │ 서비스 C │ │
│ │항공권 예약│ │호텔 예약 │ │보험 가입 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ 장점: 흐름 명확, 오류 처리 용이, 테스트 용이 │
│ 단점: 오케스트레이터에 결합도 집중, 단일 장애점 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 코레오그래피 방식에서는 각 서비스가 이벤트를 발행하고 다른 서비스가 구독하는 구조로, 서비스 간 결합도가 낮고 확장성이 우수하다. 그러나 전체 흐름을 한눈에 파악하기 어렵고, 장애 발생 시 디버깅이 어렵다. 오케스트레이션 방식에서는 중앙 오케스트레이터가 전체 흐름을 조정하므로 흐름이 명확하고 오류 처리가 용이하지만, 오케스트레이터에 결합도가 집중되고 단일 장애점이 될 수 있다.
📢 섹션 요약: 사가 패턴은 코레오그래피(분산형) 또는 오케스트레이션(중앙 집중형)으로 구현되며, 보상 트랜잭션을 통한 역순 취소를 통해 분산 환경에서 결과적 일관성을 달성한다.
Ⅲ. 구현 및 실무 응용 (Implementation & Practice)
실무 시나리오: 전자상거래 주문 처리
-- 사가 패턴 주문 처리 시나리오 (의사 코드)
-- Step 1: 재고 확인 및 예약
UPDATE inventory
SET reserved_quantity = reserved_quantity + 1
WHERE product_id = 'PROD-001' AND available_quantity >= 1;
-- 보상: 재고 예약 취소
-- UPDATE inventory
-- SET reserved_quantity = reserved_quantity - 1
-- WHERE product_id = 'PROD-001';
-- Step 2: 결제 처리
INSERT INTO payments (order_id, amount, status)
VALUES ('ORDER-001', 50000, 'PENDING');
-- 보상: 결제 취소
-- UPDATE payments SET status = 'CANCELLED' WHERE order_id = 'ORDER-001';
-- Step 3: 배송 예약
INSERT INTO shipments (order_id, status)
VALUES ('ORDER-001', 'RESERVED');
-- 보상: 배송 예약 취소
-- DELETE FROM shipments WHERE order_id = 'ORDER-001';
###补偿 트랜잭션 구현 예시
# Python 의사 코드: Saga 보상 트랜잭션 구현
class OrderSaga:
def execute(self, order_id):
try:
# Step 1: 재고 예약
self.reserve_inventory(order_id)
# Step 2: 결제 처리
self.process_payment(order_id)
# Step 3: 배송 예약
self.reserve_shipment(order_id)
return Success()
except InventoryException:
# 보상 불필요 (첫 단계)
return Failure("재고 부족")
except PaymentException:
# Step 1 보상 실행
self.cancel_inventory_reservation(order_id)
return Failure("결제 실패")
except ShipmentException:
# Step 1, 2 보상 실행
self.cancel_payment(order_id)
self.cancel_inventory_reservation(order_id)
return Failure("배송 예약 실패")
안티패턴 및 주의사항
┌─────────────────────────────────────────────────────────────────────────────┐
│ Saga 패턴 안티패턴 및 주의사항 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ❌ 안티패턴 1: 보상 미정의 │
│ 실패 시 보상 트랜잭션이 정의되지 않으면, 부분 완료된 상태에 놓이게 되어 │
│ 데이터 불일치가 발생할 수 있다. 각 단계의 보상은 필수로 정의해야 한다. │
│ │
│ ❌ 안티패턴 2: 보상 실패 처리 부재 │
│ 보상 자체가 실패할 경우를 대비한 재시도 정책이나 관리자 알림이 필요하다. │
│ 무한 재시도는 시스템을 불안정하게 만들 수 있다. │
│ │
│ ❌ 안티패턴 3: 교차 트랜잭션 의존성 │
│ 사가 내에서 보상 중 다른 사가 트랜잭션의 자원에 접근하면 데드락이 발생할 수 │
│ 있다. 보상 시에는 독립적인 자원만 접근해야 한다. │
│ │
│ ✅ 올바른 설계: │
│ • 보상은幂등하도록 설계 (여러 번 실행해도 결과 동일) │
│ • 보상 순서를明确规定 (역순 실행 보장) │
│ • 보상 실패 시 알림 및 수동 개입 절차 마련 │
│ • 보상 작업도 별도의 모니터링 시스템으로 추적 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
📢 섹션 요약: 사가 패턴의 보상 트랜잭션은 각 단계마다 명확히 정의되어야 하며, 보상은幂等하고 보상 실패 시 대응 방안이 마련되어야 한다.
Ⅳ. 품질 관리 및 테스트 (Quality & Testing)
Saga 테스트 전략
┌─────────────────────────────────────────────────────────────────────────────┐
│ Saga 패턴 테스트 전략 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1.happy path 테스트 │
│ 모든 단계가 정상적으로 완료되는 경우를 테스트한다. │
│ │
│ 2. 부분 실패 테스트 │
│ 각 단계에서 실패가 발생하고, 보상이 올바른 순서로 실행되는지 테스트한다. │
│ - 1단계 실패: 보상 불필요, 상태 확인 │
│ - 2단계 실패: 1단계 보상 실행, 전체 롤백 확인 │
│ - 3단계 실패: 1, 2단계 보상 순차 실행 확인 │
│ │
│ 3. 보상 실패 테스트 │
│ 보상 자체가 실패하는 경우의 동작을 테스트한다. │
│ - 재시도 횟수, 알림, 수동 개입 절차 확인 │
│ │
│ 4. 동시성 테스트 │
│ 동일한 주문에 대한 동시 요청이 올바르게 처리되는지 확인한다. │
│ │
│ 5. 장애 복구 테스트 │
│ Saga 실행 중 서비스 장애, 네트워크 단절 등의 상황을仿真하여 │
│ 시스템이 안전한 상태로 복구되는지 확인한다. │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Saga 모니터링 지표
┌─────────────────────────────────────────────────────────────────────────────┐
│ Saga 모니터링 핵심 지표 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ • 사가 완료율: 전체 사가 중 정상 완료 비율 (목표: 99.9%+) │
│ • 평균 사가 소요 시간: 각 단계별 소요 시간 추적 │
│ • 보상 발생률: 전체 사가 중 보상이 발생한 비율 │
│ • 보상 실패율: 보상 시도 중 실패한 비율 ( kritisch: 즉각 알림) │
│ • 보상 평균 소요 시간: 보상 트랜잭션의 평균 실행 시간 │
│ • 부분 완료 상태 건수: 보상이 완료되지 않은 상태의 건수 (정기적 모니터링) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
📢 섹션 요약: 사가 패턴의 테스트는happy path뿐 아니라 각 단계의 실패 시나리오와 보상 실패, 동시성, 장애 복구를 포함해야 하며, 지속적인 모니터링이 필수적이다.
Ⅴ. 최신 트렌드 및 결론 (Trends & Conclusion)
최신 트렌드
사가 패턴은 마이크로서비스 아키텍처의 성숙과 함께 더욱 중요해지고 있다. 최근에는 다음과 같은 발전이 있다. 첫째, 사가 프레임워크의 표준화로 Apache Camel, Eventuate Tram, AWS Step Functions 등이 Saga 구현을 지원한다. 둘째, 사가와 이벤트 소싱(Event Sourcing)의 결합으로, 트랜잭션 히스토리를 이벤트 로그로 저장하여 감사 및 장애 복구에 활용한다. 셋째, CQRS와 사가의 결합으로, 명령(Write)과 查询(Read)操作的을 분리하여 확장성을 높인다.
CAP 정리와의 관계
사가 패턴은 CAP 정리에서 AP(가용성 + 분단 내성) 시스템에 해당한다. 네트워크 분단이 발생해도 서비스를 계속 운영할 수 있으며, 일관성은 결과적 일관성으로 대체된다. 이는金融같은 강한 일관성이 필요한 시스템에는 부적합하지만,sns나E-커머스처럼 가용성이 중요한 시스템에는 적합하다.
미래 전망
사가 패턴은 서버리스(Serveless) 컴퓨팅과 컨테이너 기반 마이크로서비스의 확산에 따라 더욱 보편화될 것으로 예상된다. 특히 오케스트레이션 플랫폼의 발전으로, 개발자가 보상 로직에만 집중하고 실행 환경은 플랫폼이 관리하는 방향으로 진화하고 있다.
결론
사가 패턴은 분산 환경에서 2PC의 한계를 보완하는 유연한 방법을 제공하지만, 원자성이 아닌 결과적 일관성만을 보장한다는 한계를 가진다. 따라서 강한 일관성이 필요한 금융/결제 시스템에는 2PC나 분산 트랜잭션 관리자를, 가용성과 확장성이 중요한E-커머스/소셜 서비스에는 사가 패턴을 선택적으로使用해야 한다.
📢 섹션 요약: 사가 패턴은 MSA 환경에서 필수적인 분산 트랜잭션 관리 기법으로, 보상 트랜잭션을 통한 결과적 일관성을 제공하며, 시스템 요구사항에 따라 2PC와 적절히 선택 사용하여야 한다.
핵심 인사이트 ASCII 다이어그램 (Concept Map)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Saga Pattern Concept Map │
│ │
│ ┌──────────────────┐ │
│ │ Saga Pattern │ │
│ │ (분산 트랜잭션) │ │
│ └────────┬─────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │Compensating │ │Eventual │ │ Choreography │ │
│ │Transaction │ │Consistency │ │ vs │ │
│ │ (보상 트랜잭션)│ │ (결과적 일관성)│ │ Orchestration│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 보상 순차 │ │ CAP 정리 │ │ MSA 패턴 │ │
│ │ 실행 (역순) │ │ AP 시스템 │ │ (마이크로서비스)│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ 관련 기술: 2PC, 보상 트랜잭션, CQRS, Event Sourcing, AWS Step Functions │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
참고
- Saga 패턴은 2PC의 블로킹 한계를 해결하지만, 완전한 원자성 대신 결과적 일관성만을 보장한다.
- 보상 트랜잭션은 각 단계에서 실패할 경우를 대비하여 반드시 사전에 정의해야 한다.
- 코레오그래피와 오케스트레이션 중 시스템 요구사항에 맞는 구현 방식을 선택해야 한다.