5장. 경계를 지키는 설계
4장에서 우리는
책임을 기준으로 경계를 나누는 방법을 살펴보았다.
하지만 여기서 멈추면 안 된다.
서비스를 나누는 것보다 더 어려운 것은
그 경계를 유지하는 것이다.
그리고 경계를 무너뜨리는 가장 빠른 방법은
데이터를 공유하는 것이다.
DB를 공유하는 순간 무슨 일이 벌어지는가
많은 팀이 이렇게 말한다.
“서비스는 나누되, DB는 하나 써도 되지 않나요?”
겉보기에는 효율적이다.
- 트랜잭션도 편하고
- JOIN도 자유롭고
- 데이터 일관성도 유지하기 쉽다
하지만 그 순간 경계는 무너진다.
예를 들어보자.
- Order 서비스가 User 테이블을 직접 조회한다
- Payment 서비스도 User 테이블을 JOIN한다
- Delivery도 같은 DB에서 데이터를 읽는다
이제 User 스키마가 변경되면
세 서비스가 모두 영향을 받는다.
User 테이블이 느려지면
모든 서비스가 느려진다.
배포는 독립적이지 않다.
결국 하나의 거대한 시스템과 다르지 않다.
이것이
DB 공유가 분산 모놀리스로 가는 지름길인 이유다.
DB per Service 원칙
마이크로서비스에서 가장 중요한 원칙 중 하나는 이것이다.
서비스마다 독립된 데이터 저장소를 가진다.
이 말은 단순히 “DB 인스턴스를 나눈다”는 뜻이 아니다.
의미는 더 강하다.
- 다른 서비스의 DB를 직접 조회하지 않는다
- 다른 서비스 테이블에 JOIN하지 않는다
- 다른 서비스의 스키마에 의존하지 않는다
각 서비스는 자기 데이터에 대한 소유권을 가진다.
소유권이 분리되어야 책임도 분리된다.
데이터 중복은 정말 나쁜 것일까
여기서 많은 개발자가 불편함을 느낀다.
“그럼 데이터가 중복되지 않나요?”
맞다.
중복된다.
하지만 중요한 질문은 이것이다.
데이터 중복이 더 위험한가?
아니면 강결합이 더 위험한가?
마이크로서비스에서는
대부분의 경우 강결합이 더 위험하다.
데이터는 복제할 수 있다.
하지만 결합된 구조는 쉽게 끊을 수 없다.
스냅샷 전략 — 기록과 현재 상태는 다르다
전자상거래 예시로 다시 돌아가보자.
Order는 주문 당시의 정보를 기록한다.
- 주문자 이름
- 배송 주소
- 상품 가격
여기서 중요한 점이 있다.
주문은 “과거의 사실”이다.
사용자가 나중에 주소를 변경해도
이미 완료된 주문의 배송지는 바뀌지 않는다.
따라서 Order는
User의 최신 정보를 매번 조회할 필요가 없다.
주문 시점의 정보를
스냅샷으로 저장하면 된다.
예:
Order
- order_id
- buyer_id
- buyer_name_snapshot
- shipping_address_snapshot
- order_price_snapshot
이렇게 하면
- User 프로필 변경과 무관하게
- Order는 독립적으로 유지된다
이것이 스냅샷 전략이다.
스냅샷이 필요한 이유
만약 Order가 매번 User의 최신 주소를 조회한다면 어떻게 될까?
- User 서비스가 느려지면 주문 조회도 느려진다
- User 스키마 변경 시 Order도 수정해야 한다
- User 장애가 주문 조회를 막는다
즉, Order는 독립적이지 않다.
스냅샷은
과거의 비즈니스 사실을 고정시키는 장치다.
이는 단순한 최적화가 아니라
경계를 지키는 설계다.
데이터 복제는 어떻게 생각해야 하는가
마이크로서비스에서는
데이터 복제를 두려워해서는 안 된다.
중요한 것은 두 가지다.
-
데이터 소유권은 명확해야 한다
- User 데이터의 원본은 User Context가 가진다
- Order는 필요한 정보만 복제한다
-
복제는 단방향이어야 한다
- 원본이 변경되어도 복제된 과거 기록은 변경되지 않는다
복제는 허용하되
공유는 금지하는 것이 원칙이다.
경계를 무너뜨리는 신호들
다음과 같은 상황이 있다면
이미 경계가 흔들리고 있을 가능성이 높다.
- 다른 서비스 DB에 직접 SELECT를 날리고 있다
- 다른 서비스 테이블에 JOIN을 하고 있다
- 스키마 변경 시 여러 팀이 동시에 수정해야 한다
- 함께 배포하지 않으면 불안하다
- 한 DB 장애가 전체 시스템을 멈춘다
이 중 하나라도 해당된다면
DB 설계를 다시 봐야 한다.
이 장의 핵심
서비스를 나누는 것은 시작일 뿐이다.
진짜 경계는
데이터 소유권과 접근 방식에서 만들어진다.
- DB는 공유하지 않는다
- 다른 서비스 테이블을 직접 보지 않는다
- 필요한 정보는 복제한다
- 과거의 사실은 스냅샷으로 고정한다
경계는 선언이 아니라
설계로 지켜진다.