온라인 쇼핑몰에서 사용자가 상품을 주문하는 과정을 상상해 봅시다. 이 간단해 보이는 작업 뒤에는 주문 서비스, 결제 서비스, 재고 서비스, 배송 서비스 등 수많은 마이크로서비스(Microservices)들이 분주하게 움직입니다.
그런데 만약 주문과 재고 차감은 성공했는데, 마지막 결제 서비스에서 오류가 나면 어떻게 될까요? 고객의 돈은 나가지 않았지만, 상품 재고는 줄어들고 주문은 생성된, 데이터가 뒤죽박죽인 상태가 됩니다. 전통적인 단일 서버 환경에서는 이 모든 과정을 하나의 트랜잭션(Transaction) 으로 묶어 "전부 성공하거나, 전부 실패(롤백)하거나"를 보장했지만, 여러 서비스에 걸친 작업을 이렇게 묶는 것은 거의 불가능에 가깝습니다.
이처럼 분산된 서비스들 간의 데이터 일관성을 유지하기 위해 고안된 우아한 해결책이 바로 사가 패턴(Saga Pattern) 입니다.
사가 패턴이란? 실패를 보상하는 여정
사가(Saga) 는 여러 서비스에 걸쳐 있는 하나의 긴 비즈니스 프로세스를 의미합니다. 이 프로세스는 여러 개의 로컬 트랜잭션(Local Transaction) 과, 실패 시 각 트랜잭션의 변경 사항을 되돌리는 보상 트랜잭션(Compensating Transaction) 으로 구성됩니다.
쉽게 말해, "일단 앞으로 한 걸음씩 전진하되, 만약 중간에 넘어지면, 왔던 길을 정확히 거꾸로 되짚어 원점으로 돌아오라"는 규칙을 정해두는 것입니다. 👣
예를 들어, '상품 주문'이라는 사가(Saga)는 다음과 같이 구성됩니다.
- 주문 생성 (트랜잭션 1): 주문 서비스가 주문을 생성한다.
- (실패 시 보상 트랜잭션): 생성된 주문을 '취소' 상태로 변경한다.
- 결제 처리 (트랜잭션 2): 결제 서비스가 결제를 시도한다.
- (실패 시 보상 트랜잭션): 승인된 결제를 '취소(환불)'한다.
- 재고 차감 (트랜잭션 3): 재고 서비스가 상품 재고를 줄인다.
- (실패 시 보상 트랜잭션): 차감했던 재고를 다시 '원복(증가)'시킨다.
만약 3단계인 '재고 차감'에서 실패하면, 사가는 2단계의 보상 트랜잭션('결제 취소')과 1단계의 보상 트랜잭션('주문 취소')을 역순으로 실행하여 시스템의 데이터 상태를 여정이 시작되기 전과 동일하게 만듭니다.
사가를 지휘하는 두 가지 방법: 코레오그래피 vs. 오케스트레이션
이 사가의 흐름을 관리하는 방식에는 크게 두 가지가 있습니다.
- 코레오그래피 (Choreography) 💃: 중앙 지휘자 없이, 각 서비스가 이벤트(Event) 를 통해 서로의 작업을 알아서 촉발시키는 방식입니다. 마치 무대 위의 댄서들이 서로의 동작을 보고 다음 동작을 이어나가는 군무와 같습니다.
- 주문 서비스가 "주문이 생성되었음!" 이벤트를 발행하면, 결제 서비스가 그 이벤트를 구독하여 결제를 시작하고, 결제가 성공하면 "결제 완료됨!" 이벤트를 발행합니다. 재고 서비스는 또 그 이벤트를 받아 재고를 차감합니다.
- 장점: 서비스 간의 결합도가 낮고, 구조가 단순하고 유연합니다.
- 단점: 전체 프로세스의 흐름을 파악하기 어렵고, 서비스가 많아지면 어떤 서비스가 어떤 이벤트를 구독하는지 추적하기가 복잡해집니다.
- 오케스트레이션 (Orchestration) 👨✈️: '사가 실행 오케스트레이터(Saga Execution Orchestrator)' 라는 중앙 지휘자가 전체 프로세스를 관리하는 방식입니다. 오케스트라의 지휘자가 각 악기 파트에게 연주 순서를 지시하는 것과 같습니다.
- 오케스트레이터가 주문 서비스에게 "주문 생성해!"라고 명령하고, 작업이 끝나면 결제 서비스에게 "결제 처리해!"라고 명령하는 식입니다. 만약 실패하면, 오케스트레이터가 직접 보상 트랜잭션을 순서대로 명령합니다.
- 장점: 전체 비즈니스 프로세스가 한 곳에 명확하게 정의되어 이해하고 관리하기 쉽습니다.
- 단점: 오케스트레이터 자체에 로직이 집중되고, 서비스들이 오케스트레이터에 강하게 의존하게 됩니다.
사가 패턴은 만능일까?
사가 패턴은 분산 트랜잭션 문제를 해결하는 강력한 도구이지만, 최종 일관성(Eventual Consistency) 모델을 기반으로 한다는 점을 기억해야 합니다. 즉, 사가가 진행되는 중간 과정에는 데이터가 일시적으로 불일치하는 상태가 존재할 수 있습니다. (예: 주문은 생성되었지만 아직 결제는 안 된 상태)
따라서 모든 서비스가 실시간으로 완벽하게 동기화되어야 하는 강력한 일관성(Strong Consistency) 이 필수적인 은행의 계좌 이체 같은 작업보다는, 대부분의 전자상거래 주문 프로세스처럼 약간의 지연을 허용할 수 있는 비즈니스 로직에 더 적합합니다.
마치며
사가 패턴은 마이크로서비스 아키텍처에서 "모 아니면 도" 식의 원자적(Atomic) 트랜잭션을 흉내 내기 위한 현실적인 대안입니다. 각 서비스의 독립성은 유지하면서도, 전체 비즈니스 프로세스의 데이터 무결성을 보장하는 균형점을 제공하죠.
"실패는 당연히 일어날 수 있다. 중요한 것은 실패했을 때 어떻게 우아하게 원상 복구할 것인가?" 라는 질문에 대한 성숙한 답변. 그것이 바로 사가 패턴의 핵심 철학입니다. 🌟