62 KiB
62 KiB
크리에이터 채널 홈 구현 계획
기준 문서
- PRD:
docs/20260701_크리에이터_채널_홈/prd.md - 코드 스타일:
docs/agent-guides/code-style.md - 빌드/검증:
docs/agent-guides/build-test-verification.md - Figma 전체 화면:
296:14890 - Figma Unfollow title bar:
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 - Figma Follow + 알림 설정 title bar:
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 - Figma Follow + 알림 해제 title bar:
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
구현 원칙
- API, Response model, Repository, ViewModel을 먼저 구현한 뒤 UI phase를 진행한다.
- 크리에이터 채널 진입점은
CreatorChannelView로 두고, 최초 선택 tab은.home으로 둔다. CreatorChannelView는 title bar, 크리에이터 프로필 header, tab-bar, 선택된 tab 상태, 홈 API 호출 상태를 소유한다.CreatorChannelHomeView는 tab-bar 아래 홈 탭 콘텐츠만 렌더링하며, 대화하기 action은 최신 코드 기준처럼CreatorChannelHeaderSection내부에서 렌더링한다.- 홈 API 응답의
creator정보는 공통 shell의 header/title/follow/notification/대화하기 action 상태가 공유한다. - 크리에이터 채널 공통 shell 구현은
SodaLive/Sources/V2/CreatorChannel/**아래에 둔다. - 크리에이터 채널 홈 탭 내부에서만 쓰는 UI는
SodaLive/Sources/V2/CreatorChannel/Home/Components/**아래에 둔다. - 크리에이터 채널 공통 shell 내부에서만 쓰는 UI는
SodaLive/Sources/V2/CreatorChannel/Components/**아래에 둔다. - 여러 화면에서 재사용할 근거가 명확한 UI만
SodaLive/Sources/V2/Component/**로 올린다. - 기존 V2 홈의
TargetType, Repository, ViewModel,ApiResponse<T>디코딩 패턴을 따른다. Long계열 id/count는 SwiftInt로 통일한다.- 빈 섹션은 section title과 empty state까지 포함해 표시하지 않는다.
- API 실패 시 전체 화면 error state로 전환하지 않고 title bar, tab-bar, 홈 외 tab placeholder처럼 서버 데이터 없이 가능한 기본 shell을 유지한다.
화보탭, 화보 섹션, 활동의 화보 row는 구현하지 않는다.- DM 버튼과 DM 진입은 구현하지 않는다.
- Figma localhost asset URL은 앱 코드에 사용하지 않는다.
- title bar 아이콘은
ic_new_bar_back,ic_new_follow,ic_new_following,ic_new_more,ic_bar_bell,ic_bar_bell_coloredasset을 사용한다. - SNS 아이콘은
ic_sns_instagram,ic_sns_youtube,ic_sns_x,ic_sns_kakao,ic_sns_fancimmasset을 사용한다. - 기존
AppStep.creatorDetail(userId:)진입은 새 크리에이터 채널 화면으로 연결한다.
주요 대상 파일
생성
SodaLive/Sources/V2/CreatorChannel/Home/Models/CreatorChannelHomeResponse.swiftSodaLive/Sources/V2/CreatorChannel/Models/CreatorChannelTab.swiftSodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeApi.swiftSodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeRepository.swiftSodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swiftSodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swiftSodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swiftSodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swiftSodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swiftSodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTabBar.swiftSodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelPlaceholderTabView.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelTalkActionSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelCurrentLiveSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelLatestAudioSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelNoticeSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelScheduleSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelSeriesSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelCommunitySection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelFanTalkSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelIntroduceSection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelActivitySection.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelSnsSection.swift
수정
SodaLive/Sources/ContentView.swiftSodaLive/Sources/I18n/I18n.swift- 필요 시
SodaLive.xcodeproj/project.pbxproj
확인
SodaLive/Sources/V2/Main/Home/Ranking/Repository/MainHomeRankingApi.swiftSodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingViewModel.swiftSodaLive/Sources/V2/Main/Home/Following/Models/HomeFollowingTabResponse.swiftSodaLive/Sources/V2/Main/MainView.swiftSodaLive/Sources/Chat/ChatTabView.swiftSodaLive/Sources/User/UserApi.swiftSodaLive/Sources/Content/Series/Detail/SeriesDetailViewModel.swiftSodaLive/Sources/V2/Component/SectionTitle.swiftSodaLive/Sources/V2/Component/AudioContentCard.swiftSodaLive/Sources/V2/Component/Card/CommunityPostCard.swiftSodaLive/Sources/Explorer/Profile/Detail/CreatorDetailDialogView.swift
TASK 체크리스트
Phase 1: API와 상태 모델
-
Task 1.1: 크리에이터 채널 홈 Response model 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Models/CreatorChannelHomeResponse.swift - 확인:
SodaLive/Sources/V2/Main/Home/Following/Models/HomeFollowingTabResponse.swift
- 생성:
- 작업 내용:
- PRD의
CreatorChannelHomeResponse와 하위 응답 모델을 SwiftDecodablestruct로 작성한다. - Kotlin
Long필드는 SwiftInt로 선언한다. - list item은 필요한 경우
Identifiable을 채택하고 id는 서버 id 필드를 사용한다. CreatorActivityType은 기존 enum을 재사용하거나 공용 위치로 이동한다. 중복 enum을 만들지 않는다.- nullable URL 필드는 PRD nullable 여부에 맞춰 optional로 선언한다.
- PRD의
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelHomeResponse|struct CreatorChannelCreatorResponse|struct CreatorChannelLiveResponse|struct CreatorChannelAudioContentResponse|struct CreatorChannelDonationResponse|struct CreatorChannelScheduleResponse|struct CreatorChannelSeriesResponse|struct CreatorChannelCommunityPostResponse|struct CreatorChannelFanTalkSummaryResponse|struct CreatorChannelActivityResponse|struct CreatorChannelSnsResponse" SodaLive/Sources/V2/CreatorChannel/Home/Models/CreatorChannelHomeResponse.swift - 기대 결과: PRD의 응답 모델이 Swift 파일에 모두 존재하고 id/count 타입이
Int이다.
- 실행 명령:
- 대상 파일:
-
Task 1.2: 채널 tab enum 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Models/CreatorChannelHomeTab.swift
- 생성:
- 작업 내용:
CreatorChannelHomeTabenum을CaseIterable, Hashable로 만든다.- case는
home,live,audio,series,community,fanTalk,donation순서로 둔다. - title은
홈,라이브,오디오,시리즈,커뮤니티,팬Talk,후원을 반환한다. photo또는화보case는 만들지 않는다.
- 검증 기준:
- 실행 명령:
rg "enum CreatorChannelHomeTab|case home|case live|case audio|case series|case community|case fanTalk|case donation|화보|photo" SodaLive/Sources/V2/CreatorChannel/Home/Models/CreatorChannelHomeTab.swift - 기대 결과: 7개 tab case가 있고
화보/photocase가 없다.
- 실행 명령:
- 후속 구조 변경:
- tab enum은 홈 탭 전용이 아니라 채널 공통 shell 상태이므로 Task 2.4에서
CreatorChannelTab으로 이름과 위치를 정리한다.
- tab enum은 홈 탭 전용이 아니라 채널 공통 shell 상태이므로 Task 2.4에서
- 대상 파일:
-
Task 1.3: API endpoint 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeApi.swift - 확인:
SodaLive/Sources/V2/Main/Home/Ranking/Repository/MainHomeRankingApi.swift
- 생성:
- 작업 내용:
CreatorChannelHomeApi를TargetType으로 만든다.- case는
getHome(creatorId: Int)하나로 시작한다. - path는
/api/v2/creator-channels/{creatorId}/home형식으로 구성한다. - method는
.get, task는.requestPlain로 둔다. - headers는 기존 V2 API와 동일하게
Authorization: Bearer {token}패턴을 따른다.
- 검증 기준:
- 실행 명령:
rg "enum CreatorChannelHomeApi|getHome\\(creatorId: Int\\)|/api/v2/creator-channels/|/home|TargetType|requestPlain|Authorization" SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeApi.swift - 기대 결과: 신규 endpoint와 인증 헤더가 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 1.4: Repository 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeRepository.swift - 확인:
SodaLive/Sources/V2/Main/Home/Ranking/Repository/MainHomeRankingRepository.swift
- 생성:
- 작업 내용:
CreatorChannelHomeRepository를 만들고MoyaProvider<CreatorChannelHomeApi>를 사용한다.getHome(creatorId:) -> AnyPublisher<Response, MoyaError>메서드를 제공한다.
- 검증 기준:
- 실행 명령:
rg "final class CreatorChannelHomeRepository|MoyaProvider<CreatorChannelHomeApi>|getHome\\(creatorId: Int\\)|AnyPublisher<Response, MoyaError>" SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeRepository.swift - 기대 결과: 기존 V2 Repository와 같은 형태가 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 1.5: ViewModel 생성 및 API 실패 placeholder 상태 정의
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeViewModel.swift - 확인:
SodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingViewModel.swift - 확인:
SodaLive/Sources/User/UserApi.swift - 확인:
SodaLive/Sources/Content/Series/Detail/SeriesDetailViewModel.swift
- 생성:
- 작업 내용:
CreatorChannelHomeViewModel을ObservableObject로 만든다.@Published var isLoading,@Published var response,@Published var hasLoaded,@Published var selectedTab,@Published var isApiFailedPlaceholderVisible를 둔다.fetchHome(creatorId:)에서ApiResponse<CreatorChannelHomeResponse>를 디코딩한다.- 성공 시
response,selectedTab = .home,isApiFailedPlaceholderVisible = false를 갱신한다. - 실패/디코딩 실패 시
response = nil,isApiFailedPlaceholderVisible = true,hasLoaded = true로 두어 기본 shell은 유지할 수 있게 한다. - 초기 구현에서는
follow(creatorId:notify:),unfollow(creatorId:)에 기존UserRepository.creatorFollow,UserRepository.creatorUnFollow패턴을 재사용한다. - mutation 성공 시
response?.creator.isFollow,response?.creator.isNotify가 갱신될 수 있도록 모델 갱신 방식을 구현한다. struct 불변성 때문에 필요한 경우 creator 복사 helper를 둔다.
- 검증 기준:
- 실행 명령:
rg "final class CreatorChannelHomeViewModel|fetchHome\\(creatorId: Int\\)|ApiResponse<CreatorChannelHomeResponse>|isApiFailedPlaceholderVisible|creatorFollow|creatorUnFollow|selectedTab|hasLoaded" SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeViewModel.swift - 기대 결과: 홈 API 디코딩, API 실패 placeholder 상태, 기존 follow/unfollow API 호출이 확인된다.
- 실행 명령:
- 후속 구조 변경:
- title bar mutation은 기존
UserProfile현재 동작과 동일하게 Task 2.4에서CreatorChannelViewModel의creatorFollow(follow:notify:)기반으로 정리한다.
- title bar mutation은 기존
- 대상 파일:
Phase 2: 라우팅과 기본 화면 shell
-
Task 2.1: 기존 creatorDetail 라우팅을 신규 홈으로 연결
- 대상 파일:
- 수정:
SodaLive/Sources/ContentView.swift - 생성:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/App/AppStep.swift
- 수정:
- 작업 내용:
AppStep.creatorDetail(userId:)case는 유지한다.ContentView에서.creatorDetail(let userId)destination을CreatorChannelHomeView(creatorId: userId)로 변경한다.- 기존
UserProfileView를 삭제하거나 수정하지 않는다. - 초기 구현에서는
CreatorChannelHomeView가creatorId: Int를 받아 화면을 구성한다.
- 검증 기준:
- 실행 명령:
rg "case \\.creatorDetail|CreatorChannelHomeView\\(creatorId: userId\\)|UserProfileView\\(userId:" SodaLive/Sources/ContentView.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과:
.creatorDetail이 신규CreatorChannelHomeView로 연결되고 기존UserProfileView파일은 유지된다.
- 실행 명령:
- 후속 구조 변경:
- 크리에이터 채널 공통 shell 분리 결정에 따라 Task 2.4에서
.creatorDetaildestination을CreatorChannelView(creatorId:)로 변경한다.
- 크리에이터 채널 공통 shell 분리 결정에 따라 Task 2.4에서
- 대상 파일:
-
Task 2.2: 기본 shell과 로딩/API 실패 placeholder 구성
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelPlaceholderTabView.swift
- 수정:
- 작업 내용:
@StateObject private var viewModel = CreatorChannelHomeViewModel()를 사용한다.- 최초
onAppear에서hasLoaded == false일 때fetchHome(creatorId:)를 호출한다. - root background는 black으로 둔다.
response == nil && isApiFailedPlaceholderVisible == true이면 title bar, tab-bar, 선택된 tab placeholder만 표시한다.- 로딩 중에는 기존
LoadingView또는 V2 관례에 맞는 loading view를 사용한다. - 홈 외 tab 선택 시
CreatorChannelPlaceholderTabView(title: selectedTab.title)을 표시한다.
- 검증 기준:
- 실행 명령:
rg "@StateObject private var viewModel|fetchHome\\(creatorId: creatorId\\)|isApiFailedPlaceholderVisible|CreatorChannelPlaceholderTabView|LoadingView|Color.black" SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelPlaceholderTabView.swift - 기대 결과: API 호출, 실패 placeholder, 홈 외 tab placeholder shell이 확인된다.
- 실행 명령:
- 후속 구조 변경:
- 공통 shell과 선택 tab/API 상태는 Task 2.4에서
CreatorChannelView/CreatorChannelViewModel로 이동하고,CreatorChannelHomeView는 홈 탭 콘텐츠만 담당한다.
- 공통 shell과 선택 tab/API 상태는 Task 2.4에서
- 대상 파일:
-
Task 2.3: I18n 문구 추가
- 대상 파일:
- 수정:
SodaLive/Sources/I18n/I18n.swift
- 수정:
- 작업 내용:
I18n.CreatorChannelHomeenum을 추가한다.- 섹션명
currentLive,latestAudio,donation,notice,schedule,audio,series,community,fanTalk,introduce,activity,sns를 추가한다. - 액션 문구
follow,talk,viewAll를 추가한다. - 활동 row 문구
debut,liveCount,liveDurationHours,liveContributorCount,audioContentCount,seriesCount를 추가한다. - ko/en/ja 문구를 모두 제공한다.
- 검증 기준:
- 실행 명령:
rg "enum CreatorChannelHome|currentLive|latestAudio|fanTalk|introduce|activity|viewAll|liveDurationHours|seriesCount" SodaLive/Sources/I18n/I18n.swift - 기대 결과: 신규 사용자 노출 문구가
I18n에 존재한다.
- 실행 명령:
- 대상 파일:
-
Task 2.4: 공통 CreatorChannel shell로 구조 정리
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 생성:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift - 생성/이동:
SodaLive/Sources/V2/CreatorChannel/Models/CreatorChannelTab.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 수정/정리:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeViewModel.swift - 수정:
SodaLive/Sources/ContentView.swift - 확인:
SodaLive/Sources/App/AppStep.swift
- 생성:
- 작업 내용:
ContentView의.creatorDetail(let userId)destination을CreatorChannelView(creatorId: userId)로 연결한다.CreatorChannelView는@StateObject private var viewModel = CreatorChannelViewModel()을 사용한다.CreatorChannelViewModel은isLoading,response,hasLoaded,selectedTab,isApiFailedPlaceholderVisible, follow/notify mutation을 소유한다.- 기존
CreatorChannelHomeViewModel의 홈 API 호출/공통 상태 책임은CreatorChannelViewModel로 이동하고, 남는 책임이 없으면 파일을 제거한다. - title bar의 팔로우/팔로우 취소/알림 설정/알림 설정 취소는 기존
UserProfile현재 UI 흐름과 동일하게UserRepository.creatorFollow(creatorId:follow:notify:)를 사용한다. - 팔로우는
creatorFollow(follow: true, notify: true), 팔로우 취소는creatorFollow(follow: false, notify: false)로 호출한다. ic_bar_bell터치 시creatorFollow(follow: true, notify: true),ic_bar_bell_colored터치 시creatorFollow(follow: true, notify: false)로 호출한다.CreatorChannelHomeTab은CreatorChannelTab으로 이름을 바꾸고 공통 shell 경로로 이동한다.CreatorChannelHomeView는CreatorChannelHomeResponse와 tab 전환 closure를 주입받아 tab-bar 아래 홈 탭 콘텐츠만 렌더링하고, 대화하기 action은CreatorChannelHeaderSection에 유지한다.- API 실패 placeholder 상태에서는
CreatorChannelView가 서버 데이터 없이 가능한 title bar, tab-bar, 선택된 tab placeholder를 유지한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelView|final class CreatorChannelViewModel|enum CreatorChannelTab|CreatorChannelView\\(creatorId: userId\\)|CreatorChannelHomeView\\(|selectedTab|fetchHome\\(creatorId:|creatorFollow\\(.*follow: true, notify: true|creatorFollow\\(.*follow: false, notify: false|creatorFollow\\(.*follow: true, notify: false" SodaLive/Sources/V2/CreatorChannel SodaLive/Sources/ContentView.swift - 기대 결과: 라우팅 진입점과 선택 tab/API 상태가
CreatorChannelView/CreatorChannelViewModel로 이동했고, title bar follow/notify mutation이 기존UserProfile의creatorFollow(follow:notify:)기준으로 연결되어 있으며,CreatorChannelHomeView는 홈 탭 콘텐츠 렌더링만 담당한다.
- 실행 명령:
- 대상 파일:
Phase 3: Header / Title Bar / Tab Bar / Sticky
-
Task 3.1: title bar 컴포넌트 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift - 확인:
SodaLive/Sources/Common/FollowButtonImageAsset.swift
- 생성:
- 작업 내용:
- back 버튼, 팔로우/팔로잉 상태 버튼, 알림 상태 아이콘, 더보기 버튼을 표시한다.
- back 버튼은
ic_new_bar_backasset을 사용한다. - 더보기 버튼은
ic_new_moreasset을 사용한다. isFollow == false이면팔로우capsule을 표시한다.isFollow == false상태의 follow capsule에는ic_new_followasset을 사용한다.isFollow == true상태의 following capsule에는ic_new_followingasset을 사용한다.isFollow == true && isNotify == true이면 팔로잉 상태 capsule과 알림 설정 아이콘ic_bar_bell_colored를 표시한다.isFollow == true && isNotify == false이면 팔로잉 상태 capsule과 알림 해제 아이콘ic_bar_bell을 표시한다.ic_new_follow터치 시 부모의 팔로우 action으로creatorFollow(follow: true, notify: true)가 호출되도록 연결한다.ic_new_following터치 시 부모의 팔로우 취소 action으로creatorFollow(follow: false, notify: false)가 호출되도록 연결한다.ic_bar_bell터치 시 부모의 알림 설정 action으로creatorFollow(follow: true, notify: true)가 호출되도록 연결한다.ic_bar_bell_colored터치 시 부모의 알림 설정 취소 action으로creatorFollow(follow: true, notify: false)가 호출되도록 연결한다.- 더보기 버튼은 항상 표시한다.
- 배경 opacity는 외부에서 전달받는
backgroundProgress로 제어한다. - 구현 기준은 Figma
296:14287,296:14288,296:142893개 title bar 상태를 따른다. - title bar 아이콘은
ic_new_bar_back,ic_new_follow,ic_new_following,ic_new_more,ic_bar_bell,ic_bar_bell_colored외 다른 asset으로 대체하지 않는다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelTitleBar|isFollow|isNotify|backgroundProgress|onTapBack|onTapFollow|onTapUnfollow|onTapNotify|onTapUnnotify|onTapMore|ic_new_bar_back|ic_new_follow|ic_new_following|ic_new_more|ic_bar_bell|ic_bar_bell_colored|팔로우" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift - 기대 결과: Figma 3개 title bar 상태를 표현하는 조건 분기, 지정된 6개 icon asset 사용, 팔로우/팔로우 취소/알림 설정/알림 설정 취소 tap closure가 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 3.2: 크리에이터 이미지/프로필 헤더 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift
- 생성:
- 작업 내용:
- HeaderView의 표시 내용은
CreatorChannelHomeResponse.creator를 사용해 채운다. - 별도 원형/소형 프로필 이미지는 표시하지 않는다.
creator.profileImageUrl은 큰 배경 이미지에만 사용한다.- 큰 배경 이미지 영역은 OS status bar까지 확장되도록 top safe area를 무시한다.
creator.nickname,creator.followerCount를 표시한다.- 이미지 로드 실패 시 기존
DownsampledKFImage또는KFImageplaceholder 관례를 따른다.
- HeaderView의 표시 내용은
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelHeaderSection|CreatorChannelCreatorResponse|profileImageUrl|ignoresSafeArea\\(.*top|nickname|followerCount|DownsampledKFImage|KFImage" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 기대 결과:
CreatorChannelHomeResponse.creator기반 데이터 표시, 큰 배경 이미지의 top safe area 확장, 별도 프로필 이미지 미표시가 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 3.3: horizontal tab-bar 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTabBar.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 확인:
SodaLive/Sources/V2/Component/TextTabBar.swift
- 생성:
- 작업 내용:
CreatorChannelTab.allCases를 horizontal scroll로 표시한다.- 선택된 tab은 white text와 soda color bottom indicator로 표시한다.
- 비선택 tab은 gray text로 표시한다.
화보tab은 표시하지 않는다.- sticky 상태일 때도 같은 컴포넌트를 사용한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelTabBar|ScrollView\\(\\.horizontal|CreatorChannelTab.allCases|selectedTab|soda|indicator|화보" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTabBar.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 기대 결과: 7개 tab만 표시되고 선택 상태 UI가 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 3.4: scroll progress와 sticky 계산 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTabBar.swift
- 수정:
- 작업 내용:
GeometryReader와PreferenceKey기반 scroll offset 또는 geometry preference로 tab-bar와 title bar의 거리를 계산한다.- 거리에 따라 title bar background progress를 0...1로 clamp한다.
- title bar는 header view 위에
ZStack또는overlay형태로 띄운다. - title bar 뒤로 큰 배경 이미지가 보이도록 기본
backgroundProgress는 0, 기본 배경은 투명으로 둔다. - tab-bar가 title bar에 닿으면 tab-bar를 sticky 상태로 고정한다.
- sticky 기준은 디바이스 최상단
y=0이 아니라 title bar 하단이며, sticky 이후 tab-bar는 title bar 하단까지만 스크롤된 뒤 멈춘다. - sticky 이후 OS status bar 영역이 title bar와 동일한 black 배경으로 보이게 상단 overlay를 둔다.
- 검증 기준:
- 실행 명령:
rg "PreferenceKey|GeometryReader|ZStack|overlay|backgroundProgress|Color\\.clear|opacity|isTabBarSticky|clamp|safeAreaInsets|CreatorChannelTitleBar|CreatorChannelTabBar" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTabBar.swift - 기대 결과: geometry preference 기반 계산, 기본 투명 title bar overlay, scroll 기반 title bar opacity, sticky tab-bar 상태 계산이 확인되고, tab-bar sticky 기준이 디바이스 최상단이 아니라 title bar 하단임이 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 3.5: title bar 닉네임 표시 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift
- 수정:
- 작업 내용:
CreatorChannelTitleBar에 크리에이터 닉네임을 주입받는 값을 추가한다.- title bar의 back 버튼 우측 Text에는 크리에이터 닉네임을 표시한다.
- 닉네임은 한 줄로 표시하고, 영역을 넘으면 말줄임 처리한다.
- 닉네임이 길어도 우측 팔로우/알림/더보기 영역은 항상 먼저 보이도록 layout priority 또는 고정 영역 우선순위를 적용한다.
- 닉네임은 title bar background opacity가 1일 때만 표시한다.
CreatorChannelView는viewModel.response?.creator.nickname을CreatorChannelTitleBar에 전달한다.
- 검증 기준:
- 실행 명령:
rg "nickname|lineLimit\\(1\\)|truncationMode|layoutPriority|backgroundProgress|opacity|CreatorChannelTitleBar\\(" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 기대 결과: title bar에 크리에이터 닉네임이 전달되고, 한 줄 말줄임, 우측 action 영역 우선 노출,
backgroundProgress가 1일 때만 닉네임 표시 조건이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 4: 홈 외 placeholder
- Task 4.1: 홈 외 tab placeholder 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 생성:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelPlaceholderTabView.swift
- 수정:
- 작업 내용:
selectedTab != .home이면 실제 목록 대신CreatorChannelPlaceholderTabView(title: selectedTab.title)을 표시한다.- 홈 섹션의 전체보기 action 중 별도 기존 route가 없는 경우 대응 tab을 선택하도록 연결한다.
- 팬Talk 전체보기는
selectedTab = .fanTalk로 이동한다.
- 검증 기준:
- 실행 명령:
rg "selectedTab != \\.home|CreatorChannelPlaceholderTabView\\(title: selectedTab.title\\)|selectedTab = \\.fanTalk|selectedTab = \\.audio|selectedTab = \\.series|selectedTab = \\.community|selectedTab = \\.donation" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 기대 결과: 홈 외 tab과 전체보기 placeholder 전환이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 5: 현재 라이브 섹션
- Task 5.1: 현재 라이브 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelCurrentLiveSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
- 생성:
- 작업 내용:
currentLive == nil이면 섹션을 표시하지 않는다.liveId,title,coverImageUrl,beginDateTimeUtc,price,isAdult를 표시한다.coverImageUrl이 없으면 기존 이미지 placeholder 패턴을 사용한다.isAdult == true이면 기존 성인 콘텐츠 표시 asset/pattern을 사용한다.- card tap은 기존 live detail/live room 진입 흐름이 확인되면 연결하고, 없으면 action closure만 둔다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelCurrentLiveSection|CreatorChannelLiveResponse|currentLive|liveId|coverImageUrl|isAdult|onTapLive" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelCurrentLiveSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과:
currentLiveoptional 기반 숨김과 live item 표시가 확인된다.
- 실행 명령:
- 대상 파일:
Phase 6: 최신 오디오 콘텐츠 섹션
- Task 6.1: 최신 오디오 콘텐츠 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelLatestAudioSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/V2/Component/AudioContentCard.swift
- 생성:
- 작업 내용:
latestAudioContent == nil이면 섹션을 표시하지 않는다.AudioContentCard재사용이 맞으면 사용하고, 태그/잠금 표시가 부족하면 채널 홈 전용 thumbnail wrapper를 만든다.isAdult,isPointAvailable,isFirstContent,seriesName,isOriginalSeries표시를 기존 태그 관례에 맞춘다.- card tap은 기존
AppStep.contentDetail(contentId:)흐름이 맞으면 연결한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelLatestAudioSection|latestAudioContent|AudioContentCard|isPointAvailable|isFirstContent|isOriginalSeries|contentDetail" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelLatestAudioSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 최신 오디오 optional 기반 숨김, 태그 표시, 상세 진입이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 7: 채널 후원 섹션
- Task 7.1: 채널 후원 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/App/AppStep.swift - 확인:
SodaLive/Sources/ContentView.swift
- 생성:
- 디자인 기준:
- Figma 후원 아이템:
567:17927,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=567-17927&m=dev
- Figma 후원 아이템:
- 작업 내용:
channelDonations.isEmpty여도 섹션을 숨기지 않고 Figma290:8820기준의 빈 후원 UI를 표시한다.- 각 item은 Figma 후원 아이템처럼 외곽 card 배경을
#202020, corner radius 14, 내부 vertical spacing 14 기준으로 구성한다. - item 상단의 팬 정보/후원 금액 영역은
profileImageUrl,nickname,createdAtUtc,can을 표시한다. profileImageUrl은 42x42 원형 이미지로 표시하고, 이미지가 없거나 로드 실패 시 기존 프로필 placeholder 패턴을 따른다.nickname은 14pt medium,createdAtUtc상대 시간은 14pt regular로 표시한다.- 후원 금액은 우측 pill에 기존 can icon과
{can}캔형식으로 표시한다. - 팬 이름과 후원 금액을 포함하는 상단 영역의 배경색은 후원 금액
can에 따라 다르게 적용한다.1...50:#E2E2E251...100:#73EE01101...500:#00EAFF501...:#FF4C3C
- 상단 영역 배경이 밝은 색상이므로
nickname은 black,createdAtUtc는 기존 gray 700 계열로 표시하고, 금액 pill은#202020배경과 white text를 유지한다. message는 상단 영역 아래에 16pt regular, white text로 표시하고, 긴 문장은 화면 폭 안에서 줄바꿈한다.- 전체보기는 기존
AppStep.channelDonationAll(creatorId:)로 이동하지 않고, 부모에서 주입받은onSelectTab(.donation)closure로 현재 크리에이터 채널의 후원 tab을 선택한다. - 빈 후원 UI는 section title 아래
#202020card,처음으로 크리에이터를\n후원해 보세요!문구, white capsule후원하기버튼, blackic_new_donationicon/text를 표시한다. - 후원하기 버튼은 기존
UserProfileView에서 사용하던LiveRoomDonationDialogView를 그대로 표시한다. - Dialog 설정은 기존 채널 후원과 동일하게
isAudioContentDonation: false,messageLimit: 100,I18n.MemberChannel.secretDonationLabel,I18n.MemberChannel.secretDonationMinimumCanMessage,shouldPrefixSecretInMessagePlaceholder: false를 사용한다. - 후원 전송은 기존
ChannelDonationViewModel.postChannelDonation을 재사용하고, 성공 시 현재 채널 홈 API를 다시 호출해 후원 섹션에 즉시 반영한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelDonationSection|CreatorChannelDonationEmptyCard|처음으로 크리에이터를|ic_new_donation|LiveRoomDonationDialogView|ChannelDonationViewModel|postChannelDonation|fetchHome\(creatorId: creatorId\)|createdAtUtc|can|#E2E2E2|#73EE01|#00EAFF|#FF4C3C|onSelectTab|\\.donation|channelDonationAll" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift - 기대 결과: 빈 후원 UI, 후원 금액별 상단 영역 컬러, 기존 후원 Dialog 재사용, 후원 성공 후 홈 API 재조회, 후원 tab 전체보기 연결이 확인되고 신규 구현 경로에서
channelDonationAllroute를 사용하지 않는다.
- 실행 명령:
- 대상 파일:
Phase 8: 공지 섹션
- Task 8.1: 공지 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelNoticeSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift
- 생성:
- 작업 내용:
notices.isEmpty이면 섹션을 표시하지 않는다.CreatorChannelCommunityPostResponse를 사용한다.- 공지 섹션은 커뮤니티와 별도 component로 둔다.
imageUrl,audioUrl,price,existOrdered,likeCount,commentCount를 기존 커뮤니티 카드 패턴으로 표시한다.- item tap/댓글/구매 action은 기존 route가 확인되는 범위에서만 연결하고, 불명확한 action은 빈 closure로 둔다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelNoticeSection|notices|CreatorChannelCommunityPostResponse|CommunityPostCard|existOrdered|commentCount" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelNoticeSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 공지 섹션이 커뮤니티 섹션과 분리되어 있고 빈 배열 숨김이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 9: 스케줄 섹션
- Task 9.1: 스케줄 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelScheduleSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/V2/Main/MainView.swift
- 생성:
- 작업 내용:
schedules.isEmpty이면 섹션을 표시하지 않는다.- 각 item의
scheduledAtUtc,title,type,targetId를 표시한다. - tap action은 closure로 분리하고,
.live,.liveReplay,.audio,.community분기는 기존MainView.handleFollowingScheduleTap과 같은 기준을 따른다. .unknown은 crash 없이 무시한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelScheduleSection|schedules|scheduledAtUtc|CreatorActivityType|targetId|unknown|onTapSchedule" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelScheduleSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 스케줄 표시와 type별 tap closure가 확인된다.
- 실행 명령:
- 대상 파일:
Phase 10: 오디오 섹션
- Task 10.1: 오디오 목록 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/V2/Component/AudioContentCard.swift
- 생성:
- 작업 내용:
audioContents.isEmpty이면 섹션을 표시하지 않는다.- Figma 홈 노출 개수만 표시한다.
AudioContentCard와 채널 홈 전용 thumbnail wrapper를 재사용한다.- 전체보기는 부모에서 주입받은
onSelectTab(.audio)closure로 연결한다. - item tap은 기존
AppStep.contentDetail(contentId:)흐름으로 연결한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelAudioSection|audioContents|AudioContentCard|prefix|onSelectTab|\\.audio|contentDetail" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 빈 배열 숨김, 홈 노출 개수 제한, 오디오 tab 전체보기 연결이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 11: 시리즈 섹션
- Task 11.1: 시리즈 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelSeriesSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
- 생성:
- 작업 내용:
series.isEmpty이면 섹션을 표시하지 않는다.- 각 item의
seriesId,coverImageUrl,isNew,isOriginal을 사용한다. - 카드에는 시리즈 제목과 콘텐츠 수를 표시하지 않는다.
- 전체보기는 부모에서 주입받은
onSelectTab(.series)closure로 연결한다. - item tap은 기존
AppStep.seriesDetail(seriesId:)흐름으로 연결한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelSeriesSection|seriesId|coverImageUrl|isNew|isOriginal|onSelectTab|\\.series|seriesDetail" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelSeriesSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 시리즈 카드, 전체보기, 상세 진입이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 12: 커뮤니티 섹션
- Task 12.1: 커뮤니티 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelCommunitySection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift
- 생성:
- 작업 내용:
communities.isEmpty이면 섹션을 표시하지 않는다.CommunityPostCard가 요구사항과 맞으면 재사용한다.- 유료/잠금 게시물은 기존
price,existOrdered처리 패턴을 따른다. - 전체보기는 부모에서 주입받은
onSelectTab(.community)closure로 연결한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelCommunitySection|communities|CommunityPostCard|existOrdered|onTapPurchase|onSelectTab|\\.community" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelCommunitySection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 커뮤니티 섹션과 전체보기 tab 전환이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 13: 팬Talk 섹션
- Task 13.1: 팬Talk 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelFanTalkSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
- 생성:
- 작업 내용:
fanTalk.latestFanTalk == nil이면 섹션을 표시하지 않는다.totalCount,nickname,profileImageUrl,content,languageCode,createdAtUtc를 표시한다.- 전체보기는 부모에서 주입받은
onSelectTab(.fanTalk)closure로 연결한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelFanTalkSection|latestFanTalk|totalCount|languageCode|createdAtUtc|onSelectTab|\\.fanTalk" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelFanTalkSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 최신 팬Talk가 있을 때만 표시되고 전체보기는 팬Talk tab으로 이동한다.
- 실행 명령:
- 대상 파일:
Phase 14: 소개 섹션
- Task 14.1: 소개 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelIntroduceSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
- 생성:
- 작업 내용:
introduce가 빈 문자열이면 섹션을 표시하지 않는다.- 긴 텍스트는 화면 폭을 넘지 않게 줄바꿈한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelIntroduceSection|introduce|trimmingCharacters|fixedSize|lineLimit" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelIntroduceSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 빈 소개 숨김과 긴 텍스트 줄바꿈 처리가 확인된다.
- 실행 명령:
- 대상 파일:
Phase 15: 활동 섹션
- Task 15.1: 활동 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelActivitySection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
- 생성:
- 작업 내용:
debutDateUtc와dDay를2026.06.11(D+1)형식으로 표시한다.liveCount,liveDurationHours,liveContributorCount,audioContentCount,seriesCount를 표시한다.화보row는 만들지 않는다.- 숫자는 기존
.comma()등 프로젝트 formatting 패턴을 따른다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelActivitySection|debutDateUtc|dDay|liveCount|liveDurationHours|liveContributorCount|audioContentCount|seriesCount|화보|comma" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelActivitySection.swift - 기대 결과: 활동 6개 항목만 표시되고 화보 row가 없다.
- 실행 명령:
- 대상 파일:
Phase 16: SNS 섹션
- Task 16.1: SNS 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelSnsSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 확인:
SodaLive/Sources/Explorer/Profile/Detail/CreatorDetailDialogView.swift
- 생성:
- 작업 내용:
instagramUrl,youtubeUrl,xUrl,kakaoOpenChatUrl,fancimmUrl중 유효한 URL만 표시한다.- 표시 순서는
Instagram,YouTube,X,KakaoTalk,Fancimm(팬심M)이다. - 아이콘은 각각
ic_sns_instagram,ic_sns_youtube,ic_sns_x,ic_sns_kakao,ic_sns_fancimm을 사용한다. - tap 시
openURL또는 기존 in-app web 흐름을 따른다. - 유효한 SNS URL이 하나도 없으면 섹션을 표시하지 않는다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelSnsSection|ic_sns_instagram|ic_sns_youtube|ic_sns_x|ic_sns_kakao|ic_sns_fancimm|openURL|fancimmUrl" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelSnsSection.swift - 기대 결과: SNS asset과 URL 필터링, tap 처리 방식이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 17: 대화하기 액션 영역
-
Task 17.1: 대화하기 액션 섹션 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelTalkActionSection.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
- 생성:
- 작업 내용:
isAiChatAvailable == true일 때만 대화하기 버튼을 표시한다.- 버튼 아이콘은
ic_new_talk를 사용한다. - 버튼은 영역 중앙에 배치한다.
- 버튼이 없어도 영역 높이와 vertical spacing을 유지한다.
isDmAvailable과ic_new_dm은 이번 UI에 사용하지 않는다.- 버튼 tap은
CreatorChannelHeaderSection이 부모에서 주입받은onTapTalkclosure로 전달한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelTalkActionSection|isAiChatAvailable|ic_new_talk|ic_new_dm|frame\\(height|onTapTalk" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelTalkActionSection.swift - 기대 결과: 대화하기만 조건부 표시되고 DM 버튼 구현이 없다.
- 실행 명령:
- 대상 파일:
-
Task 17.2: 기존 AI 채팅방 진입 guard 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeRepository.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift - 확인:
SodaLive/Sources/Chat/Character/Detail/CharacterDetailView.swift - 확인:
SodaLive/Sources/Chat/Character/Detail/CharacterDetailViewModel.swift - 확인:
SodaLive/Sources/Chat/ChatTabView.swift - 확인:
SodaLive/Sources/App/AppStep.swift
- 수정:
- 작업 내용:
CreatorChannelView가CreatorChannelHeaderSection에onTapTalkclosure를 주입한다.- token이 없으면
.login으로 이동한다. - 국가 코드를 trim/uppercase 처리하고, 비어 있거나
KR이면 한국으로 취급한다. - 한국 사용자는
auth == false일 때 기존 본인인증 confirm/fullScreenCover 흐름을 재사용하거나 같은 조건으로 연결한다. - 비한국 사용자는 기존
ChatTabView의 비한국 분기와 동일하게auth조건 비교를 적용한다. - 본인인증과 콘텐츠 보기 설정 guard를 통과하면
creator.characterId로TalkApi.createChatRoom을 호출하고, 성공 응답의chatRoomId로.chatRoom(id:)에 바로 진입한다. - 본인인증 완료 후 실행되는
pendingAction도.characterDetail(characterId:)가 아니라 같은 채팅방 생성 후.chatRoom(id:)진입 helper를 사용한다.
- 검증 기준:
- 실행 명령:
rg "onTapTalk|countryCode|uppercased\\(\\)|isKoreanCountry|auth == false|isShowAuthConfirmView|createChatRoom|chatRoom\\(id:|setAppStep\\(step: \\.login\\)" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeRepository.swift SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift - 기대 결과: 기존 AI 채팅 guard와 동일한 국가/본인인증 분기가 유지되고, guard 통과 후 캐릭터 상세가 아닌 채팅방으로 직접 이동한다.
- 실행 명령:
rg "characterDetail\\(characterId: characterId\\)" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 기대 결과: 검색 결과가 없다.
- 실행 명령:
- 대상 파일:
Phase 18: 최종 조립과 검증
-
Task 18.1: 홈 섹션 순서 조립
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
- 수정:
- 작업 내용:
CreatorChannelView에서 공통 shell 순서를 PRD와 동일하게 조립한다.- 공통 shell 배치: 크리에이터 이미지 header를 먼저 배치하고, title bar는 header 위에 overlay로 띄우며, 그 아래 tab-bar와 선택된 tab content를 배치한다.
- title bar 기본 배경은 투명이고 scroll progress에 따라 black으로 전환된다.
- 대화하기 액션은 최신 코드 기준처럼
CreatorChannelHeaderSection내부에 유지한다. CreatorChannelHomeView에서 홈 탭 콘텐츠 순서를 최신 코드 기준과 동일하게 조립한다.- 홈 탭 콘텐츠 순서: 현재 라이브, 최신 오디오, 채널 후원, 공지, 스케줄, 오디오, 시리즈, 커뮤니티, 팬Talk, 소개, 활동, SNS.
- 각 섹션은 자신의 데이터가 없으면 숨긴다.
- API 실패 placeholder 상태에서는 데이터 기반 섹션을 표시하지 않는다.
- 검증 기준:
- 실행 명령:
rg -n "ZStack|overlay|Color\\.clear|backgroundProgress|CreatorChannelTitleBar|CreatorChannelHeaderSection|CreatorChannelTabBar|CreatorChannelHomeView|CreatorChannelTalkActionSection|CreatorChannelCurrentLiveSection|CreatorChannelLatestAudioSection|CreatorChannelDonationSection|CreatorChannelNoticeSection|CreatorChannelScheduleSection|CreatorChannelAudioSection|CreatorChannelSeriesSection|CreatorChannelCommunitySection|CreatorChannelFanTalkSection|CreatorChannelIntroduceSection|CreatorChannelActivitySection|CreatorChannelSnsSection" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift - 기대 결과: 최신 코드 기준의 공통 shell, header 대화하기 액션, 홈 탭 콘텐츠 순서대로 조립되어 있다.
- 실행 명령:
- 대상 파일:
-
Task 18.2: 프로젝트 파일 포함 여부 확인
- 대상 파일:
- 확인/필요 시 수정:
SodaLive.xcodeproj/project.pbxproj
- 확인/필요 시 수정:
- 작업 내용:
- 신규 Swift 파일이 Xcode target에 포함되는지 확인한다.
- 자동 포함되지 않는 프로젝트 구조이면
project.pbxproj에 신규 파일을 추가한다. - 기존 사용자 변경이 있는 경우 해당 변경을 되돌리지 않는다.
- 검증 기준:
- 실행 명령:
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build - 기대 결과: 신규 파일 누락으로 인한 compile error가 없다.
- 실행 명령:
- 대상 파일:
-
Task 18.3: PRD 성공 기준 회귀 점검
- 대상 파일:
- 확인:
docs/20260701_크리에이터_채널_홈/prd.md - 확인:
SodaLive/Sources/V2/CreatorChannel/** - 확인:
SodaLive/Sources/V2/CreatorChannel/Home/**
- 확인:
- 작업 내용:
- PRD
Success Criteria를 한 줄씩 대조한다. 화보, DM 버튼, API 실패 전체 error state가 구현에 들어가지 않았는지 검색한다.ic_sns_*,ic_new_talk, title bar icon asset, 기존UserProfile기준 follow/notify mutation, title bar/header overlay, AI 채팅 guard가 구현에 포함됐는지 검색한다.
- PRD
- 검증 기준:
- 실행 명령:
rg -n "화보|photo|ic_new_dm|DM|ic_new_talk|ic_sns_|ic_new_bar_back|ic_new_follow|ic_new_following|ic_new_more|ic_bar_bell|ic_bar_bell_colored|creatorFollow|follow: true, notify: true|follow: false, notify: false|follow: true, notify: false|onTapNotify|onTapUnnotify|ZStack|overlay|Color\\.clear|isApiFailedPlaceholderVisible|countryCode|auth == false" SodaLive/Sources/V2/CreatorChannel SodaLive/Sources/ContentView.swift - 기대 결과: 제외 범위는 UI 구현에 없고, 필수 요구사항 키워드는 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 18.4: 빌드 검증
- 대상 파일:
- 확인:
docs/agent-guides/build-test-verification.md
- 확인:
- 작업 내용:
- 공식 검증 명령으로 Debug build를 실행한다.
- 실패 시 에러 로그를 기준으로 최소 수정하고 같은 명령을 다시 실행한다.
- 검증 기준:
- 실행 명령:
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build - 기대 결과: exit code 0으로 빌드가 완료된다.
- 실행 명령:
- 대상 파일:
검증 기록
- 2026-07-01:
docs/20260701_크리에이터_채널_홈/prd.md를 기준으로 API 선구현, Figma 섹션별 phase, placeholder tab, API 실패 placeholder, DM/화보 제외 범위를 계획에 반영했다. - 2026-07-01:
docs/agent-guides/documentation-policy.md를 확인해plan-task.md경로와 phase/task/checklist 형식을 검증했다. - 2026-07-01:
docs/agent-guides/build-test-verification.md를 확인해 최종 빌드 검증 명령을xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build로 반영했다. - 2026-07-01: 기존 V2 홈 API/Repository/ViewModel, AI 채팅 guard, follow/unfollow API, SNS asset 사용처를 확인해 대상 파일과 검증 기준에 반영했다.
- 2026-07-01: 사용자 요청에 따라 기존 Phase 4
대화하기 액션 영역을 Phase 17로 이동하고, 기존 Phase 517을 Phase 416으로 한 칸씩 당겼다. - 2026-07-01: Header, TitleBar, TabBar만으로 sticky 동작을 먼저 확인할 수 있도록 Phase 3에
CreatorChannelHomeView_Previews기반 debug-only sticky scaffold 검증 task를 추가했다. 2026-07-02 구조 변경으로 실제 검증 대상은CreatorChannelView_Previews로 갱신했다. - 2026-07-01: Phase 1~2 구현을 완료하고
rg체크리스트 및xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build성공으로 신규 API/상태 모델, 라우팅, 기본 shell, I18n, 프로젝트 파일 포함을 검증했다. - 2026-07-02: 사용자 확인 사항과 최신 코드 기준을 반영해 title bar, 크리에이터 프로필 header, tab-bar를
CreatorChannelView공통 shell로 분리하고,CreatorChannelHomeView는 tab-bar 아래 홈 탭 콘텐츠만 담당하며 대화하기 action은CreatorChannelHeaderSection내부에 유지하도록 PRD와 계획을 갱신했다. - 2026-07-02: 이미 완료된 Phase 1~2 기록은 보존하고, 후속 구조 정리를 위해 Task 2.4
공통 CreatorChannel shell로 구조 정리를 추가했다. - 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)을 Task 3.1 및 최종 회귀 검색 기준에 추가했다. - 2026-07-03: Phase 5 현재 라이브 섹션을 구현했다. Figma
290:8950기준으로 LIVE pill, 시작 시간, 제목, 커버 이미지/placeholder, 유료 캔 배지, 성인 표시를 반영하고CreatorChannelHomeView에currentLiveoptional 기반으로 연결했다. - 2026-07-03: Phase 7 채널 후원 섹션을 구현했다. Figma
296:14908, 후원 아이템567:17927기준으로 후원 금액별 상단 컬러(1...50#E2E2E2,51...100#73EE01,101...500#00EAFF,501...#FF4C3C),ic_new_donation후원하기 버튼,.donationtab 전체보기 전환, Preview 금액 구간별 샘플을 반영했다.xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build성공으로 신규 파일 target 포함과 컴파일을 검증했다. - 2026-07-03: 사용자 요청에 따라 Phase 7 후원하기 버튼을 기존
LiveRoomDonationDialogView/ChannelDonationViewModel.postChannelDonation흐름으로 연결하고, 성공 시CreatorChannelViewModel.fetchHome(creatorId:)로 현재 채널 홈 데이터를 다시 불러와 후원 섹션에 즉시 반영하도록 계획을 갱신했다. 후원 내역이 없는 경우 Figma290:8820기준의 빈 후원 UI를 표시하도록 Task 7.1에 반영했다. - 2026-07-03: Phase 6 최신 오디오 콘텐츠 섹션을 구현했다. Figma
296:14898, tag567:18272,567:18274기준으로 88px 썸네일, 상단/하단 tag overlay,Newlabel, 제목, 재생시간을 반영하고latestAudioContentoptional 기반 숨김 및AppStep.contentDetail(contentId:)상세 진입을 연결했다.rg체크리스트와xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build성공으로 검증했다. - 2026-07-03: Phase 4를 완료해
CreatorChannelView에서 홈 탭은CreatorChannelHomeView, 홈 외 탭은CreatorChannelPlaceholderTabView(title: selectedTab.title)로 분기하고, 홈 섹션 전체보기용 tab 선택 closure가.audio,.series,.community,.fanTalk,.donation으로 전환되도록 연결했다. - 2026-07-02: 기존
UserProfile구현과 최신 코드 기준을 확인해 title bar 팔로우/팔로우 취소/알림 설정/알림 설정 취소를UserRepository.creatorFollow(creatorId:follow:notify:)로 처리하고,ic_bar_bell/ic_bar_bell_colored터치 시 각각notify: true/notify: false호출이 일어나도록 계획에 반영했다. - 2026-07-03: Task 3.4 구현을 완료했다.
CreatorChannelView에서 geometry preference로 tab-bar 위치를 추적하고, sticky 기준을 디바이스 최상단이 아닌 title bar 하단(safeAreaInsets.top + 56)으로 계산하도록 변경했다.rg "PreferenceKey|GeometryReader|ZStack|overlay|backgroundProgress|Color\\.clear|opacity|isTabBarSticky|clamp|safeAreaInsets|CreatorChannelTitleBar|CreatorChannelTabBar" ...기준 키워드를 확인했고,xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build가BUILD SUCCEEDED로 완료됐다. - 2026-07-03: Task 3.5 구현을 완료했다.
CreatorChannelTitleBar에 크리에이터 닉네임 주입값을 추가하고,backgroundProgress가 1일 때만 한 줄 말줄임으로 표시되도록 연결했다. 우측 팔로우/알림/더보기 영역은layoutPriority로 우선 노출되도록 처리했다.rg "nickname|lineLimit\\(1\\)|truncationMode|layoutPriority|backgroundProgress|opacity|CreatorChannelTitleBar\\(" ...기준 키워드를 확인했고,xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build가BUILD SUCCEEDED로 완료됐다. - 2026-07-02: Task 3.2 구현을 완료하고
CreatorChannelHeaderSection을 공통 shell에 연결했다.rg "struct CreatorChannelHeaderSection|CreatorChannelCreatorResponse|profileImageUrl|ignoresSafeArea\\(.*top|nickname|followerCount|DownsampledKFImage|KFImage" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift와xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build성공으로 검증했다. - 2026-07-02: Task 3.1 title bar 컴포넌트를
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift로 생성하고CreatorChannelView의 inline title bar를 교체했다.rg "struct CreatorChannelTitleBar|isFollow|isNotify|backgroundProgress|onTapBack|onTapFollow|onTapUnfollow|onTapNotify|onTapUnnotify|onTapMore|ic_new_bar_back|ic_new_follow|ic_new_following|ic_new_more|ic_bar_bell|ic_bar_bell_colored|팔로우" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift와xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build성공으로 검증했다. - 2026-07-02: 사용자 확인 사항을 반영해 HeaderView는
CreatorChannelHomeResponse.creator데이터로 채우고, 별도 프로필 이미지 없이 큰 배경 이미지만 표시하며, title bar는 기본 투명 배경으로 header 위에 overlay되도록 Task 3.2/3.4/3.5와 최종 검증 기준을 갱신했다. - 2026-07-03: 사용자 요청에 따라 Task 17.2의 대화하기 액션을 캐릭터 상세 이동이 아니라 기존 Character Detail 하단
대화하기와 동일한TalkApi.createChatRoom호출 후.chatRoom(id:)직접 진입으로 변경했다.CreatorChannelView의 로그인/한국 본인인증/content settings guard는 유지했고, 본인인증 완료 후pendingAction도 같은startChat(characterId:)helper를 사용하도록 연결했다.rg -n "characterDetail\\(characterId: characterId\\)|startChat\\(characterId:|createChatRoom\\(characterId:|chatRoom\\(id:" "SodaLive/Sources/V2/CreatorChannel"와 ast-grepAppState.shared.setAppStep(step: .characterDetail(characterId: $ID))검색으로 CreatorChannel 대화하기 경로에 캐릭터 상세 이동이 남지 않았음을 확인했다. 테스트는xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test실행 결과Scheme SodaLive-dev is not currently configured for the test action.으로 RED/GREEN 자동화가 불가했다. 빌드는xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build가BUILD SUCCEEDED로 완료됐다. - 2026-07-03: Phase 18 최종 조립과 검증을 완료했다. 최신 코드 기준에 맞춰 대화하기 액션은
CreatorChannelHeaderSection내부에 유지하고,CreatorChannelHomeView홈 콘텐츠 순서는 현재 라이브, 최신 오디오, 채널 후원, 공지, 스케줄, 오디오, 시리즈, 커뮤니티, 팬Talk, 소개, 활동, SNS 순서로 확인했다. title bar 알림 설정 asset은 최신 코드 기준인ic_bar_bell_colored를 유지했다.rg -n "ZStack|overlay|Color\\.clear|backgroundProgress|CreatorChannelTitleBar|CreatorChannelHeaderSection|CreatorChannelTabBar|CreatorChannelHomeView|CreatorChannelTalkActionSection|CreatorChannelCurrentLiveSection|CreatorChannelLatestAudioSection|CreatorChannelDonationSection|CreatorChannelNoticeSection|CreatorChannelScheduleSection|CreatorChannelAudioSection|CreatorChannelSeriesSection|CreatorChannelCommunitySection|CreatorChannelFanTalkSection|CreatorChannelIntroduceSection|CreatorChannelActivitySection|CreatorChannelSnsSection" ...와rg -n "화보|photo|ic_new_dm|DM|ic_new_talk|ic_sns_|ic_new_bar_back|ic_new_follow|ic_new_following|ic_new_more|ic_bar_bell|ic_bar_bell_colored|creatorFollow|follow: true, notify: true|follow: false, notify: false|follow: true, notify: false|onTapNotify|onTapUnnotify|ZStack|overlay|Color\\.clear|isApiFailedPlaceholderVisible|countryCode|auth == false" ...로 성공 기준을 회귀 점검했고, 신규 CreatorChannel Swift 파일은project.pbxproj의 Sources phase에 포함되어 있음을 확인했다.xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build는BUILD SUCCEEDED로 완료됐다.