본문 바로가기

Study

[내일배움캠프 TIL] SAGA 패턴

728x90
반응형

1. Saga 패턴 왜 쓸까?

  • 과거 (모놀리식): DB가 하나라 Transactional 어노테이션 한 줄이면 전부 성공하거나 전부 실패(ACID)하게 만들 수 있었음.
  • 현재 (MSA): 서비스마다 DB가 찢어짐. A DB는 성공했는데 B DB가 실패하면 전체 롤백이 불가능해짐.
  • 2PC는 왜 안 써?: "야 다들 준비됐어?" 하고 모든 서버가 응답할 때까지 DB에 락(Lock)을 걸어버림. 하나만 죽어도 전체 시스템이 멈추기 때문에 가용성이 안좋음.

💡 그래서 현대 MSA에서는 락을 안 걸고 어떻게든 최종 정합성을 맞추는 Saga 패턴이 대세가 됨.

2. Saga 패턴이란?

Saga: 각 서비스의 로컬 트랜잭션을 순차적으로 실행하고, 실패하면 왔던 길을 되돌아가는 **보상 트랜잭션(취소 작업)**을 실행하는 패턴. (약자 아님, 1987년 논문 이름)

ACID와 Saga의 결정적 차이 (ACID vs BASE)

Saga는 격리성(Isolation)이 없습니다. 즉, 작업이 완전히 끝나지 않았는데 중간 상태가 외부에 노출됩니다.

[주문 완료] ──> [결제 완료] ──> [재고 부족으로 실패!]
                                     │
   [주문 취소] <── [결제 취소] <──────┘ (보상 트랜잭션 발동)
  • ACID: 재고 차감까지 완벽히 성공하기 전엔 외부에서 주문 상태를 절대 못 봄.
  • Saga: 결제 완료된 직후, 재고가 없어서 실패하기 직전의 그 짧은 순간에 외부 사용자가 "주문+결제 완료" 상태의 데이터를 조회할 수 있음. (이를 Soft State라 부르며, 결국 시간이 지나 취소되어 정합성이 맞아떨어지는 것을 최종 일관성이라 함.)

3. Saga의 2가지 구현 방식

① 오케스트레이션 (Orchestration) 

중앙에 지휘자(Orchestrator)를 두고 각 서비스에 명령(Command)을 내리고 응답(Reply)을 받는 방식.

  • 장점: 지휘자 코드만 보면 전체 흐름이 한눈에 보임. 구현이 비교적 단순함.
  • 단점: 지휘자 서비스가 너무 무거워지고, 이 녀석이 죽으면 전체 시스템이 마비됨 (SPOF).

② 코레오그래피 (Choreography) 

중앙 제어 없이, 각 서비스가 메시지 큐(Kafka 등)의 이벤트를 구독/발행하며 자율적으로 움직이는 방식.

  • 장점: 서비스 간 결합도가 낮고, 단일 장애점(SPOF)이 없어 확장성이 끝내줌.
  • 단점: 데이터가 꼬였을 때 흐름 추적이 어려워 디버깅 지옥이 펼쳐짐.

4. 코레오그래피의 짝꿍: 이벤트 발행 보장 전략

"내 DB에 데이터 쓰기"와 "카프카에 이벤트 던지기"가 동시에 성공해야 정합성이 맞음. 이를 보장하는 2가지 방법.

방법 A. 아웃박스 패턴 (Outbox Pattern)

  • 원리: 내 DB에 비즈니스 데이터 저장할 때, 보낼 이벤트도 Outbox라는 임시 테이블에 한 트랜잭션으로 같이 묶어 저장함. 이후 CDC(Debezium 등)가 이 테이블을 읽어서 카프카로 쏨.
  • 단점: 서비스 DB마다 Outbox 테이블을 다 만들어야 해서 귀찮고, DB에 계속 읽기/쓰기 부하를 줌.

방법 B. PDL 패턴 (Producer Dead Letter)

  • 원리: 서비스는 그냥 DB에 저장하고 메인 카프카로 바로 이벤트를 던짐. 만약 카프카가 죽어서 실패하면, 유실하지 않고 고가용성 백업 큐(PDL 카프카)로 우회시켜 버림.
  • 이후 처리: 공통 DL(Dead Letter) 서버가 PDL을 구독하고 있다가, 메인 카프카가 살아나면 재처리(Consumer Dead Letter 메커니즘 등)를 통해 안전하게 밀어 넣어줌.
  • 장점: 비즈니스 DB에 부하가 전혀 없고, 인프라 팀이 공통 모듈로 만들어두면 개발자는 비즈니스 로직만 짜면 됨.

5. 요약: 오케스트레이션 vs 코레오그래피

비교 항목 오케스트레이션 (지휘자) 코레오그래피 (군무)
제어 중앙 오케스트레이터가 통제 각 서비스가 이벤트 기반 자율 제어
장점 흐름 파악 및 디버깅 쉬움 결합도 낮음, SPOF 없음 (확장성 Up)
단점 중앙 서버가 병목/SPOF 위험 전체 흐름 파악 및 디버깅 어려움
추천 비즈니스/보상 로직이 복잡할 때 트래픽이 많고 빠른 확장이 필요할 때
반응형