# PRD: 크리에이터 채널 커뮤니티 게시물 상세 / 댓글 / 답글 ## 1. Overview 크리에이터 채널 `커뮤니티` 탭에서 게시글 item을 터치하면 게시물 상세 화면으로 진입하고, 게시글 본문과 좋아요, 댓글 목록, 댓글의 답글 목록을 조회/작성/수정/삭제할 수 있게 한다. --- ## 2. Problem - 기존 크리에이터 채널 `커뮤니티` 탭은 게시글 목록만 표시하고 item 터치 시 별도 동작이 없어 게시글 상세로 진입할 수 없다. - 사용자는 게시글 본문, 이미지/오디오, 좋아요 수, 댓글 수, 댓글과 최신 답글을 한 화면에서 확인하고 싶어 한다. - 사용자는 게시글에 좋아요를 누르고, 댓글과 답글을 작성/수정/삭제하고 싶어 한다. - 댓글 작성이 불가능한 게시글에서는 댓글 영역과 입력 영역이 노출되면 안 된다. - 조회용 신규 v2 API 계약과 Figma 기반 UI 요구사항이 별도 문서로 정의되어야 한다. --- ## 3. Goals - 크리에이터 채널 `커뮤니티` 탭 게시글 item 터치 시 게시물 상세 화면으로 진입하는 신규 진입점을 정의한다. - Figma 댓글 가능 + 댓글 있음 `290:9243` 기준으로 게시물 상세 UI 요구사항을 정의한다. - Figma 댓글 불가능 `290:9266` 기준으로 댓글 불가 게시물 상세 UI 요구사항을 정의한다. - Figma 답글 없음 `669:40462`, 답글 있음 `669:40468` 기준으로 댓글 답글 목록 화면 UI 요구사항을 정의한다. - 조회는 신규 v2 endpoint를 사용한다. - 상세: `GET /api/v2/creator-channels/community-posts/{postId}` - 댓글: `GET /api/v2/creator-channels/community-posts/{postId}/comments` - 답글: `GET /api/v2/creator-channels/community-comments/{commentId}/replies` - 상세 응답의 `comments` 필드는 댓글 첫 페이지(`CreatorChannelCommunityCommentsResponse`)를 포함하며, 구현은 서버 계약 필드명을 따른다. - 상세: `postId`, `creatorId`, `creatorNickname`, `creatorProfileUrl`, `createdAtUtc`, `content`, `imageUrl`, `audioUrl`, `price`, `isCommentAvailable`, `existOrdered`, `likeCount`, `commentCount`, `isPinned`, `isLiked`, `comments` - 댓글 페이지: `commentCount`, `comments`, `page`, `size`, `hasNext` - 댓글: `commentId`, `writerId`, `writerProfileImageUrl`, `writerNickname`, `content`, `isSecret`, `createdAtUtc`, `latestReply` - 최신 답글: `commentId`, `writerId`, `writerProfileImageUrl`, `writerNickname`, `content`, `createdAtUtc` - 댓글/답글 조회 query parameter 기본값은 `page=0`, `size=20`으로 둔다. - 댓글 쓰기, 답글 쓰기, 댓글 수정, 댓글 삭제, 좋아요는 기존 `CreatorCommunityRepository`(`/creator-community/*`) API를 그대로 재사용한다. - 댓글 팝업 메뉴는 기존 커뮤니티 댓글과 동일한 팝업 메뉴(`content_comment_option_menu`, `content_comment_option_menu2`)를 사용하되, 메뉴 문구는 `수정하기`, `삭제하기`로 표시한다. - 하트 터치 시 좋아요 API를 호출하고, `isLiked`에 따라 `ic_feed_community_heart_fill`/`ic_feed_community_heart` icon을 표시한다. - 댓글 작성이 불가능한 게시글(`isCommentAvailable == false`)이면 댓글 목록과 하단 입력 영역을 숨긴다. - 하단 댓글/답글 입력 영역은 화면 하단에 고정하고 키보드 표시 여부에 따라 함께 올라오게 한다. --- ## 4. Non-Goals - 게시글 작성/수정 화면 및 API는 이번 범위에서 구현하지 않는다(기존 화면 유지). - 유료 게시글 구매(paywall unlock) 흐름은 이번 범위에서 새로 정의하지 않는다. 상세에서는 `price`, `existOrdered` 기반 표시만 다룬다. - 팬Talk 상세 화면 자체는 이번 범위에서 구현하지 않는다(답글 화면과 UI만 동일). - 서버 API schema나 endpoint를 새로 정의하지 않는다. - 레거시 커뮤니티/댓글 관련 파일을 직접 수정하지 않는다. - 크리에이터 채널의 다른 탭 UI나 공통 스크롤 구조를 재설계하지 않는다. - v2 패키지 내부 popup dialog는 `kr.co.vividnext.sodalive.v2.components.modal.V2ModalDialog`를 사용한다. --- ## 5. Target Users - 크리에이터 채널 커뮤니티 게시글을 상세히 보고 댓글로 소통하려는 로그인 사용자. - 자신의 채널 게시글/댓글을 관리(수정/삭제)하려는 크리에이터. - `kr.co.vividnext.sodalive.v2` 하위 크리에이터 채널 기능을 구현/유지보수하는 Android 개발자. --- ## 6. User Stories - 사용자는 커뮤니티 탭에서 게시글을 터치해 상세 화면으로 이동하고 싶다. - 사용자는 게시글 상세에서 본문, 이미지/오디오, 좋아요 수, 댓글 수를 확인하고 싶다. - 사용자는 하트를 눌러 게시글에 좋아요를 남기거나 취소하고 싶다. - 사용자는 댓글을 작성하고, 각 댓글의 최신 답글을 확인하고 싶다. - 사용자는 댓글을 터치해 답글 목록 화면으로 이동하고 답글을 작성하고 싶다. - 사용자는 내가 쓴 댓글/답글을 수정하거나 삭제하고 싶다. - 채널 크리에이터는 자신의 채널 댓글/답글을 삭제해 관리하고 싶다. - 사용자는 댓글이 불가능한 게시글에서는 입력창 없이 게시글만 보고 싶다. --- ## 7. Core Features ### F1. 커뮤니티 게시물 상세 진입 커뮤니티 탭 게시글 item 터치 시 상세 화면으로 이동한다. #### Requirements - 커뮤니티 탭 게시글 item(리스트형/썸네일형) 터치 시 게시물 상세 화면으로 이동한다. - 상세 화면에는 `postId`를 전달한다. - 상세 진입 시 `GET /api/v2/creator-channels/community-posts/{postId}`로 상세를 조회한다. - 로그인 토큰이 없으면 기존 크리에이터 채널 로그인 이동 정책을 따른다. #### Edge Cases - `postId <= 0`이면 상세 화면으로 이동하지 않는다. - 상세 조회 실패 시 기존 toast/error 표시 정책을 따르고 화면을 종료한다. ### F2. 게시물 상세 본문/좋아요 Figma `290:9243`, `290:9266` 기준으로 게시글 본문과 좋아요를 표시한다. #### Requirements - 상단 title-bar에 뒤로가기 버튼을 표시한다. - 게시글 header에 작성자 프로필 이미지(`creatorProfileUrl`), 닉네임(`creatorNickname`), 작성 시간(`createdAtUtc`)을 표시한다. - `createdAtUtc`는 크리에이터 채널 v2 공통 날짜/시간 포맷을 따른다. - 본문(`content`), 이미지(`imageUrl`), 오디오(`audioUrl`)를 표시한다. - 오디오 재생은 기존 `CreatorCommunityMediaPlayerManager`를 재사용한다. - 유료 게시글(`price > 0`)이고 미구매(`existOrdered == false`)이면 Figma paywall(잠금 + 가격) 표시를 따른다. - 유료 게시글을 구매한 경우(`existOrdered == true`) Figma 기준 `구매완료` badge를 표시한다. - 하트 터치 시 좋아요 API(`communityPostLike(postId)`)를 호출한다. - `isLiked == true`이면 `ic_feed_community_heart_fill`, `false`이면 `ic_feed_community_heart`를 표시한다. - 좋아요 수(`likeCount`)를 하트 옆에 표시한다. - 댓글 가능(`isCommentAvailable == true`)이면 댓글 수(`commentCount`)와 댓글 icon을 함께 표시한다. #### Edge Cases - `imageUrl`/`audioUrl`이 `null`이면 해당 영역을 표시하지 않는다. - 좋아요 API 실패 시 하트 상태와 좋아요 수를 원래 값으로 되돌린다. - 좋아요 중복 호출을 방지한다. ### F3. 댓글 목록 (댓글 가능 게시글) Figma `290:9243` 기준으로 댓글 목록을 표시한다. #### Requirements - `GET /api/v2/creator-channels/community-posts/{postId}/comments`로 댓글을 조회한다(기본 `page=0`, `size=20`). - 상세 조회 성공 후 댓글 endpoint의 첫 페이지(`page=0`, `size=20`)를 최초 댓글 목록으로 사용한다. - 각 댓글 item에 작성자 프로필 이미지, 닉네임, 본문, 작성 시간을 표시한다. - 각 댓글에 `latestReply`가 있으면 댓글 아래에 최신 답글 1개를 중첩 표시한다. - 댓글 또는 최신 답글 영역 터치 시 해당 댓글의 답글 목록 화면으로 이동한다. - 댓글 item 우측 더보기 버튼 터치 시 기존 커뮤니티 댓글 팝업 메뉴를 표시한다. - 내 댓글: `content_comment_option_menu`(수정하기/삭제하기) - 채널 크리에이터가 보는 타인 댓글: `content_comment_option_menu2`(삭제하기 기존 항목) - 일반 타인 댓글: 커뮤니티 댓글 전용 신고 API가 없어 더보기 버튼을 노출하지 않는다. - `hasNext == true`이면 현재 `page + 1` 페이지를 추가 로딩한다. - 상단에 총 댓글 수(`commentCount`)를 표시한다. #### Edge Cases - 댓글이 없으면 댓글 목록 영역을 비운 상태로 표시한다. - 추가 로딩 중 중복 요청을 방지한다. ### F4. 댓글 답글 목록 화면 (팬Talk 상세와 동일 UI) Figma `669:40462`, `669:40468` 기준으로 답글 목록 화면을 표시한다. #### Requirements - 답글 화면에는 `commentId`를 전달한다. - `GET /api/v2/creator-channels/community-comments/{commentId}/replies`로 답글을 조회한다(기본 `page=0`, `size=20`). - 상단 title-bar에 뒤로가기 버튼을 표시한다. - 상단에 부모 댓글(프로필/닉네임/시간/본문/더보기)을 표시한다. - 부모 댓글 아래에 답글 목록을 들여쓰기하여 표시한다. - 각 답글 item에 작성자 프로필 이미지, 닉네임, 본문, 작성 시간, 더보기 버튼을 표시한다. - 답글 item 더보기 버튼은 댓글과 동일한 팝업 메뉴 규칙(내 것: 수정/삭제, 채널 크리에이터가 보는 타인 답글: 삭제, 일반 타인 답글: 미노출)을 따른다. - `hasNext == true`이면 현재 `page + 1` 페이지를 추가 로딩한다. - 하단 입력 영역 placeholder는 `답글을 입력하세요`이다. #### Edge Cases - 답글이 없으면(Figma `669:40462`) 부모 댓글만 표시하고 답글 목록 영역은 비운다. - `commentId <= 0`이면 답글 화면으로 이동하지 않는다. ### F5. 댓글/답글 입력 영역 Figma 기준 하단 고정 입력 영역을 제공한다. #### Requirements - 입력값이 없을 때 placeholder를 표시한다. - 게시물 상세 댓글 입력: `댓글을 입력하세요` - 답글 화면 입력: `답글을 입력하세요` - 글자를 입력하면 전송(쓰기) 버튼을 활성화한다. - 3줄까지는 입력창 높이가 자동 확장된다. - 4줄 이상이면 3줄 높이를 유지하고 vertical scroll로 처리한다. - 입력 영역은 화면 하단에 고정되고 키보드가 올라오면 키보드 위로 함께 올라온다. - 수정 모드 진입 시 하단 입력창에 focus를 주고 키보드를 즉시 표시한다. - 전송 버튼 비활성 상태: `ic_new_arrow_up_gray` icon, 원형 배경, 배경색 `gray_900`. - 전송 버튼 활성 상태: `ic_new_arrow_up_white` icon, 원형 배경, 배경색 `soda_400`. - 게시물 상세에서 전송 시 댓글 쓰기 API(`registerComment(postId, comment)`)를 호출한다. - 답글 화면에서 전송 시 답글 쓰기 API(`registerComment(postId, comment, parentId = commentId)`)를 호출한다. - 작성 성공 시 입력값을 비우고 목록을 새로고침한다. - 작성 또는 수정 API 성공 시 키보드를 내린다. #### Edge Cases - 공백/줄바꿈만 입력한 경우 전송 버튼은 비활성 상태다. - 전송 중 중복 전송을 막는다. - 전송 실패 시 입력값을 유지하고 기존 toast/error 표시 정책을 따른다. ### F6. 댓글/답글 수정·삭제 기존 커뮤니티 댓글 수정/삭제 흐름을 재사용한다. #### Requirements - 팝업 메뉴 `수정하기` 선택 시 별도 입력 Dialog를 띄우지 않고 화면 하단 입력창을 수정 모드로 전환한다. - 수정 모드의 하단 입력창에는 기존 댓글/답글 내용을 채우고, 취소용 X 버튼을 표시한다. - 수정 모드에서 전송 버튼을 누르면 기존 수정 흐름(`modifyComment(commentId, comment = ...)`)을 따른다. - X 버튼을 누르면 수정 모드를 취소하고 입력창을 비운 뒤 일반 작성 모드로 돌아간다. - 팝업 메뉴 `삭제하기` 선택 시 v2 공통 모달(`V2ModalDialog`)로 삭제 확인 후 삭제 흐름(`modifyComment(commentId, isActive = false)`)을 따른다. - 수정/삭제 성공 시 현재 목록(댓글 목록 또는 답글 목록)을 새로고침한다. #### Edge Cases - 삭제 확인 dialog에서 취소 시 아무 동작도 하지 않는다. - 수정 시 변경 내용이 없으면 기존 정책대로 toast를 표시한다. ### F7. 댓글 불가 게시글 처리 Figma `290:9266` 기준으로 댓글 불가 상태를 처리한다. #### Requirements - `isCommentAvailable == false`이면 댓글 목록 영역을 숨긴다. - `isCommentAvailable == false`이면 하단 댓글 입력 영역을 숨긴다. - 댓글 불가 게시글에서도 하트(좋아요)는 표시한다. - 댓글 불가 게시글에서는 댓글 수/댓글 icon을 표시하지 않는다. #### Edge Cases - 댓글 불가 게시글에서는 댓글 관련 API(`comments` 조회, 댓글 쓰기)를 호출하지 않는다. --- ## 8. UX / UI Expectations - 게시글 item 터치부터 상세 진입까지 자연스럽게 이어진다. - 커뮤니티 상세 상단 게시글 영역은 목록 카드처럼 rounded 배경을 깔지 않고, 게시글과 댓글 영역 및 댓글 사이에는 Figma `290:9243` 기준 1dp border를 표시한다. - 하트 상태와 좋아요 수는 터치 즉시 반응한다(낙관적 업데이트 후 실패 시 롤백). - 입력 영역은 키보드 있음/없음 상태를 기준으로 자연스럽게 대응한다. - 답글 화면은 팬Talk 상세와 시각적으로 동일하게 보인다. - 전송 버튼 활성/비활성 색상과 icon은 입력값 변화에 즉시 반응한다. - 댓글 불가 게시글은 입력 영역/댓글 영역 없이 게시글 본문 중심으로 표시된다. --- ## 9. Technical Constraints - Android XML View/ViewBinding 기반으로 구현한다. - 신규 Activity/Fragment/ViewModel 및 하위 코드는 `kr.co.vividnext.sodalive.v2.creator.channel.community` 하위에 작성한다. - 조회용 신규 v2 endpoint는 v2 API/Repository 계약(`ApiResponse`, RxJava3, Koin)을 따른다. - 댓글 쓰기/답글 쓰기/수정/삭제/좋아요는 기존 `CreatorCommunityRepository`를 호출해 재사용한다(레거시 파일 직접 수정 금지). - 댓글 팝업 메뉴는 기존 `content_comment_option_menu`, `content_comment_option_menu2` 리소스를 재사용하고, 문구는 `수정하기`, `삭제하기`로 표시한다. - 커뮤니티 댓글/답글 신고는 현재 전용 신고 API/레거시 흐름이 없어 이번 구현 범위에서 제외하고, 기존 레거시 메뉴2의 실제 동작인 채널 크리에이터 삭제만 재사용한다. - 신규 문자열은 `values`, `values-en`, `values-ja`에 추가하거나 기존 문자열을 재사용한다. - 오디오 재생은 기존 `CreatorCommunityMediaPlayerManager`를 재사용한다. --- ## 10. Metrics - 별도 분석 이벤트 추가는 이번 범위에서 정의하지 않는다. - 기능 성공 기준은 게시글 상세 진입, 댓글/답글 조회, 좋아요/댓글/답글 작성·수정·삭제가 정상 동작하고 목록에 반영되는 것이다. - UI 완료 기준은 Figma `290:9243`, `290:9266`, `669:40462`, `669:40468`의 주요 layout 구조, 하트/전송 버튼 상태, 댓글 불가 처리, 입력 영역 동작이 구현 화면에 반영되었는지 확인되는 것이다. - 자동 검증 기준은 조회 API 계약(page/size 기본값, 응답 매핑), 하트 icon/전송 버튼 상태 계약, 댓글 불가 게시글의 댓글/입력 영역 숨김 계약을 source/resource/ViewModel 테스트로 확인하는 것이다. --- ## 11. Open Questions & Decisions - 결정(재사용 vs 복사): 답글 목록 화면 UI는 팬Talk 상세와 동일하지만 조회 API가 다르고, 현재 팬Talk 상세 화면은 v2에 미구현이다. 따라서 이번 범위에서는 **커뮤니티 전용 답글 화면으로 신규 구현하되, layout XML과 댓글/답글 item view(ViewHolder)만 데이터/콜백 주입형으로 설계해 재사용 가능하게 둔다.** ViewModel/Repository/데이터 모델/화면 컨트롤러는 커뮤니티 전용으로 분리한다. - 근거: 아직 팬Talk 상세라는 두 번째 사용처가 없어 지금 데이터 계층까지 공통 추상화하면 단일 사용처를 위한 추측성 추상화가 된다. UI 리소스/item view만 공용화하면 추후 팬Talk 상세 구현 시 동일 UI를 그대로 재사용할 수 있다. - 남은 확인: 없음.