도메인 경계 재설계 PRD
Background
sports-application backend는 com.sportsapp.domain 하위에 12개 도메인 패키지(booking, facility, goods, mcp, message, notification, operator, payment, post, ticketing, user, weather)와 공유 커널 common을 갖는 Hexagonal + Rich Domain 모놀리스다. 2026년 7월 PR #193(PKG-2)로 레이어 우선(domain/application/infrastructure/presentation) 구조를 컨텍스트 우선(레이어→도메인→서브패키지) 구조로 이전하는 작업이 완료됐다. 그러나 이 작업은 “어느 클래스가 어느 레이어에 있는가”만 정리했을 뿐, “이 도메인들이 서로 어떤 경계·관계를 갖는가”는 다루지 않았다.
이후 진행될 과제들이 이 기반 위에 얹힌다. B2B 파트너 연동(Partner가 goods·ticketing의 기존 유즈케이스를 경유), 마케팅 이벤트(goods에 한정판 판매 로직 신설), 배포 환경 분리 등은 모두 “이 데이터는 어느 도메인이 소유하는가”, “도메인 간 호출은 어떤 방향으로만 허용되는가”에 대한 합의된 기준이 있어야 설계 충돌 없이 진행된다. 현재는 이 기준이 코드에 암묵적으로만 존재하고 문서화된 컨텍스트 맵이 없다.
Problem Definition
- 12개 도메인(+공유 커널
common)이 계층 구분 없이 평면적으로 나열되어 있다.booking·facility·goods·payment·ticketing·user처럼 고객 대상 거래 도메인과,operator(내부 운영자 인박스)·mcp(AI 에이전트 토큰·이상탐지)처럼 운영 지원 서브시스템이 같은 레벨의 패키지로 존재해 “코어 도메인”과 “지원 서브시스템”이 구분되지 않는다. application/dashboard·application/image(및 대응presentation)는domain레이어가 없는 조회·유틸리티 전용 컨텍스트다(domain/dashboard,domain/image패키지 자체가 존재하지 않는다 — Aggregate Root 없이 다른 도메인의 Repository/Gateway를 조합해 조회하거나 파일 업로드를 처리하는 구조로 추정된다). 이 두 컨텍스트는 “도메인”으로 취급해야 하는지, “지원 유틸리티”로 별도 분류해야 하는지 컨텍스트 맵에 반영된 적이 없다 — 특히image는 기존 AS-IS 파악에서 누락됐었다.- B2C 거래 흐름(
goods의ownerId,ticketing의Event소유자 등)에 향후 B2B 파트너 개념이 얹힐 자리가 사전 정의돼 있지 않다. - 도메인 간 참조 규칙(ID만 참조,
domain.common예외 허용)이private-be-code-convention에 일반 원칙으로만 존재하고, 실제 도메인들에 대한 구체적인 컨텍스트 맵(관계 유형·의존 방향)으로 산출된 적이 없다.
Goals / Non-Goals
Goals
- 12개 도메인(
common제외)을 코어(거래)/지원(운영·알림)/서브시스템(AI 에이전트) 3계층으로 분류한 컨텍스트 맵을 산출한다.common은 공유 커널(Shared Kernel)로 별도 표기하며 3계층 분류 대상에 포함하지 않는다. dashboard·image를 “조회·유틸리티 전용 컨텍스트”로 명시 분류하고, 컨텍스트 맵에 포함할지(어느 계층으로) 또는 명시적으로 제외할지와 그 사유를 문서화한다 — 누락 상태로 남기지 않는다.- 각 도메인 쌍의 관계 유형(Shared Kernel/Customer-Supplier/Conformist 등)과 허용 의존 방향을 표로 확정한다.
- 각 도메인의 Aggregate Root와 소유 데이터(쓰기 권한)를 문서화한다 — 단
common은 Aggregate Root를 갖지 않는 공유 커널이므로 이 표의 적용 대상에서 제외한다. - B2B/B2C 트랜잭션 경계 기준을 확정해, [B2B 파트너 연동](../B2B 파트너 연동/PRD.md) 과제가 실제로 경유할
goods·ticketing2개 도메인의 제공 인터페이스를 식별한다. - 도메인 간 참조 규칙 위반(다른 도메인 Entity 직접 참조 등)을 코드에서 정적으로 탐지하는 방법을 정의한다.
Non-Goals
- 마이크로서비스로의 물리적 분리 — 모놀리스 구조를 유지한다.
- 기존 API 계약 변경 — FE(mobile/web)가 소비하는 엔드포인트는 하위 호환을 유지한다.
- DB 스키마 전면 재설계 — 컨텍스트 맵 산출 결과 불가피한 컬럼 소유권 이전이 있으면 개별 마이그레이션으로 후속 처리하고, 이 과제 자체는 전면 스키마 변경을 포함하지 않는다.
- 코드 재배치(패키지 이동) 실행 — 이 과제는 컨텍스트 맵과 규칙 확정까지이며, 실제 재배치는 컨텍스트 맵 확정 후 별도 티켓으로 수행한다(Open Questions 참조).
booking·payment의 파트너 경유 인터페이스 식별 — 현재 이 두 도메인을 경유하려는 소비처가 없다([B2B 파트너 연동](../B2B 파트너 연동/PRD.md)이 실제로 경유하는 도메인은goods·ticketing2개뿐이다). 소비처 없는 인터페이스를 미리 설계하는 것은 오버엔지니어링이므로, 필요 시점(실제 B2B 예약·결제 경유 요구가 생길 때)에 별도로 정의한다.
User Scenarios
페르소나: 백엔드 개발자(본인) 및 이후 과제(②③⑧)를 설계하는 설계 에이전트.
- 신규 기능 배치 판단: B2B 파트너 도메인을 신설할 때 개발자는 컨텍스트 맵을 보고 “Partner는 지원 도메인으로 분류되며
goods·ticketing을 Customer 관계로 호출한다”는 규칙을 즉시 확인한다. - 코드 리뷰 시 경계 위반 감지: 코드 리뷰어가
domain.goods가domain.ticketing의 Entity를 직접 import한 PR을 발견하면, 컨텍스트 맵의 “ID만 참조” 규칙을 근거로 반려한다. - 예외 — 애매한 컨텍스트 재분류:
dashboard·image처럼 domain 레이어가 없는 컨텍스트를 분류할 때, “조회 전용/유틸리티 전용” 사유를 근거로 지원 계층에 배치하거나 컨텍스트 맵 범위에서 명시적으로 제외한다. - 빈 상태 — 신규 도메인: 향후 완전히 새로운 도메인(예: Partner)이 추가될 때, 컨텍스트 맵에 아직 없는 도메인은 추가 전에 반드시 이 문서의 갱신 절차를 거친다.
Benchmarking
| 제품/사례 | 카테고리 | 참조 패턴 | URL |
|---|---|---|---|
| Shopify 모놀리스 + Packwerk | 이커머스 모듈러 모놀리스 | 37개 컴포넌트로 도메인을 나누고 package.yml로 컴포넌트 간 의존을 정적으로 강제. “물리적 분리 없이 경계만 강제”하는 접근이 본 과제의 Non-Goals(마이크로서비스 분리 안 함)와 정확히 일치한다 | shopify.engineering/shopify-monolith, Enforcing Modularity with Packwerk |
| Uber DOMA(Domain-Oriented Microservice Architecture) | 모빌리티 대규모 마이크로서비스 | 무통제 서비스 분해(2→2,200+)로 의존 그래프가 통제 불능이 된 뒤, 도메인 구조를 사후에 부과해 정리한 사례. “먼저 구조 없이 쪼갠 뒤 나중에 컨텍스트 맵으로 정리”하면 비용이 커진다는 반면교사로 참조 | DEV Community — Modular Monolith 2026 Guide |
Functional Requirements
| ID | 요구사항 | 우선순위 |
|---|---|---|
| FR-1 | 12개 도메인을 코어(거래)/지원(운영·알림)/서브시스템(AI 에이전트) 3계층으로 분류한 컨텍스트 맵을 산출한다. common은 공유 커널로 별도 표기한다 | P0 |
| FR-2 | 도메인 쌍별 관계 유형과 허용 의존 방향(예: 지원 도메인 → 코어 도메인 조회는 허용, 역방향 금지)을 표로 확정한다 | P0 |
| FR-3 | operator·mcp를 운영 지원 서브시스템으로 명시 분리하고, 코어 거래 도메인과의 의존 방향을 규정한다 | P0 |
| FR-4 | goods·ticketing이 [B2B 파트너 연동](../B2B 파트너 연동/PRD.md)에 유즈케이스를 “제공”하는 경계 인터페이스를 식별한다(UseCase/DomainService 중 어느 레이어로 노출할지는 설계(TDD)에서 확정한다). booking·payment는 현재 소비처가 없으므로 범위에서 제외한다(Non-Goals 참조) | P0 |
| FR-5 | common을 제외한 12개 도메인 각각의 Aggregate Root와 소유 데이터 표(도메인별 쓰기 권한 테이블)를 작성한다 | P0 |
| FR-6 | dashboard·image를 조회·유틸리티 전용 컨텍스트로 명시 분류하고, 컨텍스트 맵 포함 여부와 사유를 문서화한다 | P0 |
| FR-7 | 도메인 간 참조 규칙(ID-only 참조, domain.common 예외) 위반을 탐지하는 정적 검증 방법을 정의한다. 스캔 대상은 domain 레이어 내 Entity/VO의 타 도메인 직접 import로 한정한다 — application 레이어가 여러 도메인 서비스를 조합 호출하는 것은 정상 오케스트레이션이므로 스캔 대상에서 제외한다. 현재 domain 레이어 교차 참조는 0건이며, 이 베이스라인(0건)을 유지하는 것이 목표다 | P1 |
| FR-8 | 컨텍스트 맵 문서 갱신 절차(신규 도메인 추가 시 반드시 거치는 리뷰 단계)를 정의한다 | P2 |
Non-Functional Requirements
- 컨텍스트 맵은 기존 12개 도메인(+ 공유 커널
common, +dashboard·image분류 결과) 전부를 커버해야 한다 — 누락 0건. - FR-7의 정적 검증 스크립트는 전체 스캔 기준 실행 시간 2분 이내여야 한다(로컬 CI 파이프라인 오버헤드 제한).
- 문서 산출물은 코드 변경 없이도 독립적으로 검토 가능해야 한다(설계 문서 리뷰가 코드 리뷰에 선행).
Operations
이 과제의 산출물은 설계 문서이므로 배포 후 모니터링 대상은 없다. 다만 FR-7의 정적 검증 스크립트가 이후 CI에 편입되면, 위반 탐지 건수를 CI 로그에서 추적한다 — 이는 후속 코드 재배치 티켓의 관측 대상이다.
Success Metrics
- 컨텍스트 맵 문서가 12개 도메인 +
common+dashboard/image분류 결과 전부를 커버한다. - 판정 기준: 본인(작성자)이 각 도메인의 대표 유즈케이스 1개씩(총 12개)을 컨텍스트 맵의 관계 유형·의존 방향 표와 대조해 불일치 0건임을 확인하고, 이 확인 결과를 문서 하단에 체크리스트로 남긴다.
- FR-7 정적 스캔 결과, domain 레이어 교차 참조 위반 건수 0건(베이스라인 유지)을 CI 도입 시점에 재확인한다.
- 후속 과제(②B2B 파트너 연동, ③마케팅 이벤트)가 컨텍스트 맵의 관계 유형·의존 방향 표를 그대로 인용해 설계함을 해당 PRD/TDD 리뷰에서 확인한다.
Milestones
- M1 (본 과제 범위): 컨텍스트 맵 문서화(FR-1~FR-6) — 코드 변경 없음.
- M2 (본 과제 범위): 정적 검증 방법 정의(FR-7~FR-8) — 코드 변경 없음.
- M3 (후속 과제, 범위 외): 실제 코드 재배치(
dashboard/image재분류 결과에 따른 이동)는 컨텍스트 맵 확정 후 별도 티켓으로 수행한다.
Open Questions
- 컨텍스트 맵 산출 후 실제 코드 재배치(예:
dashboard/image이동)를 이 과제의 후속 작업으로 즉시 티켓화할지, 필요 시점(다른 과제가 해당 패키지를 건드릴 때)까지 보류할지 결정이 필요하다. - FR-7 정적 검증 규칙을 CI 게이트로 강제(빌드 실패)할지, 코드 리뷰 체크리스트로만 둘지 결정이 필요하다.
Document History
| 날짜 | 변경 내용 |
|---|---|
| 2026-07-03 | 최초 작성 |
| 2026-07-03 | 재검수 1차 반영: 도메인 카운트 정정(12+common), dashboard·image 컨텍스트 커버 누락 해소, FR-7 스캔 범위·베이스라인(0건) 명시, Success Metrics 판정 기준(주체·수치) 구체화, FR-4를 goods·ticketing 2개로 축소하고 booking·payment는 Non-Goals로 이관 |
| 2026-07-03 | 재검수 2차 반영: FR-4의 경계 레이어 확정 표현(“어떤 DomainService 메서드가 경계인지”)을 완화해 UseCase/DomainService 중 노출 레이어는 TDD에서 확정하도록 수정 — [B2B 파트너 연동](../B2B 파트너 연동/PRD.md)이 실제로는 UseCase 레이어를 경유한다는 형제 PRD와의 레이어 불일치 해소 |