들어가며
이전 포스팅에서 Saga 패턴의 기본 개념에 대해 다뤘었는데, 실제로 설계를 진행하면서 오케스트레이션과 코레오그래피 패턴에 대해 더 깊이 이해하게 되었습니다. 이번 포스팅에서는 그 깨달음을 공유하고, 실제 프로젝트에 어떻게 적용했는지 소개하겠습니다.
오케스트레이션 vs 코레오그래피 - 핵심 차이점
오케스트레이션 (Orchestration)
A → B → A
오케스트레이션은 중앙 조정자(Orchestrator)가 있어서 흐름이 다시 조정자로 돌아오는 구조입니다. 마치 지휘자가 오케스트라를 지휘하듯이, 하나의 서비스가 전체 트랜잭션 흐름을 제어합니다.
특징:
- 중앙 집중식 제어
- 명확한 트랜잭션 흐름 파악 가능
- 복잡한 비즈니스 로직 처리에 유리
코레오그래피 (Choreography)
A → B → C
코레오그래피는 각 서비스가 독립적으로 이벤트를 발행하고 구독하면서 흐름이 진행되는 구조입니다. 발레 군무처럼 각자가 자신의 역할을 수행하며 전체 흐름을 만들어냅니다.
특징:
- 분산된 제어
- 서비스 간 느슨한 결합
- 단순한 흐름에 적합
0차 설계 - 순수 오케스트레이션
이전 포스팅에서도 말씀드렸지만
완전 처음 기획할 때는 오케스트레이션으로 기획을 했습니다.!
문제점 발견
하지만 오케스트레이션으로 진행을 하고자 하였더니 Order쪽에 너무 많은 책임이 생겨 Order 서비스가 다운 된다면 다른 서비스들도 사용할 수 없게 된다는 것을 알게 되었습니다.
이렇게 된다면 MSA로 프로젝트를 하는게 의미 없다고 생각이 들었습니다.
1차 설계 - 순수 코레오그래피
전체 흐름을 코레오그래피로 설계했습니다.

흐름:
- Order → Inventory (재고 확인)
- Inventory → Payment (결제 처리)
- Payment → Delivery (배송 처리)
- Delivery → Notification (알림 발송)
각 서비스가 이벤트를 발행하고, 다음 서비스가 이를 구독하는 방식이었습니다.
문제점 발견
이렇게 설계하다 보니 결제 완료 후 주문 서비스에 결과를 알려주는 것이 필요하다는 것을 깨달았습니다.
주문 서비스는 전체 주문 상태를 관리하는 핵심 서비스인데, 결제가 완료되었는지 직접적으로 알 수 없는 구조였죠. 이는 다음과 같은 문제를 야기할 수 있습니다:
- 주문 상태 업데이트 지연
- 주문 조회 시 정확한 상태 반영 불가
- 후속 처리(배송 등) 시작의 불명확성
2차 설계 - 하이브리드 접근
이러한 문제를 해결하기 위해 오케스트레이션과 코레오그래피를 혼합한 하이브리드 구조로 재설계했습니다.

설계 구조
1단계: Order → Payment (코레오그래피)
Order → Inventory → Payment → Order (결제 완료 이벤트)
- 주문부터 결제까지는 코레오그래피 방식
- Payment가 완료되면 Order로 결제 완료 이벤트 발행
- Order는 결제 상태를 명확히 파악 가능
2단계: Order → Delivery (오케스트레이션)
Order → Delivery → Order (배송 상태 업데이트)
- 결제 완료 확인 후 Order가 Delivery에 배송 요청
- 배송 처리 결과를 다시 Order가 받아서 처리
- Order가 전체 흐름의 조정자 역할
하이브리드 구조의 장점
- 명확한 상태 관리
- Order 서비스가 주문의 전체 생명주기를 추적 가능
- 결제 완료 시점을 명확히 알 수 있음
- 유연한 확장성
- 재고-결제 부분은 각 서비스가 독립적으로 동작
- 배송 로직은 Order가 제어하여 복잡한 비즈니스 규칙 적용 가능
- 적재적소의 패턴 활용
- 단순한 흐름: 코레오그래피로 느슨한 결합 유지
- 복잡한 제어: 오케스트레이션으로 명확한 관리
이벤트 흐름 상세
정상 흐름
1. OrderCreatedEvent (Order → Inventory)
2. InventoryDeductedEvent (Inventory → Payment)
3. PaymentCompletedEvent (Payment → Order)
4. DeliveryAssignedEvent (Order → Delivery)
5. DeliveryCreatedEvent (Delivery → Notification)
Rollback 처리
각 단계에서 실패 시:
- inventory_rollback: 재고 복구
- Payment_rollback: 결제 취소
- delivery_rollback: 배송 취소
모든 rollback 이벤트는 해당 서비스가 처리 후 필요한 보상 트랜잭션을 실행합니다.
구현 시 고려사항
1. 이벤트 네이밍
- DLQ(Dead Letter Queue): {service}_dlq
- 이벤트 토픽: {service}_events
- Outbox DB: {service}_outbox_db
2. 멱등성 보장
- 각 이벤트는 고유한 ID를 가져야 함
- 중복 처리 방지를 위한 이벤트 로그 관리
3. 트랜잭셔널 아웃박스
- DB 저장과 이벤트 발행의 원자성 보장
- After_Commit 시점에 Transactional Event 발행
마치며
Saga 패턴을 실제로 설계하면서 오케스트레이션과 코레오그래피는 이분법적으로 선택할 것이 아니라, 상황에 맞게 조합해서 사용하는 것이 중요하다는 것을 배웠습니다.
특히 주문 시스템처럼 명확한 비즈니스 주체가 있는 경우, 그 주체(Order)가 중요한 전환점에서 상태를 파악하고 제어하도록 하는 것이 시스템의 일관성과 추적성을 높이는 데 도움이 됩니다.
'👍코드 회고' 카테고리의 다른 글
| Outbox와 DLQ 아키텍처 설계 (0) | 2025.12.01 |
|---|---|
| Saga 패턴 (0) | 2025.11.25 |
| N+1 (10.17) (0) | 2025.10.17 |
| 리팩토링 vs 오버 엔지니어링 (10.16) (0) | 2025.10.16 |
| 장바구니 코드 속 store_id는 어디에 둘까? (10.15) (0) | 2025.10.15 |