이번글은 MSA 환경에서 데이터의 일관성을 보장해주기 위한 Saga Pattern에 대해 정리한 글입니다.
데이터 일관성
기존의 모놀리식 환경에서는 하나의 DBMS가 트랜잭션의 원자성과 일관성을 보장해줬습니다.
즉, 어떤 작업 중 일부가 실패하더라도, 전체 트랜잭션을 간단한게 롤백할 수 있었습니다.
하지만 MSA에서는 하나의 기능이 여러 개의 마이크로서비스에 걸쳐 동작하게 됩니다.
즉, 전체 트랜잭션이 하나의 DB에서 처리되는 것이 아닌, 여러 마이크로서비스의 개별적은 로컬 트랜잭션들이 조합된 형태가 됩니다.
MSA에서는 DBMS가 제공하던 트랜잭션 기능만으로 전체 시스템의 일관성을 유지하기가 어렵습니다.
한다고 해도, 하나의 서비스라도 실패 하면, 데이터의 일관성이 깨지는 큰 문제가 발생하게 됩니다.
사가 패턴
앞서 나온 문제를 해결하기 위해서 Saga Pattern이 등장하게 됩니다.
사가 패턴은 각 서비스가 자체적으로 수행하는 로컬 트랜잭션의 흐름을 메시지 또는 이벤트를 통해 이어가는 방식입니다.
예를 들어, 전자상거래 시스템에서 고객의 신용 한도 내에서 주문을 생성해야 하는 시나리오를 생각해볼 수 있습니다.
주문 생성 트랜잭션이 완료되면 "주문 생성됨" 이벤트를 발행하고, 이를 수신한 고객 서비스가 신용 한도를 차감하는 트랜잭션을 수행합니다. 만약 중간 단계에서 어떠한 트랜잭션이 비즈니스 규칙을 위반하여 실패한다면, 이전 단계에서 수행한 작업들을 되돌리기 위한 보상 트랜잭션을 실행합니다.
사가 패턴은 문제 발생시 롤백을 사용하지 않고, 보상을 통해 트랜잭션의 전체의 일관성을 간접적으로 유지하는 방식입니다.
즉, MSA 환경에서 트랜잭션 간 결합도를 낮추면서도 데이터 정합성을 유지할 수 있는 방식입니다.
사가와 2PC방식의 비교
과거에는 분산 트랜잭션의 일관성을 보장하기 위해서 2PC(Two-Phase Commit)방식이 사용되었습니다.
2PC는 하나의 분산트랜잭션이 여러 데이터베이스에 걸쳐 있을 때, 모든 참여자가 커밋 가능한지(1단계:prepare)를 먼저 확인하고, 모두 준비가 되었다면 한꺼번에 커밋(2단계:commit)하도록 원자성을 보장하는 방식입니다.
원자성을 보장한다는 장점이 있지만, 아래와 같은 단점도 존재합니다.
- 트랜잭션 전체를 조율하는 Coordinator가 중간에 멈추거나 네트워크에 문제가 생기는 경우, 트랜잭션이 끝나지 못하고 모든 참여 서비스가 계속 기다려야 하는 장애 상황에 취약합니다.
- 여러 시스템이 동시에 처리되는 동안, 각 데이터베이스가 트랜잭션 락을 오랫동안 유지해야 되므로 시스템 전체 성능이 떨어질 수 있습니다.
- 참여하는 시스템(노드)가 많아질수록, 조율 과정도 복잡해지고 실패할 가능성도 더 커집니다.
- MSA는 각각 자신만의 DB와 트랜잭션을 독립적으로 관리하는 구조인데, 2PC는 이들을 하나로 묶어서 처리하는 부분이 MSA의 철학과도 맞지 않습니다.
사가를 사용하는 2가지 방식
사가를 사용하는 방법에는 Choreography방식과 Orchestration 방식이 있습니다.
Choreography방식은 각 로컬 트랜잭션이 도메인 이벤트를 발행하고, 그 이벤트가 다른 서비스의 로컬 트랜잭션을 트리거 하는 방식입니다. Orchestration 방식은 Orchestrator라는 객체가 각 서비스에게 어떤 로컬 트랜잭션을 실행할지 지시하는 방식입니다.
Choreography 기반의 사가
전자상거래 어플리케이션을 예시로 흐름을 살펴보면 다음과 같습니다.
- Order 서비스가 POST /orders 요청을 받고, 주문을 PENDING 상태로 생성합니다.
- 그런 다음, Order Created 이벤트를 발행합니다.
- Customer 서비스의 이벤트 핸들러가 해당 이벤트를 수신하고, 신용 한도를 예약하려 시도합니다.
- 그런 다음, 처리 결과를 나타내는 이벤트를 발행합니다.
- Order 서비스의 이벤트 핸들러는 이 결과를 수신하고, 주문을 승인(approve)하거나 거절(reject)합니다.
이 방식의 장점은 구성과 운영이 비교적 간편하다는 점입니다.
또한, 하나의 서비스에 문제가 생기더라도 나머지 시스템 전체에는 영향이 적게 미치는 구조를 만들 수 있습니다.
하지만, 단점도 존재합니다. 사가에 참여하는 서비스가 많아질수록 트랜잭션 흐름이 복잡해지고, 서로 이벤트를 주고받는 과정에서 서비스간 순환 의존이 생길 위험이 있습니다.
결과적으로, 마이크로 서비스들 간의 결합도가 높아져 MSA의 핵심인 유연성과 독립성이 저해될 수 있습니다.
Orchestration 기반의 사가
1. Orchestrator는 주문을 PENDING 상태로 생성합니다.
2. Customer 서비스에 Reserve Credit(신용 한도 예약) 명령(command)을 보냅니다.
3. Customer 서비스는 신용 한도를 예약하려 시도하고, 그 결과를 나타내는 응답 메시지(reply message)를 다시 보냅니다.
4. Orchestrator는 이 결과를 바탕으로 주문을 승인(approve)하거나 거절(reject)합니다.
이 방식의 장점은 트랜잭션 흐름이 명확하다는 점입니다.
오케스트레이터가 전체 트랜잭션을 직접 제어하기 때문에, 각 단계의 진행 상황을 추적하고 관리하기가 쉽습니다.
또한, 각 마이크로서비스는 오케스트레이터와만 통신하고 서로를 직접 참조하지 않기 때문에 서비스 간 결합도가 낮고, 독립적인 개발과 배포가 가능합니다.
하지만 단점도 존재합니다. 트랜잭션의 흐름이 오케스트레이터에 집중되기 때문에, 해당 컴포넌트가 장애를 일으키면 전체 시스템이 영향을 받을 수 있는 단일 장애 지점(SPOF)이 됩니다. 또한 모든 흐름이 중앙에서 관리되므로 시스템 구조가 경직되고, 확장성과 유연성이 떨어질 수 있습니다.
사가 패턴 장점 및 단점
분산 트랜잭션을 사용하지 않아도 여러 마이크로서비스 간에 데이터 일관성을 유지할 수 있다는 장점이 있습니다.
하지만, ACID 트래잭션처럼 자동으로 전체 작업을 롤백하지 못한다는 점으로 인해 보상 트랜잭션(ex 주문 취소, 결제 취소)을 직접 개발자가 설계해야 하고, ACID의 격리성이 없기 때문에, 동시에 실행되는 경우 데이터 충돌이나 불일치가 발생할 수 있어서 격리성을 보완하는 설계(Lock, 버전 확인, 순차 처리)해야 하는 단점이 존재합니다.
출처
'아키텍쳐' 카테고리의 다른 글
DDD(도메인 주도 설계) (0) | 2025.03.24 |
---|---|
데코레이터 패턴 (0) | 2025.03.06 |
프록시 & 프록시 패턴 (0) | 2025.03.05 |
API 멱등성 (0) | 2025.02.02 |
VO(Value Obejct) (0) | 2025.01.31 |