스포츠앱/아키텍트/20260706-사용자정의-도메인경계-갭분석-architecture.md(이하 “진단 문서”)는 사용자 정의 8개 도메인(유저·모임·커뮤니티·운동시설·상품·결제·주문·채팅)과 코드 도메인의 갭을 매트릭스로 확정했습니다. 이 PRD는 그 갭 중 §7 장기 진화 계획의 P2(모집)·P3(시설상품) 단계와, §10 “트리거 도달 시” 목록의 소모임 예약 연동(community↔booking) 항목을 제품 요구사항으로 확정합니다.
같은 폴더의 20260706-post-community-연동-prd.md(이하 “post-community PRD”)는 자신의 Milestones에서 이 작업을 명시적으로 “2단계” 로 예고했습니다: “recruitment 컨텍스트(모집 신청·정원·취소 10% 수수료), 체육관 예약 연동(CancellationPolicy 전략), 시설상품(PT·클래스)”. 본 PRD가 그 2단계입니다.
기존 산출물과의 관계(중복 방지, 필독):
문서
상태
이 PRD와의 관계
모임·커뮤니티/20260706-모임커뮤니티컨텍스트구축-prd.md
폐기(참조 금지) — stale 트리(진단 문서 재정정 이전) 기반으로 community를 orphan으로 오판정한 초안. post-community PRD의 Document History가 폐기를 명시
참조하지 않습니다
모임·커뮤니티/20260706-post-community-연동-prd.md
유효 — community 완성 컨텍스트 확인 후 재작성됨
FR-8(문서·거버넌스 정합: docs/domain-context-map.md 갱신, DomainClassification.core에 community 등록)과 FR-1~7(모임 게시글 ID참조·종목별 게시글 분류·인가)을 이미 확정했습니다. 본 PRD는 이 FR들을 선행 조건으로 삼고 재정의하지 않습니다
도메인 경계 재설계/{PRD,TDD}.md
유효 — ArchUnit 거버넌스(R1~R4)
본 PRD의 신규 도메인(recruitment)·확장 도메인(facility·booking)도 이 규칙(도메인 교차 import 금지, ID 참조만)을 그대로 따릅니다
정리하면, 사용자가 요청한 4개 스코프 중 ① P0 선행 정합과 ④ community 콘텐츠 연동의 게시글 부분(모임 게시글·종목별 게시글) 은 이미 post-community PRD가 확정했으므로 이 PRD에서 새 FR로 다시 쓰지 않습니다. 이 PRD는 ② 모집(recruitment), ③ 시설상품·운영시간·자동슬롯, 그리고 ④의 잔여 갭인 소모임 예약 연동(community↔booking) 세 가지만 다룹니다.
Problem Definition
AS-IS (진단 문서 근거)
모집(구인/구직) 개념이 전혀 없습니다.grep -rni "recruit|모집|applicant" domain/이 0건입니다(진단 문서 AS-IS 실측 1). 유저가 “이번 주말 3명 더 필요합니다” 같은 모집 글을 올리거나, 그 글에 신청하거나, 신청을 취소할 방법이 코드에 없습니다.
체육관·시설이 운영시간·휴무·자동 슬롯 생성을 지원하지 않습니다.Facility.kt:22-58의 생성자 필드에 운영시간·휴무일 관련 필드가 전무하고(operatingHours·holiday·openTime/closeTime 0건), Slot.kt:16-38은 소유자가 timeRange(문자열)와 capacity를 한 건씩 수동으로 입력해야만 예약 가능 시간이 생깁니다. 요일별 운영시간을 등록해도 자동으로 예약 가능 회차가 만들어지지 않습니다.
PT·클래스 같은 시설상품(강습형 상품) 개념이 없습니다.grep -rni "program|lesson|pilates" domain/facility/가 0건입니다. 현재 goods(물품)·ticketing(공연 좌석)만 판매 가능하고, “정원 있는 시간대별 강습”을 표현할 곳이 없습니다.
모임(community)과 시설 예약(booking)이 서로를 모릅니다. community와 booking 사이에 참조·연동 코드가 0건이라, 소모임 방장이 모임 내에서 “이번 주 토요일 우리 모임은 이 체육관 이 시간대를 씁니다”를 표현할 방법이 없습니다. 멤버는 채팅으로만 일정을 공유해야 합니다.
Goals / Non-Goals
Goals
영역
목표
모집
유저가 모집 글을 개설하고, 정원 내에서 신청을 받고, 신청 취소 시 수수료를 부과하는 흐름을 신규 recruitment 컨텍스트로 제공한다. post·community는 ID로만 참조하고, 소유권은 recruitment가 갖는다(진단 문서 §4 문제C-3 결론 그대로 적용).
시설상품
facility 산하에 PT·클래스 같은 슬롯·정원 기반 시설상품(program) 개념을 추가하고, 시설 운영시간·휴무 등록만으로 예약 가능 회차가 자동 생성되게 한다(진단 문서 §4 문제E-1, §7 P3).
소모임 예약 연동
community가 booking의 기존 예약(Slot)을 ID로 참조해 모임 활동 일정으로 연결할 수 있게 한다 — 신규 예약 메커니즘을 만들지 않고 기존 booking을 재사용한다(진단 문서 §6 사용자 도메인 매핑, “커뮤니티(개방형) → booking(체육관 예약 선택)”).
Non-Goals (명시적 미채택 — 진단 문서 결론 그대로 계승)
항목
사유
단일 Product/Order 통합 aggregate
라이프사이클 이질(중고 C2C·SKU 재고·좌석 재고·시간 게이트·슬롯이 한 aggregate에 못 들어감). 진단 문서 §4 문제A-1/B-1 미채택 결론 계승
모임·커뮤니티 2컨텍스트 분리
CommunityVisibility(PUBLIC/PRIVATE) 하나로 겸용 가능. 진단 문서 §4 문제C-1 미채택, post-community PRD도 동일 원칙 적용 중
CommunityRole 중간 계층(MANAGER) 선제 도입
현재 HOST/MEMBER 2계층으로 충분(YAGNI) — 실제 운영 위임 요구 발생 시 enum 확장(저비용). 진단 문서 §4 문제C 결론
b2c/b2b 계정 타입 1급 분리
유저가 중고 판매(b2c)와 브랜드 판매(b2b)를 동시에 할 수 있는 다중 역할성을 RBAC 롤이 자연 지원. 진단 문서 §4 문제F 결론
ticketing/payment 물리 분리(서비스·DB 분리)
상시 RPS 10 미만 추정 규모에서 조기 분리는 분산 트랜잭션·운영 비용만 유발. 측정된 피크 부하 임계 초과 시에만(진단 문서 §7 P6)
통합 catalog/order-query 읽기 파사드
이번 스코프에 교차 조회 화면 스펙이 없다. 상품·주문 통합 검색/이력 화면이 스펙에 잡히면 별도 PRD(진단 문서 §4 문제A-3/B-3, §7 P5)
체육관 예약(booking) 자체의 취소 정책 엔진(시설별 상이 취소료, 하루 전 무료 등)
시설상품(program) 예약은 기존 Booking.refund()(외부 인자 수령) 동작을 그대로 사용한다 — booking 전반의 시설별 취소 정책은 이번 스펙에 없다(진단 문서 §4 문제D, §7 P4). 모집(recruitment)의 취소 수수료(FR-4)는 이 Non-Goal과 별개로 이번 범위에 포함되며, booking이 아니라 recruitment가 소유하는 정책이다 — 혼동 방지를 위해 명시한다
채팅 시스템 고도화 PRD(FR-1~18) 범위 — 본 PRD는 어떤 신규 채팅 로직도 추가하지 않는다
모집 신청 대기열(waitlist), 부분 환불·분할 결제
이번 스코프는 정원 도달 시 즉시 마감(대기열 없음)·단일 결제-단일 환불만 다룬다(확정)
User Scenarios
페르소나: 모집 개설자(Recruiter), 모집 신청자(Applicant), 시설 운영자(FacilityOwner), 시설 이용자(Member), 소모임 방장(Host), 소모임 멤버(Member).
#
페르소나
시나리오
유형
1
모집 개설자
”이번 주말 축구 3명 더 필요해요”를 정원 3명·참가비 5,000원·마감일시 지정해 모집 글을 개설한다
해피 패스
2
모집 신청자
정원 내에서 참가비를 결제하고 신청을 완료한다
해피 패스
3
모집 신청자
마감까지 7일 초과 남은 시점에 신청을 취소하면 수수료 없이 참가비 전액을 환불받는다
해피 패스
4
모집 신청자
마감까지 3일 초과 7일 이내 남은 시점에 신청을 취소하면 참가비의 5%가 수수료로 공제되고 95%를 환불받는다
해피 패스
5
모집 신청자
마감까지 3일 이내(마감 직전까지) 남은 시점에 신청을 취소하면 참가비의 10%가 플랫폼 수수료로 공제되고 90%를 환불받는다
해피 패스
6
모집 신청자
마감 이후에는 신청 취소를 시도해도 거부된다(참가 확정)
예외
7
모집 신청자
이미 정원이 가득 찬 모집에 신청을 시도하면 거부된다(409) — 동시에 여러 명이 마지막 자리에 신청해도 정원을 초과해 확정되지 않는다
예외·동시성
8
모집 개설자
정원 미달로 모집 자체를 취소하면, 신청자 전원이 수수료 없이 전액 환불받는다(개설자 귀책은 신청자에게 불이익이 없다)
예외
9
모집 신청자
신청 0건인 모집을 조회하면 빈 신청자 목록을 정상 응답으로 받는다
엣지
10
시설 운영자
요일별 운영시간(예: 평일 06:0022:00, 브레이크타임 12:0013:00)을 등록하면, 스케줄러가 매일 향후 예약 가능 회차(Slot)를 자동 생성한다
해피 패스
11
시설 운영자
특정 날짜를 휴무일로 지정하면, 그 날짜에는 회차가 자동 생성되지 않는다
해피 패스
12
시설 이용자
휴무일로 지정된 날짜에 예약 가능 회차를 조회하면 빈 목록을 정상 응답으로 받는다(에러 아님)
엣지
13
시설 운영자
자동 생성된 특정 회차를 수동으로 마감 처리(클로즈)해 예약을 막는다
해피 패스
14
시설 운영자
운영시간 외 특별 회차(예: 임시 개관)를 수동으로 열어 예약을 받는다
해피 패스
15
시설 운영자
PT(1:1 강습) 시설상품을 정원 1명·소요시간 60분으로 등록한다
해피 패스
16
시설 이용자
등록된 시설상품(program)의 특정 회차를 예약하고 결제한다 — 결제는 기존 booking 결제 접점을 그대로 사용한다
해피 패스
17
시설 이용자
정원이 찬 시설상품 회차를 예약 시도하면 거부된다
예외
18
소모임 방장
모임 내에서 특정 체육관의 예약 가능 회차를 선택해 “이번 주 토요일 활동”으로 연결한다 — 신규 예약을 만들지 않고 기존 booking Slot을 참조만 한다
해피 패스
19
소모임 멤버
방장이 연결한 예약의 시설·일시·정원 정보를 모임 내에서 열람한다
해피 패스
20
PRIVATE 소모임 비멤버
승인되지 않은 상태로 모임에 연결된 예약 상세를 열람 시도하면 거부된다(post-community PRD FR-2 인가 규칙 재사용)
예외
21
소모임 방장
연결한 예약이 존재하지 않는 신규 모임을 조회하면 “연결된 예약이 없습니다” 빈 상태를 받는다
엣지
22
시설 운영자(운영 관점)
자동 슬롯 생성 배치가 같은 14일 윈도우로 재실행돼도, 이미 생성된 (시설·날짜·시간대) 회차는 건너뛰고 새로 윈도우에 들어온 날짜분만 생성된다 — 중복 회차가 생기지 않는다
엣지·멱등
Benchmarking
제품명
카테고리
참조 패턴
URL
프립(FRIP)
취미·소모임 액티비티 플랫폼
신청 마감일 기준으로 취소 수수료를 단계적으로 산정(결제 후 1시간 이내 무료, 마감 2일 전 전액환불, 마감 1일마감 전 50% 수수료, 마감 이후·당일 환불 불가) — “마감까지 남은 기간에 따라 수수료율이 단계적으로 오른다”는 구조를 이 PRD의 FR-4(단계별 수수료: 7일 초과 무료 / 37일 5% / 3일 이내 10%)에 그대로 채용
유저는 제목·설명·정원(1명 이상)·참가비(0원 포함)·활동 일시·신청 마감 일시를 지정해 모집 글을 개설할 수 있다. 개설자는 모집의 소유자(Recruiter) 권한을 갖는다.
P0
FR-2
모집은 특정 community에 선택적으로 소속될 수 있다(communityId 참조, ID만 보유 — post-community PRD와 동일하게 도메인 교차 import 없이 ID 참조만). 소속 시 열람·신청 인가는 소속 모임의 CommunityVisibility·멤버십 규칙을 따른다(post-community PRD FR-2 인가 규칙 재사용). 미소속(communityId 없음) 모집은 전체 공개로 동작한다.
P0
FR-3
신청자는 정원 내에서 참가비를 결제하고 신청을 완료할 수 있다. 정원이 가득 찬 모집에는 신규 신청이 거부된다(동시 신청이 몰려도 정원을 초과해 신청이 확정되지 않는다).
P0
FR-4
신청자는 신청 마감 일시 이전에 신청을 취소할 수 있다. 취소 수수료율은 마감까지 남은 기간에 따라 단계적으로 정해진다(recruitment가 소유하는 취소 정책 — 진단 문서 §4 문제D의 “정책을 전략 객체로 계산한다”는 원칙을 recruitment에 재사용한 것이며, booking의 시설별 취소 정책과는 별개다): ① 마감 7일 초과 남은 시점 취소는 무료(0%) ② 마감 3일 초과~7일 이내 남은 시점 취소는 5% ③ 마감 3일 이내(마감 직전까지) 취소는 10%. 공제된 수수료는 플랫폼에 귀속되고, 신청자는 (100%-수수료율)만큼 환불받는다. 신청 마감 이후에는 신청 취소가 거부된다(참가 확정).
P0
FR-5
개설자는 모집을 취소(전체 마감)할 수 있다 — 이 경우 이미 신청 완료한 전원에게 수수료 없이 참가비 전액을 환불한다(개설자 귀책 취소는 신청자에게 불이익이 없다. FR-4의 단계별 수수료는 신청자 자율 취소에만 적용된다).
P0
FR-6
신청 완료·단계별 수수료 공제 후 환불(FR-4)·모집 취소 전액환불(FR-5)은 기존 판매 3종(BOOKING/GOODS/TICKETING)과 동일한 동기 결제 확정/취소 접점(OrderConfirmationGateway.confirm/cancel)을 OrderType.RECRUITMENT로 확장해 그대로 재사용한다 — 신규 비동기 이벤트 경로(예: PaymentCompletedEvent Kafka 구독)는 만들지 않는다(확정 — 진단 문서 §6 TO-BE 다이어그램의 `recruitment →
취소수수료 C/S
그룹 B — 시설상품·운영시간·자동슬롯
ID
요구사항
우선순위
FR-7
시설 운영자는 요일별 운영시간(시작·종료 시각, 복수 브레이크타임 선택)을 등록할 수 있다.
P0
FR-8
시설 운영자는 특정 날짜를 휴무일로 지정할 수 있다 — 휴무일에는 예약 가능 회차가 생성되지 않는다.
P0
FR-9
등록된 운영시간·휴무일을 기준으로, 향후 예약 가능 회차(Slot)가 매일 자동 생성된다 — 운영자가 회차를 한 건씩 수동 입력하지 않아도 된다. 배치는 매일 향후 14일 윈도우 전체를 대상으로 재실행되며, 이미 존재하는 (시설, 날짜, 시간대) 조합의 회차는 건너뛰고(멱등 재생성) 새로 윈도우에 포함된 날짜분만 생성한다 — 기존 회차 UNIQUE 제약(facility_id·date·time_range 조합, V14 마이그레이션 기준)과 충돌 없이 매일 재실행 가능해야 한다.
P0
FR-10
시설 운영자는 자동 생성된 특정 회차를 수동으로 마감(클로즈)하거나, 운영시간 외 특별 회차를 수동으로 열 수 있다. 클로즈는 신규 예약만 차단하는 상태 전이이며, 이미 확정된 기존 예약은 그대로 유지된다 — 예약이 있는 회차를 완전히 삭제(제거)하는 것과는 다른 별개 동작이다(삭제는 활성 예약이 있으면 거부되는 기존 동작을 그대로 따른다).
P1
FR-11
시설 운영자는 시설 산하에 PT·클래스 같은 시설상품(program: 이름·설명·가격·정원·소요시간)을 등록할 수 있다 — goods(물품 카탈로그)와는 별도 개념이다.
P1
FR-12
이용자는 등록된 시설상품의 특정 회차를 예약·결제할 수 있다 — 예약·결제는 기존 booking의 예약·결제 접점을 그대로 재사용하며, 신규 결제 접점(신규 OrderType 등)을 만들지 않는다(확정 — 진단 문서 §8(2) OrderType 4개 초과 시 확장 마찰 임계 근거). 정원이 찬 회차는 예약이 거부된다.
P1
그룹 C — 소모임 예약 연동 (community ↔ booking)
ID
요구사항
우선순위
FR-13
소모임 방장은 모임 내에서 기존 booking의 예약 가능 회차를 선택해 모임 활동 일정으로 연결할 수 있다 — community가 booking을 ID로만 참조하며, 신규 예약 메커니즘을 만들지 않는다(확정 — 진단 문서 §8(2) 근거로 program과 동일하게 기존 booking 접점만 재사용).
P1
FR-14
모임에 연결된 예약의 정원은 연결된 booking Slot의 기존 정원을 그대로 따른다 — community가 별도의 정원을 관리하지 않는다.
P1
FR-15
소모임 멤버는 방장이 연결한 예약의 시설·일시·정원 정보를 모임 내에서 열람할 수 있다 — 열람 인가는 소속 모임의 CommunityVisibility·멤버십 규칙을 따른다(post-community PRD FR-2 인가 규칙 재사용).
P1
Non-Functional Requirements
구분
요구사항
성능
모집 목록·시설상품(program) 목록·시설 예약 가능 회차 조회 API는 P95 300ms 이내(로컬 docker compose 단일 인스턴스 기준 — post-community PRD·모임커뮤니티컨텍스트구축 PRD와 동일 목표선)
동시성
모집 신청·시설상품 예약 모두 동시 요청 100건이 마지막 1자리를 두고 경합해도 정원을 초과해 확정되는 건이 0건이어야 한다
배치
자동 슬롯 생성 스케줄러는 1일 1회 실행되며, 향후 14일치 회차를 생성한다(확정 — 대다수 예약 서비스(네이버 예약 등)가 지원하는 2~4주 사전 예약 기간과 유사한 수준이고, 이보다 길게 잡으면 미사용 Slot 데이터가 불필요하게 누적되는 부담이 있어 14일로 확정한다. 운영 중 조정 가능한 설정값으로 둔다)
데이터 정합
recruitment↔community, community↔booking, program↔facility 간 참조는 전부 일반 컬럼(ID)으로 두고 FK 제약을 걸지 않는다(private-db-schema-convention FK 컬럼 금지 준수). 도메인 패키지 간 교차 import는 0건을 유지한다(ArchUnit R1)
결제 정합
모집 신청·취소, 시설상품 예약의 결제·환불은 기존 결제 확정/취소 접점을 재사용하며 중복 처리(이중 결제·이중 환불)가 발생하지 않아야 한다. 모집 취소 수수료는 플랫폼 귀속 단일 처리로 확정하며, 개설자에게 배분·정산하는 경로는 두지 않는다
확장성
recruitment의 정원·수수료율, facility의 운영시간·휴무일 구조는 신규 필드 추가 없이 시설 수·모집 건수가 늘어나도 스키마 변경 없이 확장 가능해야 한다(설계 목표, 실측 트래픽 없음)
알람: 자동 슬롯 생성 스케줄러가 예정된 배치를 실패(예: 향후 14일치 회차 미생성)하면 알림 — 기존 알림 처리(NotificationEventWorker 계열) 패턴 재사용. 기존 회차와 중복돼 건너뛴(skip) 건은 정상 동작이며 실패로 집계·알림하지 않는다(FR-9 멱등 재생성 규칙과 정합) — 배치 실패 알림은 실제 생성 오류(예: DB 오류로 신규 날짜분 미생성)에만 발생한다