13 KiB
13 KiB
PRD: 크리에이터 채널 팬Talk 탭
1. Overview
크리에이터 채널 공통 shell의 팬Talk 탭에서 팬이 남긴 응원글 목록과 크리에이터 답글을 제공한다. 상단 title bar, header, sticky tab-bar는 기존 크리에이터 채널 홈/라이브/오디오/시리즈/후원 구현을 재사용하고, tab-bar 아래 콘텐츠만 팬Talk 탭 전용 API 응답으로 구성한다.
API는 GET /api/v2/creator-channels/{creatorId}/fan-talks를 사용한다. creatorId는 path variable이며, query parameter는 page, size를 사용한다. 기본값은 page=0, size=20이다.
Figma 참조:
- 전체 화면:
290:9139,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-9139&m=dev - 아이템 뷰(답글 없음):
290:9145,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-9145&m=dev - 아이템 뷰(답글 있음):
290:9147,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-9147&m=dev - 더보기 anchored context popup:
666:36114,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=666-36114&m=dev - Empty:
290:9001,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-9001&m=dev
2. Problem
- 현재
CreatorChannelTab.fanTalk은 placeholder로 표시되어 팬Talk 목록을 확인할 수 없다. - 기존 홈 탭에는 최신 팬Talk 요약만 있고, 팬Talk 탭 전용 목록 API, 페이징, 답글 표시, 신고/삭제 액션이 없다.
- 기존 프로필 FanTalk 구현은 구 API와 구 UI 구조를 사용하므로 V2 크리에이터 채널 탭에 그대로 붙이기 어렵다.
3. Goals
CreatorChannelTab.fanTalk선택 시 팬Talk 탭 API를 호출하고 응답 데이터로 화면을 구성한다.- 기본 query는
page=0,size=20이다. - sort-bar에는 정렬 UI 없이
전체 {fanTalkCount}만 표시한다. - 팬Talk item은 Figma
290:9145,290:9147기준으로 작성자 프로필, 닉네임, 상대 시간, 본문, 답글 목록을 표시한다. - 답글이 있으면 Figma처럼 좌측 라인과 답글 카드 영역을 표시한다.
- 다른 유저의 글에는
신고버튼만 표시하고, 기존UserProfileView의 응원글 신고 기능과 동일하게CheersReportDialogView및ReportType.CHEERS흐름을 사용한다. - 내가 쓴 글 또는 내 채널의 타인 글에는 우측 액션으로
ic_new_more더보기 버튼을 표시한다. - 내가 쓴 글의 더보기 메뉴에는
수정하기,삭제하기를 표시한다. - 내가 쓴 글이 아니지만 내 채널인 경우 더보기 메뉴에는
삭제하기만 표시한다. 삭제하기는 기존 FanTalk에서 사용하던 삭제 API와 동일하게ExplorerRepository.modifyCheers(..., isActive: false)를 사용한다.fanTalkCount == 0이면 Figma empty view(290:9001)를 표시한다.- 내 채널인 경우 우측하단 글쓰기 floating button과 empty view 내부
응원 남기기버튼을 모두 표시하지 않는다.
4. Non-Goals
- 크리에이터 채널 공통 shell, header, sticky tab-bar 동작을 다시 설계하지 않는다.
- 신규 글쓰기/수정 페이지를 이번 작업에서 구현하지 않는다.
- 팬Talk 작성/수정 mutation API를 새로 만들지 않는다.
- 신고 API나 신고 dialog를 새로 만들지 않는다.
- 삭제 API를 새로 만들지 않고 기존 FanTalk 삭제 흐름을 재사용한다.
- Figma localhost asset URL을 앱 코드에 직접 사용하지 않는다.
Pods/**,generated/**,build/**는 수정하지 않는다.
5. Core Requirements
5.1 API
- Method:
GET - Path:
/api/v2/creator-channels/{creatorId}/fan-talks - Path parameter:
creatorId
- Query parameters:
page: 기본값0size: 기본값20
- 응답 래퍼는 기존 패턴대로
ApiResponse<CreatorChannelFanTalkTabResponse>로 디코딩한다.
data class CreatorChannelFanTalkTabResponse(
val fanTalkCount: Int,
val fanTalks: List<CreatorChannelFanTalkResponse>,
val page: Int,
val size: Int,
@JsonProperty("hasNext")
val hasNext: Boolean
)
data class CreatorChannelFanTalkResponse(
val fanTalkId: Long,
val writerId: Long,
val writerNickname: String,
val writerProfileImageUrl: String,
val content: String,
val createdAtUtc: String,
val creatorReplies: List<CreatorChannelFanTalkReplyResponse>
)
data class CreatorChannelFanTalkReplyResponse(
val fanTalkId: Long,
val writerId: Long,
val writerNickname: String,
val writerProfileImageUrl: String,
val content: String,
val createdAtUtc: String
)
- Kotlin
Long은 기존 V2 모델 관례대로 SwiftInt로 선언한다. CreatorChannelFanTalkResponse는 홈 탭 모델과 이름이 충돌하므로 홈 탭 모델명을 변경하거나 팬Talk 탭 모델명을 분리해 컴파일 충돌을 피한다.
5.2 Count bar
- 팬Talk 탭 sort-bar는 정렬이 없고 전체 개수만 포함한다.
- 좌측에
전체과fanTalkCount를 표시한다. - 우측 정렬 버튼, 정렬 아이콘, 정렬 context popup, BottomSheet는 표시하지 않는다.
- 후원 탭의
CreatorChannelDonationCountBar와 같은 시각 규칙을 사용하되 FanTalk 전용 이름으로 분리하거나 공용화한다.
5.3 FanTalk item
- item 전체 배경은
Color.black, 하단 separator는Color.gray800기준을 사용한다. - item padding은 Figma 기준 14pt를 사용한다.
- 작성자 프로필 이미지는 42pt 원형으로 표시한다.
- 작성자 닉네임은 14pt medium, 작성 시간은 14pt regular와
Color.gray500으로 표시한다. - 본문은 16pt regular,
Color.white, 좌측 50pt inset으로 표시한다. - 본문과 답글은 서버 응답의 문자열을 그대로 표시한다.
- 작성 시간은 기존 프로젝트의 상대 시간 표시 helper를 우선 재사용한다.
- 이미지 로딩은 기존 V2 관례대로
DownsampledKFImage또는 Kingfisher 기반 컴포넌트를 사용한다.
5.4 Creator replies
creatorReplies가 비어 있으면 답글 영역을 표시하지 않는다.creatorReplies가 있으면 각 답글을 Figma290:9147기준으로 표시한다.- 답글 카드 배경은
Color.gray900, radius는 14pt, padding은 14pt를 사용한다. - 답글 작성자 프로필은 20pt 원형으로 표시하고 닉네임과 상대 시간을 한 줄에 표시한다.
- 답글 본문은 16pt regular,
Color.white로 표시한다. - 답글 영역 왼쪽에는 Figma처럼 세로 라인을 표시한다.
5.5 Item action rules
- 현재 로그인 사용자의 id는 기존 관례대로
UserDefaults.int(forKey: .userId)를 사용한다. isMine = fanTalk.writerId == currentUserId.isOwnCreatorChannel은CreatorChannelView에서 계산한 값을 주입한다.isMine || isOwnCreatorChannel이면 우측에ic_new_more더보기 버튼을 표시한다.!isMine && !isOwnCreatorChannel이면 우측에신고버튼만 표시한다.- 더보기 버튼을 터치하면 Figma
666:36114기준 anchored context popup을 표시한다. - 내가 쓴 글이면
수정하기,삭제하기를 표시한다. - 내가 쓴 글이 아니지만 내 채널이면
삭제하기만 표시한다. 수정하기와 글쓰기 floating button은 후속 신규 글쓰기 페이지 구현 전까지 비어 있는 placeholder action으로 두되, 코드상 TODO가 드러나게 유지한다.삭제하기는 확인 dialog 후 기존 삭제 API를 호출한다.
5.6 Report and delete
- 신고 버튼을 터치하면 기존 크리에이터 페이지의 응원글 신고와 동일하게
CheersReportDialogView를 표시한다. - 신고 confirm 시
ReportRequest(type: .CHEERS, cheersId: fanTalkId, reason: reason)흐름을 사용한다. - 삭제 confirm dialog는 기존
I18n.MemberChannel.cheersDeleteTitle,I18n.Common.confirmDeleteQuestion,I18n.Common.delete,I18n.Common.cancel을 재사용한다. - 삭제 API는 기존 FanTalk 삭제 흐름과 동일하게
ExplorerRepository.modifyCheers(cheersId: fanTalkId, content: nil, isActive: false)를 호출한다. - 삭제 성공 후 팬Talk 탭 첫 페이지를 다시 조회한다.
5.7 Empty and writing button
fanTalkCount == 0이면 Figma290:9001기준 empty view를 표시한다.- Empty 문구는
아직 응원이 없습니다.\n처음으로 크리에이터를 응원해 보세요!를 표시한다. - Empty view에는
+아이콘과응원 남기기텍스트가 있는 capsule button을 표시한다. - 단, 내 채널인 경우 empty view 내부
응원 남기기버튼을 표시하지 않는다. fanTalkCount > 0이면 홈 탭 plus button 위치에 글쓰기 floating button을 표시한다.- 단, 내 채널인 경우 글쓰기 floating button을 표시하지 않는다.
- 글쓰기 floating button은
CreatorChannelFloatingActionMenu내부floatingButton과 동일한 66pt 원형 버튼, 38pt 아이콘,Color.soda400배경을 사용한다. - 동일 UI를 중복 구현하지 않기 위해
SodaLive/Sources/V2/CreatorChannel/Components/**아래에 공용 icon floating button을 분리하고,CreatorChannelFloatingActionMenu와 팬Talk 글쓰기 floating button이 이를 재사용한다. - 글쓰기 floating button에는 plus 아이콘만 표시하고 텍스트는 표시하지 않는다.
- 글쓰기 버튼 tap action은 신규 글쓰기 페이지 구현 후 연결할 수 있도록 부모 closure로 분리한다.
5.8 Pagination
- 첫 진입 시
page=0,size=20으로 조회한다. - 다음 페이지 로딩 중 중복 호출을 막는다.
- 마지막 item이 화면에 나타났고
hasNext == true이면page + 1을 조회한다. - 다음 페이지 성공 시 기존
fanTalks뒤에 append한다. - 첫 페이지 재조회 시 기존 목록을 교체한다.
6. Success Criteria
- 팬Talk 탭 진입 시
GET /api/v2/creator-channels/{creatorId}/fan-talks?page=0&size=20가 호출된다. - count bar에는
전체 {fanTalkCount}만 표시되고 정렬 버튼/아이콘/popup은 표시되지 않는다. - 답글이 없는 item은 Figma
290:9145와 같은 정보 구조로 표시된다. - 답글이 있는 item은 Figma
290:9147처럼 좌측 라인과 답글 카드가 표시된다. - 타인의 글이면서 내 채널이 아니면
신고버튼만 표시되고 신고 confirm 시 기존 응원글 신고 API가 호출된다. - 내가 쓴 글은
ic_new_more버튼과수정하기,삭제하기메뉴를 표시한다. - 내가 쓴 글이 아니지만 내 채널이면
ic_new_more버튼과삭제하기메뉴만 표시한다. - 삭제 confirm 시 기존 FanTalk 삭제 API가 호출되고 성공 후 첫 페이지가 갱신된다.
fanTalkCount == 0이면 Figma290:9001empty view가 표시된다.- 내 채널인 경우 empty view 내부
응원 남기기버튼과 우측하단 글쓰기 floating button이 모두 표시되지 않는다. fanTalkCount > 0이고 내 채널이 아니면 우측하단 글쓰기 floating button이 표시된다.- 글쓰기/수정하기 tap은 신규 글쓰기 페이지 구현 전까지 앱 crash 없이 no-op placeholder로 동작한다.
7. Technical Constraints
- 기능 변경은
SodaLive/Sources/V2/CreatorChannel/**하위에서 해결한다. - 팬Talk 탭 전용 View, ViewModel, Repository, API, 모델은
SodaLive/Sources/V2/CreatorChannel/FanTalk/**아래에 둔다. - 우측하단 icon floating button은 팬Talk 전용 컴포넌트로 중복 생성하지 않고
CreatorChannelFloatingActionMenu의 privatefloatingButton패턴을 공용 컴포넌트로 추출해 재사용한다. - 삭제 API 재사용을 위해 기존
ExplorerRepository.modifyCheers를 호출할 수 있다. - 신고 기능 재사용을 위해 기존
ReportRepository,ReportRequest,CheersReportDialogView를 사용한다. - 신규 문구가 필요하면
SodaLive/Sources/I18n/I18n.swift에 ko/en/ja를 추가한다. - 프로젝트 설정 변경은 신규 Swift 파일 target 등록이 필요한 경우에만 수행한다.
8. Assumptions
- 신규 글쓰기/수정 페이지는 후속 작업에서 구현하며, 이번 작업에서는 버튼 표시와 action closure만 준비한다.
- 신규 API의
fanTalkId는 기존 신고/삭제 API가 요구하는cheersId와 동일한 식별자로 사용할 수 있다.
9. Open Questions
- 해당 없음
10. Verification Notes
- 2026-07-04: Figma
get_design_context와get_screenshot으로290:9139,290:9145,290:9147,666:36114,290:9001을 확인했다. - 2026-07-04:
CreatorChannelView, 후원 탭 구현, 기존UserProfileFanTalkViewModel,UserProfileFanTalkCheersItemView,UserProfileView의 신고/삭제 흐름을 확인했다.