MSA에서 데이터는 어떻게 분리되고 어떻게 다시 합쳐지는가
Database per Service 원칙부터 Polyglot Persistence, JOIN 없는 조회 전략, ACID vs BASE, 데이터 이관, 서비스 간 참조 무결성까지 MSA 데이터 아키텍처의 핵심 트레이드오프를 추적한다.
- 01 MSA는 왜 도입하는가 — 모놀리스가 무너지는 시점
- 02 MSA 통신 계층은 왜 이렇게 복잡한가
- 03 MSA에서 데이터는 어떻게 분리되고 어떻게 다시 합쳐지는가
- 04 MSA에서 분산 트랜잭션을 어떻게 다룰 것인가
- 05 MSA 탄력성 패턴 — 장애는 차단하고, 서비스는 살린다
- 06 API Gateway는 왜 단순한 프록시가 아닌가
- 07 MSA 운영의 핵심은 관찰 가능성이다
모놀리스에서는 데이터 일관성이 공짜였다. 하나의 DB, 하나의 트랜잭션, FK가 모든 것을 보장했다. MSA로 전환하는 순간, 그 공짜 점심이 사라진다. 데이터를 분리하면 독립성을 얻지만, 조인과 트랜잭션을 잃는다. 이 교환이 어떤 아키텍처 결정을 연쇄적으로 요구하는가?
DB를 서비스마다 분리하는 이유
Database per Service 원칙의 핵심 동기는 기술적 강제를 통한 조직 독립성이다. 주문 서비스와 배송 서비스가 같은 DB를 공유하면, 주문 팀이 orders 테이블 스키마를 바꿀 때 배송 팀의 배포를 블로킹한다. 배포 일정을 조율해야 하고, 한 팀의 느린 쿼리가 다른 팀의 레이턴시를 올린다.
DB를 분리하면 이 상호작용이 기술적으로 차단된다. 주문 서비스 팀은 자신의 DB를 완전히 제어하고, 배송 서비스는 영향을 받지 않는다. 대신 서비스 간 통신은 API와 메시지로만 이루어져야 한다.
분리 수준은 두 가지다. 스키마 분리는 하나의 DB 서버 안에서 스키마를 나누는 방식으로 비용이 낮지만 기술적 강제가 약하다 — 개발자가 실수로 크로스 스키마 JOIN을 작성해도 DB가 막지 않는다. 서버 분리는 물리적으로 다른 DB 서버를 쓰므로 크로스 서비스 접근이 불가능하지만 운영 비용이 높다. 실전에서는 하이브리드가 일반적이다 — 중요도가 낮은 서비스는 스키마 분리, 성능과 장애 격리가 중요한 서비스는 서버 분리.
각 서비스가 최적의 DB를 선택한다: Polyglot Persistence
DB를 분리하면 자연스러운 질문이 따라온다. 모두 같은 DB 기술을 써야 하는가? 아니다. 주문 서비스는 ACID 트랜잭션이 중요하므로 PostgreSQL이 맞고, 상품 검색은 역인덱스 기반의 Elasticsearch가 MySQL보다 100배 빠를 수 있다. 세션 저장소는 TTL과 인메모리 성능이 필요하므로 Redis가 적합하다.
Polyglot Persistence는 각 서비스의 성능을 최적화하지만, DBA 팀이 여러 기술을 관리해야 하고 백업·모니터링·장애 대응 전략이 기술마다 달라진다. 초기에는 PostgreSQL + Redis 두 가지로 시작하고, 실측된 성능 문제가 발생할 때만 기술을 추가하는 것이 안전하다.
JOIN 없이 데이터를 조합하는 세 가지 방법
DB를 분리하면 orders JOIN shipments 같은 쿼리가 불가능해진다. 이 문제를 해결하는 방법은 세 가지다.
API Composition은 여러 서비스 API를 호출해 애플리케이션 레벨에서 조합한다. 구현이 단순하고 데이터가 실시간이지만, 주문 목록을 조회할 때 각 주문마다 배송 API를 따로 호출하는 N+1 문제가 생긴다. 배치 조회 API(GET /shipments?orderIds=1,2,3)로 완화할 수 있다.
CQRS는 쓰기 모델(PostgreSQL)과 읽기 모델(Elasticsearch)을 분리한다. 주문이 생성되면 OrderCreatedEvent를 발행하고, 이벤트 핸들러가 Elasticsearch에 JOIN된 형태로 인덱싱한다. 읽기는 이미 조합된 읽기 모델에서 조회하므로 빠르다. 대신 쓰기 후 읽기 모델 업데이트까지 수백 ms의 지연이 생긴다.
데이터 복제는 자주 필요한 데이터를 로컬 스냅샷으로 저장한다. 고객 정보를 customer_snapshot 테이블에 미리 복사해두면 로컬 JOIN이 가능하다. 조회 성능이 좋지만 데이터가 오래될 수 있고, 고객이 삭제되면 고아 스냅샷이 남는다.
강한 일관성이 필요하면 API Composition, 복잡한 검색이 필요하면 CQRS, 자주 접근하는 소수 데이터면 복제를 선택한다. 세 전략을 혼합해 사용하는 것이 현실적이다.
ACID를 버리고 BASE를 받아들이다
모놀리스에서 주문 생성은 원자적이었다 — 주문, 결제, 재고 차감이 하나의 트랜잭션으로 묶였다. MSA에서는 이 작업이 세 개의 독립된 DB에 걸쳐 있다. 2PC(Two-Phase Commit)로 분산 트랜잭션을 구현하려는 시도는 실패한다 — 결제 서비스가 돈을 받은 후 재고 서비스가 다운되면 롤백 자체가 불가능하다.
MSA는 ACID 대신 BASE를 받아들인다. Basically Available — 일부 데이터가 일시적으로 오래되어도 응답한다. Soft state — 일관성이 일시적으로 깨질 수 있다. Eventual Consistency — 결국 모든 서비스의 데이터가 일치한다.
이를 구현하는 핵심 패턴이 Saga다. 주문 생성 이벤트를 발행하면 결제 서비스와 재고 서비스가 비동기로 처리한다. 결제가 실패하면 PaymentFailedEvent를 발행하고, 주문 서비스가 보상 트랜잭션으로 주문을 취소한다. 강한 일관성 대신 최종 일관성을 보장한다.
CAP Theorem이 이 선택을 강제한다. 네트워크 장애(P)는 분산 시스템에서 피할 수 없으므로, 일관성(C)과 가용성(A) 중 하나를 선택해야 한다. 금융 거래는 CP — 일관성을 위해 일부 요청을 거부한다. 소셜 미디어 좋아요 카운터는 AP — 약간의 불일치를 허용하고 가용성을 우선한다.
모놀리스 DB에서 서비스별 DB로 이관하기
이미 운영 중인 시스템에서 DB를 분리하는 것은 “오늘은 모놀리스, 내일은 마이크로서비스” 식의 빅뱅 전환이 불가능하다. Strangler Fig 패턴으로 점진적으로 전환해야 한다.
핵심 도구는 Outbox Pattern이다. 주문과 Outbox 이벤트를 같은 트랜잭션에 저장한다. 별도 Poller가 주기적으로 Outbox를 읽어 Kafka에 발행하고, 신규 DB가 이를 구독해 업데이트한다. 네트워크 장애로 Kafka 발행이 실패해도 Outbox에 PENDING 이벤트가 남아 있으므로 재시도가 가능하다 — 원자성과 보증 전달을 동시에 달성한다.
Shadow Mode는 전환 검증에 쓰인다. 읽기 요청에서 기존 DB 결과를 응답으로 반환하면서, 신규 DB에서도 비동기로 조회해 결과를 비교한다. 불일치율이 0%에 도달하면 읽기 트래픽을 단계적으로 전환한다.
물리적 FK 없이 참조 무결성을 보장하다
서비스 간 물리적 FK는 불가능하다. 주문 서비스 DB에서 고객 서비스 DB의 customers 테이블을 참조하는 FK를 만들 수 없다. 고객을 삭제하면 주문 서비스의 customer_id 참조가 고아 데이터가 된다.
애플리케이션 레벨에서 참조 무결성을 관리해야 한다. 주문 생성 시 고객 서비스 API를 호출해 존재 여부를 검증하고, 고객 삭제 이벤트를 구독해 관련 주문을 보상 처리한다. 정기 배치로 고아 데이터를 감지하고 상태에 따라 취소·환불 처리를 자동화한다.
스냅샷 전략은 고객 정보를 주문 생성 시점에 복사해두는 방식이다. 고객이 나중에 삭제되어도 주문 이력 조회가 가능하다. 단, 스냅샷은 감사 기록이므로 고객명이 변경되어도 과거 주문의 스냅샷을 갱신하지 않는 것이 맞다 — 현재 정보가 필요하면 API를 조회한다.
정리
- DB 분리는 서비스 독립성을 기술적으로 강제하는 수단이다. 대가는 JOIN 불가, 분산 트랜잭션, 참조 무결성 관리다.
- JOIN 없는 조회는 API Composition(실시간), CQRS(고성능 검색), 데이터 복제(로컬 JOIN) 세 전략으로 해결한다.
- ACID를 포기하고 BASE를 받아들이면, Saga 패턴으로 최종 일관성을 보장한다.
- 이관은 Outbox Pattern + Shadow Mode + Feature Toggle로 점진적으로, 롤백 가능하게 진행한다.
- 참조 무결성은 이벤트 기반 보상 + 정기 고아 데이터 감지 + 스냅샷의 조합으로 관리한다.
다음 글에서는 Saga 패턴의 Orchestration 방식과 Choreography 방식의 차이, 그리고 보상 트랜잭션의 멱등성 보장 전략을 추적한다.