[System Design] 분산 트랜잭션의 딜레마: Saga 패턴은 과연 데이터 정합성의 구원자인가?
단일 데이터베이스 환경에서의 ACID 트랜잭션은 더 이상 MSA(Microservices Architecture)에서 통용되지 않는다. 서비스마다 DB가 파편화된 구조에서 '전부 성공하거나 전부 실패'하는 전통적인 방식은 네트워크 지연과 가용성 저하의 주범이 된다.
결국 아키텍트는 **데이터의 즉각적 일관성(Strong Consistency)**을 포기하고 **최종적 일관성(Eventual Consistency)**을 선택해야 하는 기로에 선다. 분산 트랜잭션 문제를 해결하기 위한 실전 전략, 그중에서도 가장 현실적인 대안인 Saga 패턴을 중심으로 팩트를 분석한다.
1. 2PC(2-Phase Commit)의 몰락
분산 환경에서 가장 먼저 떠올리는 것은 2PC다. 하지만 실전에서 2PC는 '안티 패턴'에 가깝다.
장애 전파: 참여하는 서비스 중 하나만 응답이 늦어도 전체 시스템의 스레드가 점유되는 병목 현상이 발생한다.
NoSQL 미지원: 많은 현대적 NoSQL DB는 2PC를 지원하지 않아 이기종 DB 환경에서 적용이 불가능하다.
2. Saga 패턴: 보상 트랜잭션의 미학
Saga 패턴은 하나의 거대한 트랜잭션을 일련의 로컬 트랜잭션들로 분리한다. 각 서비스는 자신의 로컬 DB에 데이터를 커밋하고, 다음 서비스로 이벤트를 전달한다. 만약 중간에 실패하면? 이전에 성공했던 단계들을 취소하는 **보상 트랜잭션(Compensating Transaction)**을 실행한다.
① 코레오그래피(Choreography) 방식
중앙 제어자 없이 서비스들이 이벤트를 주고받으며 연쇄적으로 반응하는 방식이다.
장점: 구조가 단순하고 서비스 간 결합도가 낮다. 소규모 시스템에 적합하다.
단점: 워크플로우가 복잡해지면 트랜잭션의 현재 상태를 파악하기 어렵고, 순환 참조 위험이 있다.
② 오케스트레이션(Orchestration) 방식
중앙의 '오케스트레이터'가 트랜잭션의 모든 흐름을 제어하고 명령을 하달한다.
장점: 복잡한 비즈니스 로직도 한곳에서 관리되므로 상태 추적이 용이하고 에러 핸들링이 명확하다.
단점: 오케스트레이터 자체가 병목점이 되거나 과도한 로직 집중으로 비대해질 수 있다.
3. 실전 적용 시 마주하는 3가지 기술적 팩트
① 트랜잭셔널 아웃박스(Transactional Outbox) 패턴
Saga 패턴의 핵심은 '로컬 DB 커밋'과 '메시지 발행'이 **원자적(Atomic)**으로 일어나야 한다는 점이다. DB 업데이트는 성공했는데 메시지 전송에 실패하면 데이터 정합성이 깨진다.
Fact: 로컬 DB에 'Outbox' 테이블을 두고 비즈니스 데이터와 메시지를 하나의 트랜잭션으로 묶어 저장한 뒤, 별도 프로세스(Relay)가 메시지를 발행하는 방식이 가장 안전하다.
② 멱등성(Idempotency) 보장
네트워크 장애로 인해 동일한 이벤트가 중복 전달될 수 있다. 보상 트랜잭션이나 서비스 로직은 여러 번 실행되어도 결과가 같아야 한다. 이를 위해 Execution ID나 Request ID를 통한 중복 처리 로직은 선택이 아닌 필수다.
③ 격리성(Isolation)의 부재
Saga는 ACID 중 'I(격리성)'가 없다. 즉, 트랜잭션이 완료되기 전의 중간 데이터가 다른 요청에 노출될 수 있다.
Dirty Read 발생: 주문이 아직 확정되지 않았는데 재고가 줄어든 상태로 보일 수 있다.
대책: '시맨틱 락(Semantic Lock)'을 활용해 상태값(PENDING, APPROVING 등)을 관리하거나, 업데이트 순서를 비즈니스 위험도가 낮은 순으로 배치해야 한다.
4. 결론: 기술보다 비즈니스 설계가 우선이다
Saga 패턴 도입은 단순히 라이브러리를 추가하는 문제가 아니다. **"실패했을 때 어떻게 되돌릴 것인가?"**에 대한 비즈니스 정의가 기술적 구현보다 훨씬 중요하다.
간소화: 모든 곳에 Saga를 바르지 마라. 가능하다면 서비스 경계를 재조정하여 단일 트랜잭션 범위로 묶는 것이 최선이다.
가시성: 분산 트랜잭션은 추적이 어렵다. Zipkin이나 Jaeger 같은 분산 트래킹 도구를 반드시 병행하라.
댓글
댓글 쓰기