2026-07-06 아키텍처 진단(스포츠앱/아키텍트/20260706-사용자정의-도메인경계-갭분석-architecture.md, 이하 “진단 문서”)에서 사용자가 정의한 8개 도메인(유저·모임·커뮤니티·운동시설·상품·결제·주문·채팅) 중 모임·커뮤니티가 코드에 orphan 상태로 확인됐습니다. domain/community/vo/에 VO(Value Object) 4개(CommunityRole, CommunityVisibility, MembershipStatus, SportCategory)만 존재하고 Entity·Repository·Service는 0건입니다. 이 4개 VO의 주석은 이미 채팅 시스템/20260704-채팅시스템고도화-tdd.md(이하 “채팅 TDD”)의 Detail Design을 참조하고 있어, community 컨텍스트 본체가 채팅 고도화 로드맵의 다음 단계로 예정돼 있었음을 보여줍니다.
채팅 PRD(채팅 시스템/20260704-채팅시스템고도화-prd.md)는 이미 FR-1~5로 community 개설·가입·역할·채팅 자동연동을 확정했지만, Non-Goals에 “커뮤니티 피드/게시판/이벤트 관리 — post 도메인과의 결합이나 이벤트(일정) 관리는 향후 별도 PRD로 다룹니다”를 명시하며 게시글 결합을 명시적으로 미룬 상태입니다. 본 PRD가 그 “향후 별도 PRD”이며, 동시에 진단 문서 §10 “즉시 착수” 3개 항목(① community 컨텍스트 본체 ② 컨텍스트 맵 Core 등록 ③ 설계 원칙 5종 문서화)을 실행하는 산출물입니다.
Problem Definition
현재(AS-IS) 상태의 불편은 3가지입니다.
모임을 만들 방법이 없습니다.domain/community에 Entity가 없어(VO 4개뿐, find domain/community -name "*.kt" = vo 4개 전부) 유저가 모임을 개설·가입·운영하는 기능이 코드에 전혀 없습니다.
채팅 연동 메커니즘은 준비됐지만 미사용입니다.Room.kt(domain/message/entity/Room.kt)가 이미 contextType: RoomContextType?·contextId: Long?을 보유하고 RoomContextType.COMMUNITY(domain/message/vo/RoomContextType.kt)까지 예약해 뒀지만, community 본체가 없어 createForContext(type, RoomContextType.COMMUNITY, ...) 호출이 실제로 일어나지 않습니다.
게시글이 모임·커뮤니티와 전혀 결합되지 않습니다.Post.kt(domain/post/entity/Post.kt)는 userId·title·content·type(PostType: FREE/NOTICE/QUESTION/REVIEW)만 가진 전역 게시판이라, 특정 모임·커뮤니티에 속한 게시글이라는 개념이 없습니다. PostType에도 모집(RECRUITMENT) 유형이 없어(grep -rni "recruit|모집" domain/ 0건, 진단 문서 §AS-IS 실측 재확인), 게시글로 인원을 모집한다는 사용자 요구를 표현할 지점이 아예 없습니다.
Goals / Non-Goals
Goals
목표는 진단 문서가 제시한 3가지 관점입니다.
관점
이 PRD가 하는 일
확장 가능성
CommunityRole(HOST/MEMBER)·CommunityVisibility(PUBLIC/PRIVATE) 2계층 구조를 유지하되, 신규 역할·공개 단계를 enum 확장만으로 추가할 수 있게 설계합니다. 모집(recruitment) 컨텍스트가 이후 게시글 ID만 참조해 붙을 수 있는 훅 지점을 마련합니다.
재사용 가능성
신규 채팅 기능을 만들지 않습니다 — 채팅 TDD가 이미 설계한 Room.contextType/contextId 확장 메커니즘과 도메인 이벤트(CommunityCreated/MemberJoined/MemberLeft) 연동 패턴을 그대로 재사용합니다. 신규 게시판 도메인도 만들지 않습니다 — 기존 post 도메인에 community 참조 컬럼만 additive로 추가합니다.
통합
사용자가 구분한 “모임”(폐쇄형)과 “커뮤니티”(개방형)를 2개 컨텍스트로 쪼개지 않고 CommunityVisibility(PUBLIC/PRIVATE) 하나로 겸용합니다. 컨텍스트 맵에 community를 Core로 등록해, 향후 recruitment·시설상품 등이 참조할 명확한 앵커를 제공합니다.
Non-Goals (범위 밖 — 오버엔지니어링 차단)
항목
미포함 사유
트리거(착수 조건)
recruitment 컨텍스트 본체 (모집 신청·정원 상태 머신·취소 10% 수수료)
post/community와 변경 주기·라이프사이클이 다른 독립 컨텍스트 — 진단 문서 §4 문제C 결론. 본 PRD는 게시글에 “모집 표시” 훅 지점만 연다
모집 FR 스펙 확정 시 별도 PRD
체육관 예약 연동 실사용 로직 (게시글 작성 전 선택적 예약, 하루 전 무료 취소 CancellationPolicy 전략)
Booking.refund()가 refundAmount를 외부 인자로만 받는 하드코딩 상태(BookingDomainService.kt:174)를 지금 전략 객체로 바꿀 소비처(FR)가 없음 — 진단 문서 §4 문제D 결론
시설 예약 고도화 FR 확정 시 별도 PRD
CommunityRole 중간 계층(MANAGER) 선제 도입
현재 HOST/MEMBER 2계층으로 충분 — enum 확장은 저비용이라 실제 운영 위임 요구가 생길 때 추가(YAGNI)
모임장이 운영을 위임할 실제 요구 발생 시
모임·커뮤니티 물리적 2컨텍스트 분리
CommunityVisibility로 겸용 가능 — 조기 분리는 멤버십·역할·채팅 연동 로직 중복
폐쇄형·개방형의 멤버십 모델이 실제로 갈라질 때
신규 실시간 채팅 기능 (게스트 초대, WebSocket 등)
이미 채팅고도화 PRD FR-1~18 범위 — 본 PRD는 그 이벤트 연동을 재사용만 함
해당 없음 (이미 별도 PRD 진행 중)
시설상품(PT·클래스) 모델링, 상품/주문 통합 aggregate, b2c/b2b 계정 타입 분리
community 스코프 밖 — 진단 문서 §10에서 “설계 원칙”으로만 문서화하고 구현하지 않기로 확정한 항목
각 항목 트리거는 진단 문서 §7 참조
User Scenarios
페르소나: 방장(Host, 모임·커뮤니티 개설자), 멤버(Member, 가입자), 방문자(비회원·비멤버, PUBLIC 커뮤니티 열람자).
해피 패스
방장이 “주말 축구 모임”을 PRIVATE(폐쇄형, 모임)로 개설한다 → 개설자가 HOST 역할을 갖고, 전용 그룹 채팅방이 자동 생성된다(기존 RoomContextType.COMMUNITY 재사용, 신규 채팅 로직 없음).
유저가 “배드민턴 정보방”이라는 PUBLIC(개방형, 커뮤니티)에 즉시 가입한다 → 종목별 게시글 목록을 보고 질문 게시글을 작성한다.
방장이 모임 내에 “이번 주 토요일 오전 10시, 3명 더 필요합니다”라는 게시글을 모집 표시를 켜서 작성한다 → 멤버·방문자가 게시글 목록에서 모집 표시된 게시글을 구분해 볼 수 있다(신청·정원 처리는 없음 — 훅 지점만).
멤버가 모임을 탈퇴한다 → 연결된 그룹 채팅방에서도 자동으로 퇴장된다(채팅 PRD FR-5 재사용).
방장이 다른 멤버에게 HOST 권한을 위임한다 → 위임받은 멤버가 새 방장이 되고 기존 방장은 MEMBER로 전환된다.
예외 · 빈 상태
비회원이 PRIVATE 모임에 가입을 신청한다 → PENDING_APPROVAL 상태로 대기하고, 방장 승인 전까지 게시글·멤버 목록 조회가 거부된다(서버 강제 인가 — 채팅 PRD FR-13 ② 패턴 재사용, 클라이언트 게이팅에 의존하지 않음).
방장이 위임 전에 모임을 탈퇴하려 한다 → 거부된다(채팅 TDD 상태 보호 규칙 재사용: “HOST 위임 전 탈퇴 거부”).
신규 개설된 모임·커뮤니티에 게시글이 아직 없다 → 게시글 목록에 빈 상태(“아직 게시글이 없습니다”) 문구를 노출한다.
기존 전역 게시판 글(어떤 모임·커뮤니티에도 속하지 않는 글, community 참조 없음)은 그대로 조회·작성이 유지된다 — 하위 호환.
이미 LEFT·KICKED 상태인 멤버가 같은 모임에 재가입을 시도한다 → 신규 가입 신청으로 처리되며(MembershipStatus는 terminal 상태에서 재전이 불가), PUBLIC이면 즉시 재가입, PRIVATE이면 승인 대기부터 다시 시작한다.
Benchmarking
제품명
카테고리
참조 패턴
URL
네이버 밴드
모임·그룹 SNS
공개 설정을 비공개·밴드명공개·공개 3단계로 세분화 — 본 PRD Open Question(공개범위 세분화)의 참조 옵션
유저는 이름·설명·공개 여부(PUBLIC/PRIVATE)·종목 카테고리(SportCategory)를 지정해 모임 또는 커뮤니티를 개설할 수 있다. 개설자는 HOST 역할을 갖는다. (채팅 PRD FR-1 기준선 재확인)
FR-2
P0
PUBLIC은 즉시 가입되고, PRIVATE은 HOST 승인 후 가입된다. 승인 대기 중 HOST가 거부(reject)했을 때의 상태 표현은 Open Question Q3에서 확정한다. (채팅 PRD FR-2 기준선)
FR-3
P0
멤버는 HOST(1명) 또는 MEMBER(N명) 역할을 가지며, HOST는 멤버를 강퇴하거나 HOST 권한을 위임할 수 있다. HOST는 위임 전 탈퇴할 수 없다. (채팅 PRD FR-3 기준선)
FR-4
P0
개설 시 전용 그룹 채팅방이 자동 생성되고, 가입과 동시에 채팅방 참여자로 자동 등록되며, 탈퇴·강퇴 시 자동 퇴장된다. 기존 Room.contextType=COMMUNITY 확장 메커니즘을 그대로 재사용하고 신규 채팅 로직을 만들지 않는다. (채팅 PRD FR-4/5 기준선)
FR-5
P0
”모임”(폐쇄형)과 “커뮤니티”(개방형)를 별도 컨텍스트로 분리하지 않고, 단일 community 컨텍스트에서 CommunityVisibility(PUBLIC/PRIVATE)만으로 겸용한다.
FR-6
P0
모임(PRIVATE)에 속한 게시글을 작성할 수 있다. post 도메인에 community 참조(nullable, additive 컬럼)를 추가하며, 기존 전역 게시글(참조 없음)은 그대로 유지한다.
FR-7
P1
개방형 커뮤니티(PUBLIC)에서도 게시글을 작성할 수 있다. community와의 결합 방식(특정 PUBLIC community 소속 여부)은 Open Question Q1의 답변에 따라 확정한다.
FR-8
P1
PRIVATE community의 게시글·멤버 목록은 ACTIVE 멤버만 조회할 수 있고, PUBLIC community의 게시글은 비멤버도 열람할 수 있다(멤버 목록 조회는 PUBLIC이라도 ACTIVE 멤버로 한정).
FR-9
P1
community 게시글은 작성자가 “인원 모집” 여부를 표시할 수 있다. 표시만 제공하며 신청·정원 관리·취소 수수료 로직은 포함하지 않는다(recruitment 컨텍스트가 이후 이 표시와 게시글 ID를 훅 지점으로 참조). 표시 적용 범위(모임/커뮤니티/전역 게시글)는 Open Question Q5에서 확정한다.
FR-10
P2
docs/domain-context-map.md와 도메인 경계 재설계/TDD.md 관계표·5계층 분류표에 community를 Core 도메인으로 등록한다. TDD 단계에서 ArchUnit 화이트리스트(R1~R4) 자동 포함 여부를 확인한다. 코드 변경이 아닌 문서 산출물이다.
FR-11
P2
진단 문서 §10에서 도출된 설계 원칙 5종(① 상품 통합 aggregate 금지 ② 주문 통합 쓰기 aggregate 금지 ③ 모집은 post가 아닌 recruitment 소유 ④ 취소 정책은 전략 객체로, refundAmount 외부 주입 지양 ⑤ b2c/b2b는 롤+Partner 유지)를 프로젝트 설계 원칙 문서로 기록한다. 코드 변경이 아닌 문서 산출물이다.
Non-Functional Requirements
구분
요구사항
성능
community 목록·상세 조회 API는 P95 300ms 이내(로컬 docker compose 단일 인스턴스 기준, 진단 문서 §2 상시 RPS 10 미만 전제). community 게시글 목록 조회는 페이지당 20건 페이지네이션, P95 300ms 이내
확장성
CommunityRole·CommunityVisibility·MembershipStatus 확장(신규 enum 값 추가)이 기존 데이터 마이그레이션 없이 가능해야 한다. community 1,000개, community당 멤버 500명까지 스키마 변경 없이 확장 가능해야 한다(설계 목표 수치, 실측 트래픽 없음)
보안
PRIVATE community의 게시글·멤버 목록 조회는 서버 사이드에서 ACTIVE 멤버 여부를 강제 검증한다(requireActiveMember 패턴 재사용). 클라이언트 UI 게이팅만으로 비공개 정보를 가리지 않는다
데이터 정합
post의 community 참조는 ID만 보유(FK 컬럼 금지, private-db-schema-convention 준수)하며, community 도메인 패키지를 직접 import하지 않는다(ArchUnit R1 도메인 교차 참조 금지 유지)
Operations
배포 후 다음을 관측합니다.
지표: 신규 community 개설 수(일별), 활성 community 수(최근 7일 내 게시글 또는 채팅 발생), 게시글 작성 수(모임 내부/개방형 커뮤니티/전역 분리 집계), 모집 표시 게시글 비율, community 개설 시 채팅방 자동 생성 성공률
알람: community 개설 시 채팅방 자동 생성이 실패(이벤트 처리 실패)하면 알림 — 기존 NotificationEventWorker 계열 실패 로그 패턴 재사용
대시보드/로그: community별 멤버 수·게시글 수·채팅 활성도를 주기적으로 집계해 dashboard 컨텍스트에서 노출(기존 Conformist 읽기 집계 패턴 재사용, 신규 집계 저장소를 만들지 않음)
회귀 감시: ArchUnit R1(도메인 교차 참조 0건) 회귀 테스트에 community 패키지가 자동 포함되는지 CI에서 확인
Success Metrics
지표
목표
측정 방법
community 도메인 본체화
domain/community에 Entity·Repository·Service가 0건 → 1건 이상씩 존재
게시글 종목 분류 체계 (Q1): 개방형 커뮤니티의 “종목별 게시글”이 (a) 특정 PUBLIC community에 가입해야 작성 가능한 것인지, 혹은 (b) Post에 독립적인 종목 태그를 추가해 어떤 community에도 속하지 않고 자유롭게 작성 가능한 전역 게시글을 의미하는지 확인이 필요합니다. domain-reference.md의 “모임에 속하지 않아도 됨”이라는 문구가 두 해석 중 어느 쪽인지에 따라 FR-7의 결합 방식이 달라집니다.
모임 정원 (Q2): “소모임 형태로 특정 인원들로 운동 예약”이 정원 상한을 의미하는지, 상한 도달 시 서버가 가입 신청을 자동 거부하는지 혹은 방장이 수동으로 가입을 마감하는지, 정원 필드가 필수인지 선택인지 결정이 필요합니다.
가입 거부 상태 표현 (Q3): 현재 MembershipStatus(ACTIVE/PENDING_APPROVAL/LEFT/KICKED)에는 거부(REJECTED) 상태가 없습니다(domain/community/vo/MembershipStatus.kt). 방장이 승인 대기 신청을 거부했을 때 레코드를 삭제할지, 신규 REJECTED 상태를 추가할지, 기존 KICKED를 재사용할지 결정이 필요합니다.
공개범위 세분화 (Q4): 현재 2단계(PUBLIC/PRIVATE)로 충분한지, 네이버 밴드처럼 “이름만 검색 노출·게시글은 비공개” 같은 3단계 세분화가 필요한지 확인이 필요합니다.
모집 표시 적용 범위 (Q5): FR-9의 모집 표시가 모임(PRIVATE) 게시글에만 적용되는지, 개방형 커뮤니티(PUBLIC) 게시글에도 적용되는지, 전역 게시글(community 참조 없음)에도 적용되는지 확인이 필요합니다.
Success Metrics 초안 수치의 근거 (Q6): 개인 프로젝트로 실측 트래픽이 없어 community 개설 수(4주 10개)·게시글 작성 비율(D7 20%)은 초안 수치입니다. 1단계 배포 후 실측치로 재조정이 필요합니다.
Document History
날짜
변경 내용
2026-07-06
최초 작성 — 아키텍처 진단 §10 즉시 착수 3개 항목을 근거로 community 컨텍스트 본체 구축 PRD 작성. AS-IS는 Room.kt·Post.kt·community VO 4개 실측 근거. 채팅 PRD FR-1~5를 기준선으로 재확인하고 게시글 결합·모집 훅·컨텍스트 맵 등록·설계 원칙 문서화를 신규 스코프로 추가. Open Questions 6건(종목 분류·정원·가입 거부 상태·공개범위 세분화·모집 훅 범위·지표 근거) 산출