290 lines
22 KiB
Markdown
290 lines
22 KiB
Markdown
# PRD: 커뮤니티 게시글 상세
|
|
|
|
## 1. Overview
|
|
크리에이터 채널 커뮤니티 게시글을 터치했을 때 진입하는 V2 커뮤니티 게시글 상세 화면을 제공한다. 화면은 게시글 본문, 이미지/오디오/유료 잠금 상태, 좋아요, 댓글 목록, 최신 답글, 하단 고정 댓글 입력 바를 표시한다.
|
|
|
|
상세 API는 `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`를 사용한다. `page` 기본값은 `0`, `size` 기본값은 `20`이다.
|
|
|
|
Figma 참조:
|
|
- 댓글 가능 상세: `290:9243`, `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=290-9243&m=dev`
|
|
- 댓글 불가능 상세: `290:9266`, `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=290-9266&m=dev`
|
|
|
|
## 2. Problem
|
|
- 현재 V2 커뮤니티 탭은 게시글 목록을 제공하지만, 게시글 상세 API와 Figma 기준 상세 화면이 연결되어 있지 않다.
|
|
- 기존 커뮤니티 댓글 화면은 V1 sheet 기반이고, 이번 상세 화면의 하단 고정 입력 바와 댓글/최신 답글 노출 구조와 다르다.
|
|
- 팬Talk/댓글 답글 상세 UI가 이미 V2에 구현되어 있으므로 같은 UI를 복사할지 재사용할지 결정이 필요하다.
|
|
- 신규 상세/댓글/답글 조회 API는 `page=0` 기준인 반면 기존 V1 커뮤니티 API 일부는 내부에서 `page - 1`을 사용하므로 API 계층을 분리해야 한다.
|
|
|
|
## 3. Goals
|
|
- 커뮤니티 목록 item tap 시 게시글 상세 화면으로 진입한다.
|
|
- 상세 진입 시 `GET /api/v2/creator-channels/community-posts/{postId}`를 호출한다.
|
|
- 상세 응답의 `comments`를 초기 댓글 목록으로 표시한다.
|
|
- 댓글 목록 추가 조회는 `GET /api/v2/creator-channels/community-posts/{postId}/comments?page={page}&size={size}`를 사용한다.
|
|
- 댓글의 답글 추가 조회는 `GET /api/v2/creator-channels/community-comments/{commentId}/replies?page={page}&size={size}`를 사용한다.
|
|
- 댓글 작성, 답글 작성, 댓글 수정, 댓글 삭제, 좋아요 API는 기존 커뮤니티 구현에서 사용하던 API를 그대로 사용한다.
|
|
- 댓글 popup menu는 기존 커뮤니티 댓글과 동일한 수정/삭제 흐름을 사용한다.
|
|
- 커뮤니티 댓글 신고는 [blocked] 상태로 구현 범위에서 제외한다. 현재 코드베이스에는 커뮤니티 댓글 신고용 `ReportRequest`/`ReportType` 식별자와 API가 없고, 기존 `CreatorCommunityCommentItemView`도 댓글 신고 UI를 노출하지 않는다.
|
|
- 댓글의 답글 상세 UI는 팬Talk 답글 상세와 동일하므로 `CreatorChannelReplyDetailView` 계열을 복사하지 않고 재사용/확장한다.
|
|
- `isCommentAvailable == false`이면 reaction bar의 댓글 icon/count, 댓글 목록, 하단 댓글 입력 바를 숨긴다.
|
|
- 하단 댓글 입력 바는 화면 하단에 고정하고 키보드 표시 시 키보드 위로 밀려 올라와야 한다.
|
|
- 댓글 입력창은 최대 3줄까지 자동 확장하고, 4줄 이상은 3줄 높이를 유지한 채 내부 vertical scroll로 처리한다.
|
|
- 좋아요 상태에 따라 `ic_feed_community_heart_fill` 또는 `ic_feed_community_heart`를 표시하고 tap 시 기존 좋아요 API를 호출한다.
|
|
|
|
## 4. Non-Goals
|
|
- 커뮤니티 게시글 작성/수정 화면을 변경하지 않는다.
|
|
- 댓글/답글 작성, 수정, 삭제, 좋아요 mutation API를 신규 V2 endpoint로 교체하지 않는다.
|
|
- 기존 V1 커뮤니티 댓글 화면 전체를 삭제하거나 일괄 리팩터링하지 않는다.
|
|
- 팬Talk 답글 상세 UI를 별도 파일로 동일 복사하지 않는다.
|
|
- Figma localhost asset URL을 앱 코드에 직접 사용하지 않는다.
|
|
- `Pods/**`, `generated/**`, `build/**`는 수정하지 않는다.
|
|
|
|
## 5. Target Users
|
|
- 크리에이터의 커뮤니티 게시글을 상세로 읽고 좋아요를 누르려는 사용자
|
|
- 커뮤니티 게시글에 댓글을 작성하려는 사용자
|
|
- 커뮤니티 댓글에 답글을 확인하거나 작성하려는 사용자
|
|
|
|
## 6. User Stories
|
|
- 사용자는 커뮤니티 목록에서 게시글을 터치해 상세 본문, 이미지, 좋아요 수, 댓글 수를 확인할 수 있다.
|
|
- 사용자는 댓글 입력창에 글자를 입력하면 전송 버튼이 활성화되는 것을 확인하고 댓글을 작성할 수 있다.
|
|
- 사용자는 댓글이 불가능한 게시글에서는 댓글 목록과 댓글 입력창이 보이지 않는 것을 확인할 수 있다.
|
|
- 사용자는 댓글에 최신 답글이 있으면 댓글 아래에서 답글 요약을 확인하고, 댓글을 터치해 답글 상세 화면으로 이동할 수 있다.
|
|
- 사용자는 게시글 하트를 터치해 좋아요 상태를 변경할 수 있다.
|
|
|
|
## 7. Core Requirements
|
|
|
|
### 7.1 API
|
|
신규 V2 조회 API는 `SodaLive/Sources/V2/CreatorChannel/Community/**` 하위 Repository/API에 추가한다. 기존 `CreatorCommunityApi`는 mutation 재사용 대상으로 유지하고, 신규 V2 조회 API에는 `page - 1` 보정을 적용하지 않는다.
|
|
|
|
상세:
|
|
- Method: `GET`
|
|
- Path: `/api/v2/creator-channels/community-posts/{postId}`
|
|
- Path parameter: `postId`
|
|
|
|
댓글:
|
|
- Method: `GET`
|
|
- Path: `/api/v2/creator-channels/community-posts/{postId}/comments`
|
|
- Path parameter: `postId`
|
|
- Query parameters: `page` 기본값 `0`, `size` 기본값 `20`
|
|
|
|
답글:
|
|
- Method: `GET`
|
|
- Path: `/api/v2/creator-channels/community-comments/{commentId}/replies`
|
|
- Path parameter: `commentId`
|
|
- Query parameters: `page` 기본값 `0`, `size` 기본값 `20`
|
|
|
|
응답 래퍼는 기존 V2 패턴대로 `ApiResponse<...>`로 디코딩한다. Kotlin `Long`은 기존 V2 관례대로 Swift `Int`로 선언한다.
|
|
|
|
```kotlin
|
|
data class CreatorChannelCommunityPostDetailResponse(
|
|
val postId: Long,
|
|
val creatorId: Long,
|
|
val creatorNickname: String,
|
|
val creatorProfileUrl: String,
|
|
val createdAtUtc: String,
|
|
val content: String,
|
|
val imageUrl: String?,
|
|
val audioUrl: String?,
|
|
val price: Int,
|
|
@JsonProperty("isCommentAvailable")
|
|
val isCommentAvailable: Boolean,
|
|
val existOrdered: Boolean,
|
|
val likeCount: Int,
|
|
val commentCount: Int,
|
|
@JsonProperty("isPinned")
|
|
val isPinned: Boolean,
|
|
@JsonProperty("isLiked")
|
|
val isLiked: Boolean,
|
|
val comments: CreatorChannelCommunityCommentsResponse
|
|
)
|
|
|
|
data class CreatorChannelCommunityCommentsResponse(
|
|
val commentCount: Int,
|
|
val comments: List<CreatorChannelCommunityCommentResponse>,
|
|
val page: Int,
|
|
val size: Int,
|
|
@JsonProperty("hasNext")
|
|
val hasNext: Boolean
|
|
)
|
|
|
|
data class CreatorChannelCommunityCommentResponse(
|
|
val commentId: Long,
|
|
val writerId: Long,
|
|
val writerProfileImageUrl: String,
|
|
val writerNickname: String,
|
|
val content: String,
|
|
val createdAtUtc: String,
|
|
val latestReply: CreatorChannelCommunityReplyResponse?
|
|
)
|
|
|
|
data class CreatorChannelCommunityReplyResponse(
|
|
val commentId: Long,
|
|
val writerId: Long,
|
|
val writerProfileImageUrl: String,
|
|
val writerNickname: String,
|
|
val content: String,
|
|
val createdAtUtc: String
|
|
)
|
|
|
|
data class CreatorChannelCommunityRepliesResponse(
|
|
val replyCount: Int,
|
|
val replies: List<CreatorChannelCommunityReplyResponse>,
|
|
val page: Int,
|
|
val size: Int,
|
|
@JsonProperty("hasNext")
|
|
val hasNext: Boolean
|
|
)
|
|
```
|
|
|
|
### 7.2 Entry and navigation
|
|
- `CreatorChannelCommunityTabView`의 리스트형/썸네일형 item tap에서 상세 화면으로 진입한다.
|
|
- 상세 route는 `AppStep`에 추가하고 `postId`와 필요한 refresh callback을 전달한다.
|
|
- 상세 화면에서 back tap 시 이전 화면으로 돌아간다.
|
|
- 상세에서 좋아요/댓글 작성/댓글 삭제 등으로 목록 갱신이 필요한 경우, 상세 종료 또는 mutation 성공 시 커뮤니티 탭 첫 페이지 갱신 callback을 호출한다.
|
|
|
|
### 7.3 Screen layout
|
|
- 배경은 `Color.black`을 사용한다.
|
|
- 상단 title bar는 Figma처럼 title text 없이 back chevron만 표시한다.
|
|
- 게시글 영역은 작성자 프로필, 닉네임, 상대 시간, 본문, 이미지/오디오/잠금 영역, 좋아요/댓글 count를 표시한다.
|
|
- `createdAtUtc`는 기존 `DateParser.relativeTimeText(fromUTC:fallback:now:)` 계열 helper로 상대 시간으로 표시한다.
|
|
- `price > 0 && existOrdered == false && isOwnPost == false`이면 유료 미구매 잠금 상태로 표시한다.
|
|
- 유료 미구매 잠금 상태는 Figma처럼 `gray800` 계열 이미지 영역, 잠금 아이콘, 캐시 가격 capsule을 표시한다.
|
|
- 구매 완료 상태는 Figma `290:9266`처럼 `구매완료` capsule tag를 표시한다.
|
|
- 이미지가 있고 접근 가능한 게시글이면 이미지 또는 GIF를 표시한다.
|
|
- `audioUrl`이 있으면 기존 커뮤니티 오디오 재생 흐름을 재사용해 이미지 중앙에 재생 버튼을 표시한다.
|
|
- `isPinned == true`이면 기존 커뮤니티 탭의 pinned 표시 규칙을 따른다.
|
|
|
|
### 7.4 Reaction
|
|
- `isLiked == true`이면 `ic_feed_community_heart_fill`을 표시한다.
|
|
- `isLiked == false`이면 `ic_feed_community_heart`를 표시한다.
|
|
- 하트 tap 시 기존 `CreatorCommunityRepository.communityPostLike(postId:)`를 호출한다.
|
|
- 좋아요 tap 직후 UI는 기존 `CreatorChannelCommunityListItem`처럼 local optimistic state로 반영하고, API 실패 시 toast를 표시한 뒤 tap 직전의 `isLiked`, `likeCount` 값으로 local state를 복구한다.
|
|
- `isCommentAvailable == true`이면 댓글 icon과 `commentCount`를 표시한다.
|
|
- `isCommentAvailable == false`이면 댓글 icon/count, 댓글 목록, 하단 입력 바를 모두 숨긴다.
|
|
|
|
### 7.5 Comments
|
|
- 상세 API 응답의 `comments.comments`를 초기 댓글 목록으로 표시한다.
|
|
- 댓글 section header는 Figma처럼 `댓글 {commentCount}` 형식으로 표시한다.
|
|
- 댓글 row는 작성자 프로필, 닉네임, 상대 시간, 본문, 우측 더보기 버튼을 표시한다.
|
|
- `writerId`로 내 댓글/답글 여부를 판정하고, 게시글의 `creatorId`로 현재 사용자가 해당 커뮤니티 게시글을 쓴 크리에이터인지 판정한다.
|
|
- 댓글/답글 popup menu는 기존 커뮤니티 댓글과 동일하게 내 댓글/답글이면 `수정하기`, `삭제하기`를 표시하고, 해당 게시글을 쓴 크리에이터이면 내가 쓴 댓글/답글이 아니어도 `삭제하기`를 표시한다.
|
|
- 커뮤니티 댓글 신고는 [blocked] 상태로 구현하지 않는다. 현재 코드베이스에는 커뮤니티 댓글 신고용 `ReportRequest`/`ReportType` 식별자와 API가 없고, 기존 `CreatorCommunityCommentItemView`도 댓글 신고 UI를 노출하지 않는다.
|
|
- `latestReply != nil`이면 댓글 아래에 최신 답글 카드와 좌측 연결선을 표시한다.
|
|
- 댓글 목록 하단 도달 시 `hasNext == true`이면 다음 page를 append한다.
|
|
- 첫 페이지 재조회 시 기존 댓글 목록을 교체한다.
|
|
- 댓글을 터치하면 답글 상세 화면으로 진입한다.
|
|
|
|
### 7.6 Reply detail reuse decision
|
|
- 댓글의 답글 상세 UI는 팬Talk 상세와 동일한 UI를 가진다.
|
|
- 별도 동일 복사는 하지 않는다.
|
|
- 기존 `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift`, `CreatorChannelReplyDetailFeedView.swift`, `CreatorChannelReplyDetailInputBar.swift`를 재사용한다.
|
|
- 신규 응답 모델이 기존 `GetCommunityPostCommentListItem`과 필드가 다르므로, 구현 시 `CreatorChannelReplyDetailDisplayItem` 생성용 adapter 또는 context 확장을 추가한다.
|
|
- 답글 목록 추가 조회는 신규 `GET /api/v2/creator-channels/community-comments/{commentId}/replies`를 우선 사용한다.
|
|
- 답글 작성/수정/삭제 mutation은 사용자 요구대로 기존 커뮤니티 댓글 API를 재사용한다.
|
|
|
|
### 7.7 Comment input bar
|
|
- `isCommentAvailable == true`일 때만 하단 고정 댓글 입력 바를 표시한다.
|
|
- placeholder는 사용자 요구사항 기준 `댓글을 입력하세요`를 표시한다.
|
|
- Figma에는 `댓글을 입력하세요.`처럼 마침표가 보이나, 구현 기준은 사용자 요구 문구를 우선한다.
|
|
- 댓글 쓰기 UI에는 기존 커뮤니티 댓글과 동일한 비밀댓글 toggle을 추가한다.
|
|
- 비밀댓글 toggle은 기존 커뮤니티 댓글 sheet의 `isShowSecret` 노출 정책을 따른다.
|
|
- 비밀댓글 toggle이 노출되지 않는 경우 `isSecret == false`로 댓글 작성 API를 호출한다.
|
|
- 입력값이 없거나 공백/줄바꿈만 있으면 전송 버튼을 비활성화한다.
|
|
- 입력값이 있으면 전송 버튼을 활성화한다.
|
|
- 입력창은 1줄에서 시작하고 3줄까지 자동 확장한다.
|
|
- 4줄 이상 입력 시 3줄 높이를 유지하고 입력창 내부에서 vertical scroll 처리한다.
|
|
- 하단 입력 바는 키보드가 표시되면 키보드 위로 올라와야 한다.
|
|
- 전송 중에는 중복 tap으로 같은 댓글이 여러 번 등록되지 않도록 한다.
|
|
- 댓글 작성 성공 후 입력값을 비우고 댓글 첫 페이지 또는 상세 데이터를 재조회한다.
|
|
|
|
전송 버튼 상태:
|
|
- 비활성화: icon `ic_arrow_up_gray`, 원형 배경, `gray900`
|
|
- 활성화: icon `ic_arrow_up_white`, 원형 배경, `soda400`
|
|
|
|
### 7.8 Comment popup menu and mutation reuse
|
|
- 댓글/답글 popup menu는 기존 커뮤니티 댓글과 동일한 메뉴 정책을 따른다.
|
|
- 기존 메뉴 정책은 `CreatorCommunityCommentItemView`와 동일하게 수정은 작성자에게만 허용하고, 삭제는 작성자 또는 게시글 크리에이터에게 허용한다.
|
|
- 커뮤니티 댓글 신고는 [blocked] 상태로 구현하지 않는다. `ReportRequest`/`ReportType`에 커뮤니티 댓글 신고 식별자가 추가되기 전까지 작성자도 게시글 크리에이터도 아닌 사용자에게도 `신고`를 제공하지 않는다.
|
|
- 댓글 작성은 기존 `CreatorCommunityRepository.createCommunityPostComment(comment:postId:parentId:isSecret:)`를 사용하고, 원댓글 작성 시 `parentId == nil`, `isSecret == 비밀댓글 toggle 값`으로 호출한다.
|
|
- 답글 작성은 같은 API에 `parentId == commentId`를 전달한다.
|
|
- 댓글/답글 수정과 삭제는 기존 `CreatorCommunityRepository.modifyComment(request:)`를 사용한다.
|
|
- 좋아요는 기존 `CreatorCommunityRepository.communityPostLike(postId:)`를 사용한다.
|
|
- 댓글 신고가 필요한 경우 `ReportRequest`/`ReportType`에 커뮤니티 댓글 신고 식별자가 추가된 뒤 별도 범위에서 연결한다.
|
|
|
|
### 7.9 Pagination and state
|
|
- 상세 첫 진입은 상세 API 1회로 게시글과 초기 댓글을 함께 구성한다.
|
|
- 댓글 추가 조회는 `comments.page + 1` 기준으로 호출한다.
|
|
- 답글 상세 추가 조회는 `replies.page + 1` 기준으로 호출한다.
|
|
- 조회 중 중복 호출을 막는다.
|
|
- `hasNext == false`이면 추가 조회하지 않는다.
|
|
- pull-to-refresh가 필요하면 상세 API를 다시 호출해 게시글과 댓글 첫 페이지를 동기화한다.
|
|
|
|
## 8. Reusable V2 Candidates
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift`
|
|
- 게시글 header, content, 유료 잠금 overlay, 오디오 재생, 좋아요/댓글 reaction 규칙을 상세 게시글 영역 구현 후보로 검토한다.
|
|
- 목록 카드 배경/radius는 상세 화면과 다르므로 전체 View 복사보다 내부 규칙을 추출하거나 참고하는 방향이 적합하다.
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityGridItem.swift`
|
|
- 유료 잠금 가격 overlay와 pinned 표시 규칙 참고 후보이다.
|
|
- `SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift`
|
|
- 홈/추천 카드의 좋아요 optimistic state, 잠금 overlay, 오디오 재생 흐름 참고 후보이다.
|
|
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift`
|
|
- 댓글의 답글 상세 화면 재사용 대상이다.
|
|
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailFeedView.swift`
|
|
- 원댓글/답글 카드/좌측 연결선/더보기 popup 위치 계산을 재사용한다.
|
|
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailInputBar.swift`
|
|
- 답글 입력 바의 send 상태와 하단 고정 구조를 참고하되, 댓글 상세 입력 바는 3줄 자동 확장 요구가 있어 별도 확장 또는 공용화가 필요하다.
|
|
- `SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift`
|
|
- 댓글 row + latest reply 카드 + 좌측 연결선 구조가 Figma 댓글 row와 유사하다.
|
|
- `SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkActionPopup.swift`
|
|
- `CreatorChannelActionPopup`이 수정/삭제 popup 공용 기반으로 이미 사용 중이다.
|
|
- `SodaLive/Sources/V2/Component/Modal/SodaV2ActionModal.swift`
|
|
- 댓글/답글 삭제 확인 dialog 후보이다.
|
|
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailTitleBar.swift`
|
|
- back-only title bar 재사용 후보이다.
|
|
|
|
## 9. Success Criteria
|
|
- 커뮤니티 게시글 item tap 시 상세 화면으로 진입한다.
|
|
- 상세 진입 시 `GET /api/v2/creator-channels/community-posts/{postId}`가 호출된다.
|
|
- 상세 API 응답으로 게시글 본문, 이미지/오디오/잠금 상태, 좋아요 수, 댓글 수, 초기 댓글 목록이 표시된다.
|
|
- 댓글 추가 로딩 시 `GET /api/v2/creator-channels/community-posts/{postId}/comments?page={page}&size=20`가 호출된다.
|
|
- 댓글의 답글 상세 추가 로딩 시 `GET /api/v2/creator-channels/community-comments/{commentId}/replies?page={page}&size=20`가 호출된다.
|
|
- `isCommentAvailable == false`이면 reaction bar의 댓글 icon/count, 댓글 section, 하단 댓글 입력 바가 표시되지 않는다.
|
|
- 댓글 쓰기 UI에는 기존 비밀댓글 toggle이 표시 조건에 맞게 제공된다.
|
|
- 입력값이 없으면 댓글 전송 버튼은 `gray900` 배경과 `ic_arrow_up_gray` icon으로 비활성화된다.
|
|
- 입력값이 있으면 댓글 전송 버튼은 `soda400` 배경과 `ic_arrow_up_white` icon으로 활성화된다.
|
|
- 댓글 입력창은 3줄까지 높이가 늘어나고, 4줄 이상은 3줄 높이에서 내부 스크롤된다.
|
|
- 키보드가 올라오면 하단 댓글 입력 바가 키보드 위로 올라온다.
|
|
- 댓글 작성 성공 후 입력값이 비워지고 댓글 목록이 갱신된다.
|
|
- 하트 tap 시 기존 좋아요 API가 호출되고 `isLiked` 상태에 맞는 heart icon이 표시된다.
|
|
- 댓글 popup menu는 기존 커뮤니티 댓글과 동일한 수정/삭제 흐름을 사용한다.
|
|
- 게시글을 쓴 크리에이터는 내가 작성하지 않은 댓글/답글에도 `삭제하기`를 사용할 수 있다.
|
|
- 커뮤니티 댓글 신고는 [blocked] 상태이며, 현재 코드베이스에 커뮤니티 댓글 신고용 `ReportRequest`/`ReportType` 식별자와 API가 없고 기존 `CreatorCommunityCommentItemView`도 신고를 노출하지 않으므로 이번 구현의 성공 기준에서 제외한다.
|
|
- 댓글의 답글 상세 UI는 팬Talk 상세와 동일한 기존 `CreatorChannelReplyDetailView` 계열을 재사용한다.
|
|
|
|
## 10. Technical Constraints
|
|
- 기능 변경은 `SodaLive/Sources/V2/**` 하위에서 우선 해결한다.
|
|
- 커뮤니티 게시글 상세 신규 View, ViewModel, 모델, 조회 Repository/API는 `SodaLive/Sources/V2/CreatorChannel/Community/**` 하위에 둔다.
|
|
- 댓글/답글 mutation은 기존 `SodaLive/Sources/Explorer/Profile/CreatorCommunity/**` repository를 호출할 수 있다.
|
|
- 신규 공용 컴포넌트가 필요하면 `SodaLive/Sources/V2/Component/**` 아래에 둔다.
|
|
- 특정 상세 화면에서만 쓰는 컴포넌트는 `SodaLive/Sources/V2/CreatorChannel/Community/Detail/Components/**` 아래에 둔다.
|
|
- 신규 문구가 필요하면 `SodaLive/Sources/I18n/I18n.swift`에 ko/en/ja를 추가한다.
|
|
- 프로젝트 설정 변경은 신규 Swift 파일 target 등록이 필요한 경우에만 수행한다.
|
|
|
|
## 11. Assumptions
|
|
- 상세 API의 `postId`는 기존 좋아요/댓글 작성 mutation API가 요구하는 post id와 동일하다.
|
|
- 신규 답글 API의 `commentId`는 기존 `modifyComment`와 `createCommunityPostComment(parentId:)`에서 사용하는 comment id와 동일하다.
|
|
- `existOrdered == true`이면 유료 게시글의 구매 완료 또는 접근 가능 상태로 본다.
|
|
- 본인 게시글 판정은 기존 관례대로 `creatorId == UserDefaults.int(forKey: .userId)`를 우선 사용한다.
|
|
- 댓글 원문과 최신 답글은 서버 응답 문자열을 그대로 표시한다.
|
|
|
|
## 12. Open Questions
|
|
- 해당 없음
|
|
|
|
## 13. Verification Notes
|
|
- 2026-07-07: Figma `get_design_context`와 `get_screenshot`으로 `290:9243`, `290:9266`을 확인했다.
|
|
- 2026-07-07: `docs/agent-guides/documentation-policy.md`와 `docs/prd/sample-prd.md`를 확인해 신규 PRD 경로와 필수 섹션을 맞췄다.
|
|
- 2026-07-07: 기존 문서 `docs/20260705_크리에이터_채널_커뮤니티_탭/prd.md`, `docs/20260704_크리에이터_채널_팬Talk_탭/prd.md`, `docs/20260707_글_상세_답글_쓰기/prd.md`를 확인했다.
|
|
- 2026-07-07: 기존 V2 재사용 후보로 `CreatorChannelCommunityListItem`, `CreatorChannelCommunityGridItem`, `CommunityPostCard`, `CreatorChannelReplyDetailView`, `CreatorChannelReplyDetailFeedView`, `CreatorChannelReplyDetailInputBar`, `CreatorChannelFanTalkListItem`, `CreatorChannelActionPopup`, `SodaV2ActionModal`, `CreatorChannelReplyDetailTitleBar`를 확인했다.
|
|
- 2026-07-07: 기존 mutation 재사용 후보로 `CreatorCommunityRepository.communityPostLike`, `createCommunityPostComment`, `modifyComment`, `getCommunityPostDetail`, `getCommunityPostCommentList`, `getCommentReplyList`를 확인했다. 신규 V2 조회 API는 path/page 기준이 달라 V2 API에 별도 추가가 필요하다.
|
|
- 2026-07-07: 사용자 확인 사항을 반영해 댓글/답글 응답에 `writerId`를 추가하고, 댓글 쓰기 UI의 기존 비밀댓글 toggle 유지, 전송 버튼 icon의 `ic_arrow_up_gray`/`ic_arrow_up_white` 매핑, 댓글 불가능 게시글의 댓글 icon/count 숨김 정책을 확정했다.
|
|
- 2026-07-07: 기존 커뮤니티 댓글과 동일하게 수정은 작성자에게만, 삭제는 작성자 또는 게시글 크리에이터에게 제공하는 권한 규칙을 반영했다. 커뮤니티 댓글 신고는 기존 `ReportRequest`/`ReportType`에 커뮤니티 댓글 신고 식별자가 없고 기존 `CreatorCommunityCommentItemView`도 신고를 노출하지 않아 [blocked]로 정정했다.
|