Files

414 lines
32 KiB
Markdown

# PRD: 크리에이터 채널 홈 탭
## 1. Overview
크리에이터 채널 화면은 title bar, 크리에이터 프로필 header, tab-bar를 공통 shell로 유지하고, tab-bar 아래 콘텐츠만 선택된 탭에 따라 교체한다. 채널 최초 진입 시 기본 선택 탭은 `홈`이며, 홈 탭에서는 신규 API `GET /api/v2/creator-channels/{creatorId}/home` 응답을 사용해 현재 라이브, 최신 오디오 콘텐츠, 후원, 공지, 스케줄, 오디오, 시리즈, 커뮤니티, 팬Talk, 소개, 활동, SNS 정보를 표시한다. 대화하기 액션은 최신 코드 기준처럼 크리에이터 프로필 header 내부에 표시한다.
API 연동을 먼저 구현하고, UI는 공통 shell과 홈 탭 콘텐츠를 분리한 뒤 API 응답 데이터를 기준으로 Figma 섹션 단위로 나누어 순차 구현한다.
Figma 전체 화면 기준 공통 shell은 아래를 따른다.
1. title bar
2. 크리에이터 이미지/프로필 header
3. tab-bar
최신 코드 기준 홈 탭 콘텐츠 순서는 아래를 따른다.
1. 현재 라이브
2. 최신 오디오 콘텐츠
3. 채널 후원
4. 공지
5. 스케줄
6. 오디오
7. 시리즈
8. 커뮤니티
9. 팬Talk
10. 소개
11. 활동
12. SNS
상단 tab-bar 항목은 `홈`, `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원`으로 구성한다. Figma에는 `화보` 탭과 활동 항목이 보이지만 이번 구현 범위에서는 제외한다.
## 2. Problem
- 기존 크리에이터 상세/채널 화면은 신규 `creator-channels` 홈 API 응답 구조와 Figma의 채널 홈 구성을 그대로 반영하지 못한다.
- 홈 API는 크리에이터 프로필과 여러 도메인 데이터를 한 endpoint에서 받지만, 크리에이터 프로필은 채널 공통 shell에 쓰이고 나머지 섹션은 홈 탭 콘텐츠에 쓰인다. 이를 한 View에 직접 구현하면 이후 탭별 화면 확장 시 유지보수와 검증이 어려워진다.
- 크리에이터 이미지 영역이 OS status bar 영역까지 확장되고, scroll 위치에 따라 title bar/tab-bar/status bar 상태가 함께 변해야 하므로 일반적인 정적 navigation bar로 처리하기 어렵다.
- tab-bar는 title bar와 붙는 순간 sticky 상태가 되어야 하고, sticky 이후에는 아래 콘텐츠만 스크롤되어야 한다.
- `isAiChatAvailable` 값에 따라 대화하기 버튼 노출이 달라지지만, 버튼이 없어도 액션 영역 높이는 유지해야 한다.
- 선택된 tab 및 홈 섹션의 `전체보기` 진입 화면은 전체 기능 구현 전에도 placeholder destination이 필요하다.
## 3. Goals
- `creatorId``GET /api/v2/creator-channels/{creatorId}/home`을 호출하고 응답 데이터로 크리에이터 채널 공통 shell과 홈 탭 콘텐츠를 구성한다.
- 신규 API, Repository, ViewModel, Response model은 `SodaLive/Sources/V2/**` 하위에 둔다.
- API 구현을 UI보다 먼저 완료해 공통 shell과 홈 탭 섹션들이 동일한 response model을 사용하도록 한다.
- `CreatorChannelView`는 title bar, header, tab-bar, 선택된 tab 상태, 홈 API 호출 상태를 소유한다.
- `CreatorChannelHomeView`는 tab-bar 아래 홈 탭 콘텐츠만 렌더링하며, 대화하기 액션은 `CreatorChannelHeaderSection`에서 렌더링한다.
- 홈 API 응답의 `creator` 정보는 공통 shell의 header/title/follow/notification/action 상태에 반영한다.
- Figma 기준 섹션을 이후 `plan-task.md`에서 phase 단위로 나눌 수 있도록 요구사항을 분리한다.
- 크리에이터 대표 이미지는 화면 최상단에서 OS status bar 영역까지 확장해 표시한다.
- scroll 진행도에 따라 title bar 배경색을 점진적으로 black에 가깝게 변경한다.
- tab-bar가 title bar와 맞닿으면 sticky 상태로 고정하고, sticky 이후 OS status bar 배경도 title bar와 동일하게 보이도록 처리한다.
- title bar는 `isFollow`, `isNotify` 상태에 따라 Figma의 Unfollow, Follow+알림 설정, Follow+알림 해제 상태를 표시한다.
- 홈 tab 외 tab-bar 항목 및 홈 섹션의 전체보기 destination은 placeholder 형태로 먼저 연결한다.
- V2 하위의 재사용 가능한 공용 컴포넌트는 우선 재사용한다.
- 빈 섹션은 section title과 empty state를 표시하지 않고 숨긴다.
## 4. Non-Goals
- `화보` 탭과 화보 섹션은 구현하지 않는다.
- 이번 API 스펙에 없는 페이지네이션, 무한 스크롤, 섹션별 필터/정렬 기능을 추가하지 않는다.
- 후원 작성, 댓글/좋아요, 커뮤니티 구매, 콘텐츠 구매의 실제 mutation 구현은 이번 PRD의 필수 범위로 보지 않는다.
- DM 버튼 및 DM 보내기 진입은 추후 작업으로 미루고 이번 범위에서 구현하지 않는다.
- 라이브룸, 오디오 상세, 시리즈 상세, 커뮤니티 상세, 팬Talk 전체, 후원 전체의 실제 상세 기능을 새로 구현하지 않는다. 기존 진입 흐름이 있으면 연결하고, 없으면 placeholder로 둔다.
- Figma localhost asset URL을 앱 코드에 직접 사용하지 않는다.
- `Pods/**`, `generated/**`, `build/**`는 수정하지 않는다.
## 5. Target Users
- 크리에이터 채널에서 라이브, 콘텐츠, 커뮤니티, 후원, 팬Talk 정보를 한 번에 확인하려는 사용자
- 크리에이터를 팔로우하거나 알림 상태를 확인하려는 사용자
- 크리에이터와 AI 대화로 이동하려는 사용자
- 특정 섹션의 전체 목록으로 이동해 더 많은 콘텐츠를 탐색하려는 사용자
## 6. User Stories
- 사용자는 크리에이터 채널 홈에서 크리에이터 이미지, 닉네임, 팔로워 수를 확인하고 싶다.
- 사용자는 팔로우하지 않은 크리에이터를 title bar에서 팔로우하고 싶다.
- 사용자는 팔로우한 크리에이터의 알림 설정 상태를 title bar에서 구분하고 싶다.
- 사용자는 현재 진행 중인 라이브가 있으면 홈 상단에서 바로 확인하고 싶다.
- 사용자는 최신 오디오 콘텐츠와 오디오 목록을 홈에서 빠르게 탐색하고 싶다.
- 사용자는 채널 후원 메시지와 후원 전체 목록을 확인하고 싶다.
- 사용자는 공지, 스케줄, 커뮤니티, 팬Talk를 홈에서 요약 형태로 확인하고 전체보기로 이동하고 싶다.
- 사용자는 크리에이터 소개, 활동 통계, SNS 링크를 채널 홈 하단에서 확인하고 싶다.
## 7. Core Requirements
### 7.1 크리에이터 채널 홈 데이터 조회
#### API
- Method: `GET`
- Path: `/api/v2/creator-channels/{creatorId}/home`
- Path parameter: `creatorId`
- 인증: 기존 V2 API 인증 헤더 패턴을 따른다.
- 응답 래퍼: 기존 관례대로 `ApiResponse<CreatorChannelHomeResponse>` 디코딩을 우선한다.
#### Response 기준
```kotlin
data class CreatorChannelHomeResponse(
val creator: CreatorChannelCreatorResponse,
val currentLive: CreatorChannelLiveResponse?,
val latestAudioContent: CreatorChannelAudioContentResponse?,
val channelDonations: List<CreatorChannelDonationResponse>,
val notices: List<CreatorChannelCommunityPostResponse>,
val schedules: List<CreatorChannelScheduleResponse>,
val audioContents: List<CreatorChannelAudioContentResponse>,
val series: List<CreatorChannelSeriesResponse>,
val communities: List<CreatorChannelCommunityPostResponse>,
val fanTalk: CreatorChannelFanTalkSummaryResponse,
val introduce: String,
val activity: CreatorChannelActivityResponse,
val sns: CreatorChannelSnsResponse
)
```
#### Swift 모델 기준
```swift
struct CreatorChannelHomeResponse: Decodable {
let creator: CreatorChannelCreatorResponse
let currentLive: CreatorChannelLiveResponse?
let latestAudioContent: CreatorChannelAudioContentResponse?
let channelDonations: [CreatorChannelDonationResponse]
let notices: [CreatorChannelCommunityPostResponse]
let schedules: [CreatorChannelScheduleResponse]
let audioContents: [CreatorChannelAudioContentResponse]
let series: [CreatorChannelSeriesResponse]
let communities: [CreatorChannelCommunityPostResponse]
let fanTalk: CreatorChannelFanTalkSummaryResponse
let introduce: String
let activity: CreatorChannelActivityResponse
let sns: CreatorChannelSnsResponse
}
```
- Kotlin `Long`으로 정의된 id/count 계열 값은 Swift에서 `Int`로 통일한다.
- `CreatorActivityType`은 기존 `SodaLive/Sources/V2/Main/Home/Following/Models/HomeFollowingTabResponse.swift`의 enum 재사용 또는 공용 이동 여부를 계획 단계에서 결정한다.
- `profileImageUrl`, `coverImageUrl`, `imageUrl`, `audioUrl` 등 URL 문자열은 서버 스펙의 nullable 여부를 따른다. 빈 문자열은 이미지 없음과 동일하게 처리할지 구현 전 확인한다.
### 7.2 화면 상태
- 최초 진입 시 홈 API를 호출한다.
- 로딩 중에는 기존 V2 화면 패턴에 맞는 loading state를 표시한다.
- API 실패 시에는 전체 화면 error state로 전환하지 않고 placeholder 기반으로 일부 UI를 유지한다.
- API 실패 placeholder는 title bar, tab-bar, 홈 외 tab placeholder destination처럼 서버 데이터 없이 표시 가능한 공통 shell을 유지하는 방식으로 처리한다.
- 선택된 tab 상태와 홈 API 호출 상태는 공통 shell의 ViewModel에서 관리한다.
- 응답을 성공적으로 받은 뒤 각 섹션은 자신의 데이터가 비어 있으면 section title과 empty state를 표시하지 않고 섹션 전체를 숨긴다.
- 동일 화면 생명주기 안에서 불필요한 중복 호출은 피한다.
- pull-to-refresh가 기존 크리에이터 상세 화면에 있다면 같은 패턴을 검토한다. 기존 패턴이 없으면 이번 범위에서 새로 추가하지 않는다.
### 7.3 Header / Title Bar / Status Bar
Figma 참조:
- 전체 화면: `node-id=296:14890`
- Unfollow title bar: `node-id=296:14287`, `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=296-14287&m=dev`
- Follow + 알림 설정 title bar: `node-id=296:14288`, `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=296-14288&m=dev`
- Follow + 알림 해제 title bar: `node-id=296:14289`, `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=296-14289&m=dev`
요구사항:
- title bar, 크리에이터 프로필 header, status bar 처리는 `CreatorChannelView` 공통 shell에서 담당한다.
- 크리에이터 이미지 영역은 OS status bar 영역까지 확장한다.
- title bar는 화면 최상단에 `ZStack` 또는 `overlay` 형태로 띄워 header view와 겹치게 배치한다.
- title bar 뒤에 큰 배경 이미지가 보이도록 기본 배경은 투명이다.
- scroll 진행도에 따라 `backgroundProgress`가 증가할 때만 title bar 배경색을 black에 가깝게 점진적으로 표시한다.
- tab-bar와 title bar가 가까워질수록 title bar 배경색은 점진적으로 black으로 변한다.
- tab-bar가 sticky 상태가 되면 OS status bar 영역도 title bar 배경색과 동일하게 보이도록 한다.
- title bar 좌측에는 back 버튼을 둔다.
- title bar 우측에는 팔로우/알림 상태 버튼과 더보기 버튼을 둔다.
- title bar 중앙에는 크리에이터 닉네임을 표시한다.
- title bar 닉네임은 `backgroundProgress`가 1일 때만 표시한다.
- title bar 닉네임은 한 줄로 표시하고, 영역을 넘으면 말줄임 처리한다.
- title bar 닉네임이 길어도 우측 팔로우/알림/더보기 영역은 항상 먼저 보여야 한다.
- title bar 좌측 back 버튼은 `ic_new_bar_back` asset을 사용한다.
- title bar 우측 더보기 버튼은 `ic_new_more` asset을 사용한다.
- `isFollow == false`이면 `팔로우` capsule 버튼을 표시한다.
- `isFollow == false` 상태의 follow capsule에는 `ic_new_follow` asset을 사용한다.
- `isFollow == true` 상태의 following capsule에는 `ic_new_following` asset을 사용한다.
- `isFollow == true && isNotify == true`이면 following capsule과 알림 설정 아이콘 `ic_bar_bell_colored`를 표시한다.
- `isFollow == true && isNotify == false`이면 following capsule과 알림 해제 아이콘 `ic_bar_bell`을 표시한다.
- 더보기 버튼은 항상 표시한다.
- 팔로우/팔로우 취소/알림 설정/알림 설정 취소 mutation은 기존 `UserProfile`에서 사용하는 `UserRepository.creatorFollow(creatorId:follow:notify:)` 흐름을 그대로 사용한다.
- 팔로우 action은 `creatorFollow(follow: true, notify: true)`를 호출한다.
- 팔로우 취소 action은 기존 `UserProfile``CreatorFollowNotifyDialog.onClickUnFollow`와 동일하게 `creatorFollow(follow: false, notify: false)`를 호출한다.
- `ic_bar_bell` 터치 시 알림 설정 action으로 `creatorFollow(follow: true, notify: true)`를 호출한다.
- `ic_bar_bell_colored` 터치 시 알림 설정 취소 action으로 `creatorFollow(follow: true, notify: false)`를 호출한다.
- 알림 상태 변경용 신규 API는 만들지 않는다.
- title bar에 사용하는 아이콘은 `ic_new_bar_back`, `ic_new_follow`, `ic_new_following`, `ic_new_more`, `ic_bar_bell`, `ic_bar_bell_colored`로 고정하고, 다른 back/follow/more/bell asset으로 대체하지 않는다.
### 7.4 크리에이터 프로필 헤더
- 크리에이터 프로필 헤더는 홈 탭 콘텐츠가 아니라 `CreatorChannelView` 공통 shell에 속한다.
- HeaderView의 표시 내용은 `CreatorChannelHomeResponse.creator`를 사용해 채운다.
- HeaderView에는 별도 원형/소형 프로필 이미지를 표시하지 않는다.
- `creator.profileImageUrl`은 크리에이터 이미지 헤더의 큰 배경 이미지에만 사용한다.
- 큰 배경 이미지 영역은 OS status bar까지 확장되도록 top safe area를 무시한다.
- `creator.nickname`, `creator.followerCount`를 Figma 위치와 계층에 맞게 표시한다.
- `creator.characterId`가 있는 경우 캐릭터/AI 대화 연결 여부를 판단하는 데이터로 사용한다.
- 대화하기 액션 영역은 최신 코드 기준처럼 `CreatorChannelHeaderSection` 내부에 속한다.
- 이미지 로드 실패 시 기존 프로젝트의 이미지 placeholder 패턴을 따른다.
- 텍스트가 길어도 이미지/버튼/탭 영역과 겹치지 않도록 한 줄 말줄임 또는 기존 nickname 표시 관례를 따른다.
### 7.5 대화하기 액션 영역
- 대화하기 액션 영역은 최신 코드 기준처럼 크리에이터 프로필 header 내부에 속한다.
- `creator.isAiChatAvailable == true`이면 대화하기 버튼을 표시한다.
- 대화하기 아이콘은 `ic_new_talk` asset을 사용한다.
- 대화하기 버튼은 영역 중앙에 배치한다.
- `creator.isAiChatAvailable == false`여도 액션 영역의 높이와 vertical spacing은 보존한다.
- 대화하기 버튼 action은 기존 AI 채팅방 페이지로 이동한다.
- 기존 AI 채팅방 진입에 필요한 본인인증 guard를 동일하게 적용한다.
- 본인인증 guard에는 한국이 아닌 국가에서 다른 값으로 비교하는 기존 분기 조건도 포함한다.
- `creator.isDmAvailable``ic_new_dm`은 response/asset 확인 대상이지만, DM 버튼 UI와 DM 진입은 추후 작업으로 미루고 이번 범위에서 구현하지 않는다.
### 7.6 Tab Bar
- tab-bar는 `CreatorChannelView` 공통 shell에 속하며, 선택된 tab에 따라 tab-bar 아래 콘텐츠만 교체한다.
- tab-bar 항목은 `홈`, `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원` 순서로 표시한다.
- `화보` 탭은 표시하지 않는다.
- tab-bar는 horizontal scroll 가능 구조로 구현한다.
- 선택된 탭은 Figma처럼 하단 indicator와 white text로 표시한다.
- 선택되지 않은 탭은 gray text로 표시한다.
- tab-bar가 title bar와 맞닿으면 sticky 상태가 되고, 이후에는 tab-bar 아래 콘텐츠만 스크롤된다.
- 선택된 tab이 `홈`이 아닐 때는 실제 목록 화면 대신 선택된 탭 제목을 표시하는 placeholder 페이지를 표시한다.
- 홈 섹션의 `전체보기` chevron/button으로 이동해야 하는 destination도 해당 tab placeholder 또는 별도 placeholder 화면으로 연결한다.
### 7.7 현재 라이브 섹션
- `currentLive != nil`이면 현재 라이브 섹션을 표시한다.
- `liveId`, `title`, `coverImageUrl`, `beginDateTimeUtc`, `price`, `isAdult`를 사용한다.
- `coverImageUrl`이 없으면 기존 라이브 카드의 기본 이미지 처리 패턴을 따른다.
- `isAdult == true`이면 기존 19금/성인 콘텐츠 표시 asset 또는 패턴을 따른다.
- card tap 시 기존 라이브 상세/라이브룸 진입 흐름이 있으면 연결하고, 없으면 placeholder action으로 둔다.
### 7.8 최신 오디오 콘텐츠 섹션
- `latestAudioContent != nil`이면 최신 오디오 콘텐츠 섹션을 표시한다.
- `audioContentId`, `title`, `duration`, `imageUrl`, `price`, `isAdult`, `isPointAvailable`, `isFirstContent`, `seriesName`, `isOriginalSeries`를 사용한다.
- V2 공용 `AudioContentCard`가 요구사항과 맞으면 재사용한다.
- `isPointAvailable`, `isFirstContent`, `isOriginalSeries` 표시는 기존 오디오 카드/태그 패턴을 우선 따른다.
- card tap 시 기존 오디오 콘텐츠 상세 진입 흐름이 있으면 연결하고, 없으면 placeholder action으로 둔다.
### 7.9 채널 후원 섹션
- `channelDonations`를 사용해 채널 후원 요약 목록을 표시한다.
- 각 item은 `nickname`, `profileImageUrl`, `can`, `message`, `createdAtUtc`를 표시한다.
- `channelDonations`가 비어 있으면 채널 후원 섹션을 숨긴다.
- 전체보기 action은 기존 `AppStep.channelDonationAll(creatorId:)` 또는 동일한 기존 흐름이 있으면 연결한다.
- 기존 흐름 연결이 어렵다면 후원 tab placeholder로 이동한다.
### 7.10 공지 섹션
- `notices`를 사용해 공지 게시물을 표시한다.
- 응답 모델은 `CreatorChannelCommunityPostResponse`를 재사용한다.
- 공지 섹션은 일반 커뮤니티 섹션과 시각 구성이 다를 수 있으므로 별도 section component로 분리한다.
- `imageUrl`, `audioUrl`, `price`, `existOrdered`, `likeCount`, `commentCount` 처리는 기존 커뮤니티 카드 패턴을 따른다.
- 반응 정보는 Figma 기준으로 댓글 아이콘/댓글 수를 먼저, 좋아요 아이콘/좋아요 수를 뒤에 표시한다.
- 공지 전체보기 또는 item tap destination은 기존 커뮤니티 상세/목록 흐름이 있으면 연결하고, 없으면 placeholder로 둔다.
### 7.11 스케줄 섹션
- `schedules`를 사용해 예정 항목을 표시한다.
- 각 item은 `scheduledAtUtc`, `title`, `type`, `targetId`를 사용한다.
- `type``LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 등 기존 `CreatorActivityType` 처리 범위를 따른다.
- schedule tap 시 기존 `MainView.handleFollowingScheduleTap(type:targetId:)`와 같은 분기 패턴을 검토해 재사용한다.
- 지원하지 않는 type은 crash 없이 무시하거나 placeholder로 둔다.
### 7.12 오디오 섹션
- `audioContents`를 사용해 오디오 콘텐츠 목록을 표시한다.
- V2 공용 `AudioContentCard` 재사용을 우선 검토한다.
- 홈 섹션에서는 Figma 기준 노출 개수만 표시하고, 전체보기는 오디오 tab placeholder 또는 기존 오디오 목록으로 이동한다.
- `audioContents`가 비어 있으면 오디오 섹션을 숨긴다.
### 7.13 시리즈 섹션
- `series`를 사용해 시리즈 목록을 표시한다.
- 각 item은 `seriesId`, `title`, `coverImageUrl`, `numberOfContent`, `isNew`, `isOriginal`을 표시한다.
- `isNew`, `isOriginal` 표시는 Figma 태그와 기존 시리즈 카드 패턴을 따른다.
- 전체보기는 시리즈 tab placeholder 또는 기존 시리즈 목록으로 이동한다.
- item tap 시 기존 시리즈 상세 흐름이 있으면 연결하고, 없으면 placeholder action으로 둔다.
### 7.14 커뮤니티 섹션
- `communities`를 사용해 커뮤니티 게시물 목록을 표시한다.
- V2 공용 `CommunityPostCard`가 요구사항과 맞으면 재사용한다.
- `imageUrl`, `audioUrl`, `price`, `existOrdered`, `likeCount`, `commentCount`를 표시 규칙에 반영한다.
- 반응 정보는 Figma 기준으로 댓글 아이콘/댓글 수를 먼저, 좋아요 아이콘/좋아요 수를 뒤에 표시한다.
- 유료/잠금 게시물은 기존 커뮤니티 잠금/구매 표시 패턴을 따른다.
- 홈에서는 Figma 기준 노출 개수만 표시하고 `전체보기` 버튼으로 커뮤니티 tab placeholder 또는 기존 커뮤니티 목록으로 이동한다.
### 7.14.1 커뮤니티 게시글 상세
- 게시글 본문 영역과 댓글 목록 사이에는 Figma 기준 `gray/800` 1pt 하단 border를 표시한다.
- 댓글 목록에서는 댓글 row 사이에 `gray/800` 1pt separator를 표시한다.
- 상세 본문의 반응 정보도 댓글 아이콘/댓글 수를 먼저, 좋아요 아이콘/좋아요 수를 뒤에 표시한다.
### 7.15 팬Talk 섹션
- `fanTalk.totalCount``fanTalk.latestFanTalk`를 사용한다.
- `latestFanTalk == nil`이면 팬Talk 섹션을 숨긴다.
- 최신 팬Talk가 있으면 `nickname`, `profileImageUrl`, `content`, `languageCode`, `createdAtUtc`를 표시한다.
- 전체보기 action은 크리에이터 채널의 팬Talk 탭으로 이동한다.
### 7.16 소개 섹션
- `introduce` 문자열을 표시한다.
- 빈 문자열이면 소개 섹션을 숨긴다.
- 긴 텍스트는 Figma 기준으로 전체 표시하되, 화면 폭을 넘지 않게 줄바꿈 처리한다.
### 7.17 활동 섹션
- `activity`를 사용해 아래 항목을 표시한다.
- `debutDateUtc``dDay`를 조합해 `2026.06.11(D+1)` 형식으로 표시한다.
- `liveCount``라이브 총 진행 수`로 표시한다.
- `liveDurationHours``라이브 누적 진행 시간`으로 표시한다.
- `liveContributorCount``라이브 누적 참여자`로 표시한다.
- `audioContentCount``오디오`로 표시한다.
- `seriesCount``시리즈`로 표시한다.
- Figma에는 `화보` 활동 항목이 있지만 response 초안에 필드가 없고 이번 범위에서 화보 제외이므로 표시하지 않는다.
- 숫자 formatting은 기존 프로젝트의 count formatting 패턴을 따른다.
### 7.18 SNS 섹션
- `sns.instagramUrl`, `sns.fancimmUrl`, `sns.xUrl`, `sns.youtubeUrl`, `sns.kakaoOpenChatUrl`을 사용한다.
- 빈 URL 또는 유효하지 않은 URL은 해당 SNS 아이콘을 숨긴다.
- 표시 순서는 Figma 기준 `Instagram`, `YouTube`, `X`, `KakaoTalk`, `Fancimm(팬심M)` 순서를 따른다.
- SNS 아이콘은 `ic_sns_*` asset을 사용한다.
- tap 시 외부 브라우저 또는 기존 in-app web 흐름을 따른다.
## 8. UX / UI Expectations
### 8.1 포함하는 UI
- OS status bar 영역까지 확장되는 크리에이터 이미지 헤더
- scroll progress에 따라 black으로 변하는 overlay title bar
- 팔로우/알림 상태별 title bar
- sticky horizontal tab-bar
- 크리에이터 프로필 header 내부의 대화하기 액션 영역
- 홈 탭의 섹션별 summary UI
- 홈 외 탭의 placeholder page
- 홈 섹션 전체보기 placeholder destination
### 8.2 제외하는 UI
- 화보 탭
- 화보 섹션
- 활동 섹션의 화보 count row
- DM 버튼 및 DM 보내기 진입
- 새 외부 라이브러리 추가
### 8.3 시각 규칙
- 전체 화면은 Figma처럼 dark background를 기준으로 한다.
- Figma의 fixed width/height 값은 참고하되, SwiftUI 구현에서는 화면 width, safe area, dynamic type에 대응 가능한 layout을 우선한다.
- card/list root container는 필요한 경우를 제외하고 고정 숫자 width/height로 제한하지 않는다.
- section title은 V2 공용 `SectionTitle` 재사용을 우선 검토한다.
- chevron이 있는 section title 또는 전체보기 버튼은 tap 가능한 영역을 충분히 확보한다.
- profile image, cover image, content image는 기존 이미지 로딩/placeholder 패턴을 따른다.
- nickname/title/content가 길어도 인접 UI와 겹치지 않도록 말줄임 또는 줄바꿈을 적용한다.
## 9. Technical Constraints
- 신규 View, ViewModel, Repository 및 연결 하위 코드는 `SodaLive/Sources/V2/**` 아래에 작성한다.
- 여러 페이지에서 재사용 가능한 공용 컴포넌트는 `SodaLive/Sources/V2/Component/**` 아래에 둔다.
- 크리에이터 채널 공통 shell 내부에서만 쓰는 컴포넌트는 `SodaLive/Sources/V2/CreatorChannel/Components/**` 아래에 둔다.
- 홈 탭 내부에서만 쓰는 컴포넌트는 `SodaLive/Sources/V2/CreatorChannel/Home/Components/**` 아래에 둔다.
- API/Repository/ViewModel 구성은 기존 `SodaLive/Sources/V2/Main/Home/Following/**`, `Ranking/**`, `Recommendation/**` 패턴을 따른다.
- `SodaLive/Sources/V2/Component/SectionTitle.swift`, `AudioContentCard.swift`, `CommunityPostCard.swift`, `CapsuleTabBar.swift` 등 기존 V2 컴포넌트 재사용 가능성을 먼저 검토한다.
- `CreatorActivityType`은 중복 선언하지 않고 기존 enum 재사용 또는 공용 위치 이동을 검토한다.
- 신규 asset은 프로젝트 asset catalog에 이미 존재하는 `ic_new_talk`을 사용한다. `ic_new_dm`은 추후 DM 버튼 작업에서 사용한다.
- title bar 아이콘은 프로젝트 asset catalog의 `ic_new_bar_back`, `ic_new_follow`, `ic_new_following`, `ic_new_more`, `ic_bar_bell`, `ic_bar_bell_colored`를 사용한다.
- 신규 문구가 다국어 대상이면 `SodaLive/Sources/I18n/I18n.swift`에 추가한다.
- Figma에서 제공되는 localhost asset URL은 앱 코드에 넣지 않는다.
- 프로젝트 설정 변경은 신규 파일이 Xcode project에 자동 포함되지 않는 구조일 때만 수행한다.
- Kotlin `Long`으로 정의된 id/count 계열 값은 Swift에서 `Int`로 통일한다.
- SNS 섹션 아이콘은 Figma localhost asset이 아니라 프로젝트 asset catalog의 `ic_sns_*` 아이콘을 사용한다.
## 10. Success Criteria
- 크리에이터 채널 진입 시 `CreatorChannelView`가 표시되고, 기본 선택 탭은 `홈`이다.
- 크리에이터 채널 진입 시 `GET /api/v2/creator-channels/{creatorId}/home` 호출이 발생한다.
- response model이 PRD의 API 초안 필드를 디코딩한다.
- API 실패 시 전체 화면 error state 대신 placeholder 기반으로 표시 가능한 공통 shell UI가 유지된다.
- `creator` 정보가 공통 shell의 header/title 상태와 홈 탭의 action 상태에 반영된다.
- 크리에이터 이미지가 OS status bar 영역까지 표시된다.
- HeaderView는 `CreatorChannelHomeResponse.creator`를 기반으로 표시되고, 별도 프로필 이미지를 추가로 표시하지 않는다.
- title bar의 기본 배경은 투명이고 큰 배경 이미지 위에 overlay되어 보인다.
- scroll 위치에 따라 title bar 배경이 점진적으로 black으로 변한다.
- tab-bar가 title bar와 맞닿으면 sticky 상태가 되고 아래 콘텐츠만 스크롤된다.
- sticky 상태에서 OS status bar 영역도 title bar와 동일한 black 배경으로 보인다.
- `isFollow`, `isNotify` 조합에 따라 title bar의 팔로우/알림 상태가 Figma 3개 상태와 일치한다.
- title bar 배경 opacity가 1일 때 크리에이터 닉네임이 한 줄 말줄임으로 표시되고, 긴 닉네임이어도 우측 팔로우/알림/더보기 영역이 우선 노출된다.
- title bar는 `ic_new_bar_back`, `ic_new_follow`, `ic_new_following`, `ic_new_more`, `ic_bar_bell`, `ic_bar_bell_colored` asset만 사용한다.
- 팔로우/팔로우 취소/알림 설정/알림 설정 취소 action은 기존 `UserProfile`과 동일하게 `UserRepository.creatorFollow(creatorId:follow:notify:)`를 호출한다.
- `ic_bar_bell` 터치 시 `creatorFollow(follow: true, notify: true)`, `ic_bar_bell_colored` 터치 시 `creatorFollow(follow: true, notify: false)`가 호출된다.
- `isAiChatAvailable`에 따라 대화하기 버튼이 조건부 표시된다.
- 대화하기 버튼은 기존 AI 채팅방 페이지로 이동하고, 기존 본인인증 guard와 비한국 국가 분기 guard를 적용한다.
- 대화하기 버튼이 없어도 액션 영역 높이는 유지된다.
- DM 버튼은 표시되지 않는다.
- tab-bar 아래 콘텐츠는 선택된 tab에 따라 교체된다.
- 홈 tab에는 현재 라이브, 최신 오디오 콘텐츠, 채널 후원, 공지, 스케줄, 오디오, 시리즈, 커뮤니티, 팬Talk, 소개, 활동, SNS 섹션이 API 데이터 기반으로 표시된다.
- SNS 섹션은 `ic_sns_*` asset 아이콘과 유효한 SNS URL만 사용해 표시된다.
- 데이터가 비어 있는 섹션은 표시되지 않는다.
- `화보` 탭, 화보 섹션, 활동의 화보 row가 표시되지 않는다.
- 홈 외 tab-bar 항목 선택 시 선택한 탭 제목을 표시하는 placeholder page가 표시된다.
- 홈 섹션의 전체보기 action은 기존 화면 또는 placeholder destination으로 이동한다.
- 기존 V2 공용 컴포넌트를 재사용 가능한 곳에서 재사용하고, 채널 홈 전용 UI만 전용 `Components`로 분리한다.
## 11. Open Questions
해당 없음.
## 12. Verification Notes
- `docs/agent-guides/documentation-policy.md`를 확인해 신규 PRD 경로와 필수 섹션 기준을 검증했다.
- `docs/prd/sample-prd.md`, `docs/20260630_메인_홈_랭킹_탭/prd.md`, `docs/20260630_메인_홈_팔로잉_탭/prd.md`를 확인해 저장소의 PRD 작성 스타일을 맞췄다.
- Figma `node-id=296:14890`의 design context와 screenshot을 확인해 홈 화면 섹션, tab-bar 항목, sticky 대상 구조를 검토했다.
- Figma `node-id=296:14287`, `296:14288`, `296:14289`의 design context와 screenshot을 확인해 title bar의 Unfollow, Follow+알림 설정, Follow+알림 해제 상태를 검토했다.
- `SodaLive/Sources/V2/**` 구조를 확인해 기존 V2 홈 API/Repository/ViewModel/Components 배치 패턴을 검토했다.
- `SodaLive/Sources/V2/Component/SectionTitle.swift`, `AudioContentCard.swift`, `CommunityPostCard.swift`, `CapsuleTabBar.swift` 등 재사용 후보 파일 존재를 확인했다.
- 사용자 확인 사항을 반영해 `creator.profileImageUrl`을 헤더 큰 이미지로 사용, 빈 섹션 숨김, 기존 `UserProfile` follow/notify API 사용, 대화하기의 기존 AI 채팅방 및 본인인증 guard 적용, DM 버튼 추후 작업, 홈 외 탭 제목 placeholder, 팬Talk 전체보기의 팬Talk 탭 이동, Swift `Int` 통일 정책을 확정 요구사항으로 이동했다.
- 사용자 확인 사항을 반영해 API 실패 시 placeholder 기반으로 일부 UI를 유지하고, SNS 섹션 아이콘은 `ic_sns_*` asset을 사용하도록 확정 요구사항으로 이동했다.
- 저장소의 `ic_sns_fancimm`, `fancimmUrl`, `I18n.ProfileUpdate.fancimm`을 확인해 Figma의 Fansim 표기를 `Fancimm(팬심M)` 기준으로 정리했다.
- 2026-07-02: 사용자 확인 사항과 최신 코드 기준을 반영해 title bar, 크리에이터 프로필 header, tab-bar를 `CreatorChannelView` 공통 shell로 두고, tab-bar 아래 홈 탭 콘텐츠는 `CreatorChannelHomeView`가 담당하며 대화하기 액션은 `CreatorChannelHeaderSection` 내부에 유지하도록 구조를 정리했다.
- 2026-07-02: 사용자 확인 사항과 최신 코드 기준을 반영해 title bar Figma URL 3종과 사용할 아이콘 asset(`ic_new_bar_back`, `ic_new_follow`, `ic_new_following`, `ic_new_more`, `ic_bar_bell`, `ic_bar_bell_colored`)을 확정 요구사항으로 추가했다.
- 2026-07-02: 기존 `UserProfile` 동작을 확인해 title bar의 팔로우/팔로우 취소/알림 설정/알림 설정 취소를 `UserRepository.creatorFollow(creatorId:follow:notify:)`로 처리하도록 확정했다.
- 2026-07-02: 사용자 확인 사항을 반영해 HeaderView는 `CreatorChannelHomeResponse.creator` 데이터로 채우고, 별도 프로필 이미지 없이 큰 배경 이미지만 표시하며, title bar는 기본 투명 배경으로 header 위에 overlay되도록 요구사항을 정리했다.