분산 트랜잭션
모노리틱 서버에서 기타 사유로 서버가 분리되었을 때
분리되기 전 처럼 요청의 원자성을 보장하기 위해 분산된 트랜잭션을 관리해주어야한다.
이것을 흔히 분산 트랜잭션이라고 한다.
메시지 전달 보장 수준(Message Delivery Semantics)
메시지에 따라 해당 전달에 대한 보장 수준을 달리가져간다.
해당 수준은 따라 구현 또는 플로우에 지대한 영향을 끼치기 때문에
하나의 수준으로 모든 메시지를 처리하는 것이 아닌 상황에 맞는 수준을 채택하여 다양하게 사용한다.
최대 한 번 전달(At Most Once)
메시지는 최대 한 번 전송되며, 재전송하지 않는다.
해당 메시지는 유실될 가능성이 있다.
일상 생활로 치면 GPS라고 생각한다.
주기적으로 전송하기 때문에 10번 중 한번의 데이터를 못받았다고 크게 문제가 발생하지 않는다.
최소 한 번 전달(At Least Once)
메시지는 최소 한 번 이상 전송되며, 중복 전송이 발생할 수 있다.
중복에 대한 멱등성을 수신자쪽에서 보장해야한다.
정확히 한 번 전달(Exactly Once)
메시지는 정확히 한 번만 전송되며, 유실이나 중복이 없다.
구현이 복잡하고 비용이 높은 만큼 가장 이상적인 전달 보장 수준
2PC(Two-Phase Commit)
분산 트랜잭션의 강한 원자성을 보장하기 위해 두 단계(준비 및 커밋)로 트랜잭션을 처리함
그러나 중앙 코디네이터에 강하게 의존하기 때문에 장애시 전체 트랜잭션 실패의 위험이 있음
트랜잭션이 완료되면 트랜잭션이 준비 상태가 되고 트랜잭션 코디네이터에 의해 상태가 전파되어 커밋 혹은 롤백 됨
장점
- 강한 원자성 보장
모든 트랜잭션이 준비되어야 커밋됨
단점
- 낮은 성능
DB 비관적 락을 사용하기 때문에 성능에 안좋은 영향을 줌
- DBMS 의존성
일부 DB에서 2PC를 지원하지 않으며 서버 간 서로 다른 DB를 사용하는 경우 호환성 문제가 있을 수 있음 (MSA에 사용시 DB종류에 제약이 생김)
- 코디네이터 의존성
장애 발생시 전체 트랜잭션에 영향을 줌
SAGA
SAGA는 여러 로컬 트랜잭션을 순차적으로 실행하며 중간에 문제 발생시 각 서비스별 보상 트랜잭션으로 이전 상태로 복구하는 방식
이를 통해 전체 시스템의 원자성을 보장
종류
Choreographed Saga
각 마이크로서비스가 이벤트 및 보상 트랜잭션을 중앙제어 없이 자체적으로 관리
Orchestrated Saga
중앙 Orchestrator가 모든 이벤트 및 보상 트랜잭션을 관리
예시
- 복잡함을 최소화하기 위해 뒤에 ‘이벤트'가 붙은 화살표는 중간에 이벤트 메시지 버스가 있다고 가정
- 주문자에게 가는 응답은 이해를 돕기위해 추가함

장점
-
최종적 일관성(Eventual Consistency)
데이터를 즉시 완벽하게 동기화하지 않고, 일정 시간이 지난 후 시스템 전체의 일관성을 보장하는 최종적 일관성 채택
-
느슨한 결합(Loose coupling), 높은 확장성
각 마이크로서비스는 자체 트랜잭션과 보상 로직을 포함하므로 독립적으로 개발, 배포 및 확장에 용이
-
장애에 견고함
부분 실패 시 보상 트랜잭션을 통한 복구가 가능하여 전체 시스템 장애를 방지할 수 있음
단점
-
복잡성 증가
각 로컬 트랜잭션 실패 시 대응하는 보상 로직을 설계하고 구현해야함
-
보상 트랜잭션의 한계
보상 트랜잭션이 “완벽한 원자성”을 보장하지 않으므로, 도메인 로직에 따라 최종 일관성 상태에 도달하는 데 시간이 걸릴 수 있음
-
메시지 전달 신뢰성
중복, 메세지 소실 등의 위험이 있음
-
최종적 일관성
최종적인 일관성을 보장하기 때문에 데이터의 일시적 불일치가 생길 수 있음
-
Orchestrator 의존성(Orchestrated Saga 시)
중앙 제어기의 장애시 전체 트랜잭션에 문제가 생김
Outbox(Transactional Outbox)
- Outbox 패턴은 비즈니스 데이터 변경과 함께 메시지(이벤트)를 동일한 데이터베이스 트랜잭션 내에 별도 테이블(Outbox 테이블)에 저장
- 로컬 트랜잭션이 성공하면 메시지도 함께 기록되므로, 메시지 전파와 데이터 변경의 원자성 보장
- 별도의 메시지 전파기(이벤트 프로세서)가 Outbox 테이블을 모니터링하여 메시지를 메시지 브로커 등을 통해 다른 서비스에 전파
Outbox Polling Publisher
- 주기적으로 아웃박스 테이블을 폴링하여 처리되지 않은 메시지를 읽어 메시지를 전파,처리
- 간단한 구현이 가능하지만, 폴링 간격에 따라 지연 발생
예시

장점
- 구현과 운영 용이성
구현 및 운영이 비교적 단순하며 유지 보수가 편리
- 원자성 보장 및 메시지 유실 최소화
로컬 트랜잭션 내 메시지 기록으로 메시지 유실 최소화, 원자성 보장
- 장애에 견고함
장애 상황에서 재시도 및 보상이 용이 (폴링 주기대로 재시도 가능)
단점
- 지연 발생
폴링 간격에 의해 메시지 발행 실시간 성능 지연 발생 가능
- 성능 이슈
Outbox 테이블 크기 커짐에 따라 폴링 성능 이슈 가능
- 추가 관리 포인트
Outbox 데이터 관리(예: 이미 전송된 이벤트 정리)등의 관리가 추가됨
CDC(Change Data Capture) - Transaction Log Tailing
- Outbox 테이블 INSERT, UPDATE 등 변경 이벤트를 CDC 툴을 통해 감지하여 실시간으로 읽고 이벤트 브로커(Kafka, Pulsar 등)에 전송
- CDC는 Debezium, Kafka Connect 같은 기술을 활용
예시

장점
- 실시간성
거의 실시간에 가까운 빠른 이벤트 전달 보장
- 낮은 지연시간
낮은 지연(latency) 및 메시지 처리 속도가 우수
- 안정성 및 유지보수성
안정성 높고 복구 자동화, 모니터링 기능 제공 가능
- 성능
Outbox 테이블 규모 증가 시 폴링 방식 대비 성능 유지 우수
- 낮은 결합도
시스템 간의 결합도를 더욱 낮출 수 있음
단점
- 초기 비용및 운영 비용 증가
CDC 인프라(Debezium, Kafka Connect 등)를 추가로 도입해야 하므로 초기 설정과 운영 복잡성 증가 및 인프라 비용 및 학습 곡선
- 운영관리 복잡성 증가
CDC 시스템 장애나 장애 복구, 데이터 스키마 변경 관리(버전 관리) 등의 추가 고려사항 필요