포스트

[TIL] MSA에서 FK를 어디까지 허용해야 할까?

물류/배송 플랫폼 SA 문서를 작성하며 MSA 서비스 경계, 테이블 소유권, FK 사용 범위, 논리 참조 방식에 대해 고민한 기록입니다.

For the English version of this post, see here.
[TIL] MSA에서 FK를 어디까지 허용해야 할까?

오늘 한 일

  • 물류 관리 및 배송 시스템 SA 문서 작성 시작

  • 도메인 정의 및 테이블 명세서 작성

  • MSA 서비스 경계 분리 논의

  • 서비스 간 데이터 참조 방식 정리

  • FK 사용 범위와 데이터 정합성 방식 고민


도메인 및 서비스 분리

프로젝트는 다음과 같이 5개의 서비스로 분리하기로 결정했다.

1. 사용자 및 인증

  • p_users

2. 허브 및 허브 관리

  • p_hub

  • p_hub_to_hub

3. 업체 및 상품

  • p_company

  • p_product

4. 주문 및 배송 실행

  • p_order

  • p_delivery

  • p_delivery_route

  • p_delivery_manager

5. 알림 및 AI 메시지

  • p_slack_message

  • p_ai_message


서비스를 왜 분리할까?

처음에는 MSA를 단순히 “서비스를 여러 개로 나누는 구조” 정도로 생각했다.

하지만 오늘 설계를 진행하면서 중요한 건 단순 분리가 아니라, 각 서비스가 자신의 책임과 데이터를 독립적으로 관리할 수 있도록 만드는 것이라는 점을 알게 되었다.

예를 들어:

  • User Service는 인증과 권한 관리에 집중하고

  • Hub Service는 허브 및 물류 이동 정보 관리에 집중하고

  • Order/Delivery Service는 주문 및 배송 흐름 관리에 집중한다.

이렇게 역할을 분리하면 특정 기능 수정이 다른 서비스에 미치는 영향을 줄일 수 있고, 서비스별 독립 배포 및 확장에도 유리해진다.

또한 서비스별 데이터 소유권을 분리함으로써 각 서비스가 자신의 비즈니스 로직에 집중할 수 있다는 점도 인상적이었다.

다만 프로젝트 규모와 구현 난이도를 고려하여, 현재는 완전히 잘게 쪼개기보다는 강하게 연결된 기능은 하나의 서비스로 묶는 방향으로 설계를 진행했다.

예를 들어 주문 생성 이후 배송 생성 흐름은 밀접하게 연결되어 있기 때문에 Order와 Delivery를 하나의 서비스로 구성했다.


MSA 환경에서의 FK 고민

MSA 구조에서는 각 서비스가 자신의 데이터를 소유해야 한다.

따라서 다른 서비스의 테이블을 직접 FK로 참조하지 않고, UUID 값만 저장하여 논리적으로 연결하기로 했다.

예를 들어:

  • Order Service는 user_id를 저장하지만

  • User Service의 users 테이블과 물리 FK는 연결하지 않음

서비스 간 데이터 조회는 API 호출 또는 이벤트 기반 방식으로 처리한다.


같은 서비스 내부에서도 FK를 꼭 사용해야 할까?

처음에는 같은 서비스 내부라면 FK를 사용하는 것이 당연하다고 생각했는데, 실무에서는 운영 복잡도와 성능 문제 때문에 FK를 사용하지 않는 경우도 있다는 점을 알게 되었다.

특히:

  • INSERT/UPDATE/DELETE 시 참조 무결성 검사 비용 발생

  • 대량 데이터 적재 시 성능 부담

  • 마이그레이션 및 장애 복구 복잡성 증가

같은 이유 때문에 애플리케이션 레벨에서 정합성을 관리하기도 한다고 한다.


사용자 테이블 설계 고민

사용자의 역할에 따라 company_id 또는 hub_id를 저장해야 한다는 점이 인상적이었다.

예를 들어:

  • HUB_MANAGER → hub_id 사용

  • COMPANY_MANAGER → company_id 사용

역할에 따라 참조 대상이 달라지는 구조를 고려해야 했다.


배송 담당자 설계 고민

배송 담당자가 사용자 엔티티와 어떤 관계를 가져야 하는지 고민했다.

slack_id와 hub_id를 User에서 관리할지, DeliveryManager에서 별도로 관리할지 논의했고,

현재는:

  • User = 인증 주체

  • DeliveryManager = 배송 업무 주체

처럼 역할을 분리하는 방향으로 이해하고 있다.


느낀 점

오늘은 단순 CRUD 설계가 아니라 “서비스를 어디까지 나눌 것인가”를 계속 고민했던 하루였다.

특히 MSA에서는 ERD를 단순히 연결하는 것이 아니라, 서비스 경계를 기준으로 데이터를 어떻게 소유하고 참조할지 고민해야 한다는 점이 인상적이었다.

ERD 선 하나를 긋는 것도 서비스 책임과 강하게 연결된다는 걸 처음 체감했다.