post-community 연동 PRD
Background
community는 Community·CommunityMember Entity, CommunityDomainService, UseCase 10개, Controller, EventWorker까지 갖춘 완성 컨텍스트입니다(domain/community/**, application/community/**, presentation/community/**). post는 userId/title/content/type(PostType: FREE/NOTICE/QUESTION/REVIEW)만 가진 전역 게시판으로, community를 전혀 참조하지 않습니다(domain/post/entity/Post.kt#Post — communityId·SportCategory 필드 0건, post-community 상호 import 0건).
모임 기능이 완성됐는데도 모임 안에서 게시글을 쓸 방법이 없고, 종목별로 게시글을 묶어 볼 방법도 없는 것이 현재의 갭입니다. 이 PRD는 새 도메인을 만드는 것이 아니라 기존 post·community 두 컨텍스트를 연동해 재사용하는 것을 목표로 합니다.
Problem Definition
- AS-IS:
Post는communityId가 없어 특정 모임에 소속시킬 수 없습니다(domain/post/entity/Post.kt:19-36).PostType은 종목 개념이 없고,PostCriteria(application/post/dto/PostCriteria.kt)의 검색 조건도type/userId/keyword뿐이라 종목별 필터가 불가능합니다. - 사용자가 모임에 가입해도 그 모임 전용 게시판이 없어, 모임 관련 소통은 전역 게시판(비소속)에 뒤섞이거나 채팅(
messageRoom, contextType=COMMUNITY)으로만 가능합니다. - 종목(축구/농구/러닝 등)별로 게시글을 묶어 보는 기능이 없어, 관심 종목 콘텐츠를 찾기 위해 전체 게시글을 훑어야 합니다.
docs/domain-context-map.md:20-21이 community를 “(VO만) — 구축 중”으로 기술하고 있어 실제 코드 상태(완성된 10개 UseCase)와 어긋납니다.SupportToCoreDependencyRulesTest.kt#DomainClassification.core목록에도community가 빠져 있어 코어 도메인 간 의존 규칙(R3) 검증 대상에서 누락돼 있습니다.
Goals / Non-Goals
Goals
- post가 community에 선택적으로 소속될 수 있게 한다 — 모임 소속 게시글과 기존 전역(비소속) 게시글이 공존한다.
- post가 종목(SportCategory)으로 분류될 수 있게 한다 — community의 기존
SportCategoryVO를 재사용하고, 신규 종목 enum을 정의하지 않는다. - community의 기존 가시성·멤버십 규칙(
CommunityVisibility,MembershipStatus,CommunityDomainService.requireActiveMember)을 그대로 재사용해 모임 소속 게시글의 열람·작성 인가를 구현한다 — 새 인가 모델을 설계하지 않는다. - 문서(
docs/domain-context-map.md)와 아키텍처 검증 상수(DomainClassification.core)를 실제 코드 상태와 정합시킨다.
Non-Goals
- 실제 인원 모집·신청·수수료(10%) —
recruitment소관 별도 과제, 이 PRD 범위 아님. - 소모임 시설 예약(booking) 연동 — 범위 아님.
community본체 enum(CommunityRole/CommunityVisibility/MembershipStatus) 변경 — 근거 없이 변경하지 않는다.SportCategory는 재사용만 하고 값 추가·의미 변경을 하지 않는다.- 상품(goods)/주문/티켓(ticketing) 도메인 — 범위 아님.
- 모임 게시글에 대한 신고·좋아요·북마크 등 부가 인터랙션 — 이 PRD 범위 아님(후속 과제).
- 모임 탈퇴·강퇴 시 과거 작성 게시글의 삭제·이관 — 범위 아님. 게시글은 유지되고 열람 인가만 현재 시점 멤버십 상태로 재판정한다(Open Questions 참고).
User Scenarios
| # | 페르소나 | 시나리오 | 유형 |
|---|---|---|---|
| 1 | PUBLIC 모임 멤버 | 가입한 PUBLIC 모임 안에서 게시글을 작성하면, 같은 모임 멤버뿐 아니라 비멤버도 목록·상세를 열람할 수 있다 | 해피 패스 |
| 2 | PRIVATE 모임 ACTIVE 멤버 | 가입 승인된 PRIVATE 모임 안에서 게시글을 작성·열람·댓글 작성한다 | 해피 패스 |
| 3 | PRIVATE 모임 비멤버 | PRIVATE 모임 게시글 목록·상세·댓글에 접근을 시도하면 거부된다(403) | 예외 |
| 4 | 미가입 사용자 | 어떤 모임에도 속하지 않고 전역(비소속) 게시글을 작성·열람한다 — 기존 동작 그대로 | 해피 패스 |
| 5 | 관심 종목 탐색 사용자 | SportCategory=RUNNING으로 게시글을 필터링하면 모임 소속·비소속을 가리지 않고 러닝 관련 게시글만 조회된다 | 해피 패스 |
| 6 | 종목 미지정 게시글 작성자 | 전역 게시글 작성 시 종목을 지정하지 않으면, 종목 필터 없이 조회할 때만 노출되고 특정 종목 필터에는 걸리지 않는다 | 엣지 |
| 7 | PRIVATE 모임 HOST | 모임 소속 게시글을 NOTICE로 작성한다 | 해피 패스 |
| 8 | PRIVATE 모임 일반 멤버(MEMBER) | 모임 소속 게시글을 NOTICE로 작성 시도하면 거부된다 | 예외 |
| 9 | 전역 게시글 작성자 | 모임에 속하지 않은 채로 NOTICE 게시글을 작성한다 — 기존처럼 제한 없이 허용(하위 호환) | 예외 경계 확인 |
| 10 | PENDING_APPROVAL 상태 가입 신청자 | 아직 승인되지 않은 PRIVATE 모임의 게시글에 접근을 시도하면 비멤버와 동일하게 거부된다 | 예외 |
| 11 | 빈 상태 조회자 | 특정 종목·특정 모임에 게시글이 0건이면 빈 목록을 정상 응답으로 받는다(에러 아님) | 엣지 |
Benchmarking
| 제품명 | 카테고리 | 참조 패턴 | URL |
|---|---|---|---|
| Strava Clubs | 피트니스 SNS | 클럽 생성 시 종목(sport type) 1개 필수 지정 → 클럽 피드가 종목 기준 필터링. 게시글은 Club Announcements(운영자만 작성)/Member Posts(멤버 누구나 작성) 2종으로 작성 권한이 게시글 성격에 따라 분리 | https://support.strava.com/hc/en-us/articles/18288273144973-Club-Posts |
| Band(밴드) | 소모임 SNS | 밴드(모임) 공개/비공개 설정 + 게시판 내 공지사항 탭을 일반글과 별도 노출, 공지 작성은 운영자 중심 | https://namu.wiki/w/%EB%B0%B4%EB%93%9C(SNS) |
| 문토(Munto) | 관심사 기반 커뮤니티 | 지속 소속 단위 ‘클럽’(승인 기반 멤버십)과 비소속으로도 이용 가능한 ‘라운지’(전역 게시판)를 이원화 — 모임 소속 여부와 무관하게 게시글 작성이 가능한 구조 | https://www.munto.kr/ |
Functional Requirements
| ID | 요구사항 | 우선순위 |
|---|---|---|
| FR-1 | 게시글은 특정 community에 선택적으로 소속될 수 있다(communityId 미지정 시 기존과 동일한 전역 게시글). 소속 시 어느 모임의 게시글인지 목록·상세 응답에 식별 가능해야 한다. | P0 |
| FR-2 | 모임 소속 게시글의 열람(목록·상세·댓글) 인가는 소속 모임의 CommunityVisibility를 따른다 — PUBLIC 모임 게시글은 비멤버도 열람 가능, PRIVATE 모임 게시글은 ACTIVE 멤버만 열람 가능(비멤버·PENDING_APPROVAL은 거부). | P0 |
| FR-3 | 모임 소속 게시글의 작성(게시글·댓글)은 해당 모임의 ACTIVE 멤버(HOST 포함)만 가능하다 — 비멤버는 거부된다. | P0 |
| FR-4 | community에 소속되지 않은 게시글(communityId 미지정)은 인가 검사 없이 기존과 동일하게 전체 공개로 동작한다(하위 호환). | P0 |
| FR-5 | 게시글은 종목(SportCategory)으로 선택적으로 분류될 수 있다. 신규 종목 enum을 정의하지 않고 community의 기존 SportCategory VO를 재사용한다. 모임 소속 게시글은 작성 시점에 소속 모임의 sportCategory를 자동 상속한다(작성자가 별도로 지정하지 않는다). | P1 |
| FR-6 | 게시글 목록·검색 조회에 종목(SportCategory) 필터를 추가한다. 필터를 지정하지 않으면 종목 미지정 게시글을 포함한 전체가 조회되고, 특정 종목으로 필터링하면 그 종목으로 분류된 게시글만(모임 소속·비소속 무관) 조회된다. | P1 |
| FR-7 | PostType=NOTICE인 게시글은 모임 소속일 경우 해당 모임의 HOST만 작성할 수 있다. 모임 비소속(전역) NOTICE 게시글은 기존 동작(작성 제한 없음)을 그대로 유지한다. FREE/QUESTION/REVIEW는 모임 소속 여부와 무관하게 작성 권한 제한이 없다. | P1 |
| FR-8 | docs/domain-context-map.md의 community 컨텍스트 설명을 실제 완성 상태(Entity·DomainService·UseCase 10개·Controller·EventWorker 완비)로 갱신하고, SupportToCoreDependencyRulesTest.kt#DomainClassification.core 목록에 community를 등록해 코어 간 의존 규칙(R3) 검증 대상에 포함시킨다. | P2 |
Non-Functional Requirements
- 모임 소속 여부·종목 필터가 추가된 게시글 목록 조회 API는 기존
SearchPostsUseCase응답 시간 특성을 유지한다 — 신규 필터 추가로 인한 조회 지연은 P95 500ms 이내(로컬 개발 환경 기준, 기존 게시판 조회와 동일 목표선). - 페이지 크기 상한은 기존 정책(
PostCriteria.MAX_PAGE_SIZE = 100)을 그대로 유지한다. - PRIVATE 모임 게시글에 대한 비인가 접근은 403(Forbidden)으로 응답한다 — 기존
CommunityDomainService.requireActiveMember인가 실패 시 응답 규약과 동일하게 맞춘다. community_id컬럼은 FK 제약 없이 일반 컬럼으로 추가한다(정합성은 애플리케이션 레벨) —private-db-schema-convention의 FK 컬럼 금지 규칙을 따른다.- 신규 컬럼(
community_id,sport_category)은 nullable로 단일 마이그레이션 추가하고 기존 행은 NULL로 유지한다(백필 없음) — 무중단 배포 전제(private-db-schema-convention“컬럼 추가(nullable)” 케이스).
Operations
- 모임 소속 게시글 작성·PRIVATE 모임 접근 거부(403) 발생 건수를 로그 또는 카운터로 관측한다 — 인가 로직 배포 직후 예상보다 거부율이 급증하면 멤버십 상태 조회 로직 결함 신호로 본다.
- 신규 필터(종목·모임 소속) 포함 게시글 조회 API의 응답 시간을 배포 전후로 비교해 회귀 여부를 확인한다.
- FR-8 반영 후
SupportToCoreDependencyRulesTest가 community 패키지를 대상으로도 통과하는지 CI에서 확인한다.
Success Metrics
측정 항목만 확정합니다(목표 수치는 런칭 후 베이스라인 확보 뒤 별도 결정).
- 전체 게시글 대비 모임 소속 게시글(
communityIdnon-null) 비율 — 측정: DB 집계 쿼리 - 전체 게시글 대비 종목 지정 게시글(
sportCategorynon-null) 비율 — 측정: DB 집계 쿼리 - 종목 필터를 포함한 게시글 조회 API 호출 비율 — 측정: API 호출 로그 집계
- PRIVATE 모임 게시글 비인가 접근 시도(403) 건수 대비 전체 모임 게시글 접근 요청 건수 — 측정: API 응답 로그 집계
- 모임 가입 후 D7 이내 해당 모임에 첫 게시글을 작성한 사용자 비율 — 측정: 가입 이벤트·게시글 작성 이벤트 타임스탬프 대조
Milestones
해당 없음 — 단일 범위로 P0(FR-1~FR-4)부터 P2(FR-8)까지 한 번에 진행합니다. 규모가 티켓 분해 단계에서 커지면 P0(모임 소속·인가) → P1(종목 분류·필터·NOTICE 권한) → P2(문서 정합) 순서로 wave를 나눌 수 있습니다(TPM 판단 영역).
Open Questions
- 모임 탈퇴·강퇴 이력이 있는 사용자의 과거 작성 게시글 열람 인가 기준 — 이 PRD의 기본값은 “게시글은 유지되고, 열람 인가는 조회 시점의 현재 멤버십 상태로 판정한다”(작성자 본인도 탈퇴 후 PRIVATE 모임 게시글을 재열람할 수 없음)입니다. 다른 정책(예: 작성자 본인은 항상 열람 가능)을 원하면 알려주세요.
- 댓글에도 게시글과 동일한 열람·작성 인가(FR-2/FR-3)를 적용하는 것으로 전제했습니다 — 댓글만 별도 완화된 규칙이 필요하면 알려주세요.
- 종목 필터와 모임 소속 필터를 동시에 지정했을 때의 AND 조합 여부(예: 특정 모임 + 특정 종목 동시 필터) — 이 PRD는 두 필터가 독립적으로 AND 결합된다고 전제합니다.
Document History
| 날짜 | 변경 내용 |
|---|---|
| 2026-07-06 | 최초 작성 — post-community 연동(모임 소속 게시글, 종목별 분류) FR-1~FR-8 확정. 이전 stale 초안(20260706-모임커뮤니티컨텍스트구축-prd.md)은 폐기 대상이며 참조하지 않음 |