17 KiB
크리에이터 채널 후원 탭 구현 계획
기준 문서
- PRD:
docs/20260704_크리에이터_채널_후원_탭/prd.md - 기존 크리에이터 채널 홈 PRD:
docs/20260701_크리에이터_채널_홈/prd.md - 기존 크리에이터 채널 홈 구현 계획:
docs/20260701_크리에이터_채널_홈/plan-task.md - 기존 크리에이터 채널 오디오 탭 구현 계획:
docs/20260704_크리에이터_채널_오디오_탭/plan-task.md - 코드 스타일:
docs/agent-guides/code-style.md - 빌드/검증:
docs/agent-guides/build-test-verification.md - Figma 전체 화면:
290:9093,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-9093&m=dev - Figma 후원 랭킹 섹션:
290:9097,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-9097&m=dev - Figma 후원 랭킹 최신 섹션:
665:19056,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=665-19056&m=dev - Figma Empty:
290:9009,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-9009&m=dev
구현 원칙
- 기존
CreatorChannelView의 공통 shell, header, sticky tab-bar, title bar 동작은 유지한다. CreatorChannelTab.donation콘텐츠만 신규CreatorChannelDonationTabView로 교체한다.- 후원 mutation은 기존
LiveRoomDonationDialogView와ChannelDonationViewModel.postChannelDonation흐름을 재사용한다. - 후원 성공 후 홈 데이터와 후원 탭 첫 페이지를 모두 다시 조회한다.
- 후원 랭킹은 최대 8명, 한 줄에 4명씩 표시하고
전체보기는 기존AppStep.userProfileDonationAll(userId:)로 이동한다. - sort-bar는 정렬 없이
전체 {donationCount}만 표시한다. rankings.isEmpty && donationCount == 0이면 empty view 내부 후원하기 버튼만 표시하고 하단 고정 후원하기 버튼은 숨긴다.- 단, 내 채널인 경우 empty view 내부 후원하기 버튼과 우측하단 후원하기 버튼을 모두 표시하지 않는다.
donationCount != 0 || !rankings.isEmpty이면 홈 탭 plus button 위치에ic_new_donationicon-only 후원하기 버튼을 표시한다.CreatorChannelDonationResponse는 홈 탭 모델의 기존 타입을 재사용한다.- 후원 item UI는 홈 탭과 후원 탭에서 같은 표시 규칙을 갖도록 공용화한다.
- 서버 응답에 없는 secret 여부는 클라이언트에서 추론하지 않는다.
주요 대상 파일
생성
SodaLive/Sources/V2/CreatorChannel/Donation/Models/CreatorChannelDonationTabResponse.swiftSodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationApi.swiftSodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationRepository.swiftSodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationViewModel.swiftSodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationTabView.swiftSodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationRankingSection.swiftSodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCountBar.swiftSodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationEmptyView.swiftSodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationFloatingButton.swift
수정
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swiftSodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swiftSodaLive/Sources/I18n/I18n.swift- 필요 시
SodaLive.xcodeproj/project.pbxproj
TASK 체크리스트
Phase 1: 문서와 API 모델
-
Task 1.1: PRD와 계획 문서 생성
- 대상 파일:
- 생성:
docs/20260704_크리에이터_채널_후원_탭/prd.md - 생성:
docs/20260704_크리에이터_채널_후원_탭/plan-task.md
- 생성:
- 검증 기준:
- 실행 명령:
rg "290:9093|290:9097|290:9009|CreatorChannelDonationTabResponse|MemberDonationRankingResponse|/api/v2/creator-channels/.*/donations|UserProfileDonationAllView" docs/20260704_크리에이터_채널_후원_탭 - 기대 결과: Figma URL, 응답 모델, API path 요구사항이 문서에 기록된다.
- 실행 명령:
- 대상 파일:
-
Task 1.2: 후원 탭 Response model 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/Models/CreatorChannelDonationTabResponse.swift
- 생성:
- 작업 내용:
CreatorChannelDonationTabResponse와MemberDonationRankingResponse를Decodable로 생성한다.CreatorChannelDonationTabResponse.donations는 기존[CreatorChannelDonationResponse]를 사용한다.
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelDonationTabResponse|donationCount|rankings|donations|hasNext|struct MemberDonationRankingResponse|donationCan" SodaLive/Sources/V2/CreatorChannel/Donation/Models/CreatorChannelDonationTabResponse.swift
- 실행 명령:
- 대상 파일:
Phase 2: API, Repository, ViewModel
-
Task 2.1: 후원 탭 API endpoint 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationApi.swift
- 생성:
- 작업 내용:
CreatorChannelDonationApi.getDonations(creatorId:page:size:)를 만든다.- path는
/api/v2/creator-channels/{creatorId}/donations로 구성한다. - query parameter는
page,size만 보낸다.
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationApi|getDonations|/api/v2/creator-channels/|/donations|page|size|URLEncoding.queryString" SodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationApi.swift
- 실행 명령:
- 대상 파일:
-
Task 2.2: 후원 탭 Repository 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationRepository.swift
- 생성:
- 작업 내용:
MoyaProvider<CreatorChannelDonationApi>를 사용하는getDonations(...)publisher를 제공한다.
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationRepository|MoyaProvider<CreatorChannelDonationApi>|AnyPublisher<Response, MoyaError>|getDonations" SodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationRepository.swift
- 실행 명령:
- 대상 파일:
-
Task 2.3: 후원 탭 ViewModel 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationViewModel.swift
- 생성:
- 작업 내용:
- 상태는 loading, loadingNextPage, response, rankings, donations, page, size, hasNext, hasLoaded, error toast를 둔다.
fetchFirstPage(creatorId:)는page=0,size=20으로 조회한다.fetchNextPageIfNeeded(creatorId:currentItem:)는 마지막 item 기준으로 다음 페이지를 조회한다.- 첫 페이지는 목록 교체, 다음 페이지는 append한다.
- 최신 요청만 반영하도록
latestRequestId패턴을 사용한다.
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationViewModel|fetchFirstPage|fetchNextPageIfNeeded|isLoadingNextPage|latestRequestId|rankings|donations|hasNext" SodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationViewModel.swift
- 실행 명령:
- 대상 파일:
Phase 3: Figma 섹션별 UI
-
Task 3.1: 후원 count bar 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCountBar.swift
- 생성:
- 작업 내용:
- Figma sort-bar 기준으로 높이 52pt, 좌측
전체 {donationCount}만 표시한다. - 정렬 버튼/아이콘/action은 포함하지 않는다.
- Figma sort-bar 기준으로 높이 52pt, 좌측
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationCountBar|donationCount|전체|frame\\(height: 52\\)|ic_new_sort|selectedSort" SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCountBar.swift - 기대 결과: count bar 구현이 확인되고 정렬 관련 문자열은 없어야 한다.
- 실행 명령:
- 대상 파일:
-
Task 3.2: 후원 랭킹 섹션 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationRankingSection.swift
- 생성:
- 작업 내용:
rankings가 비어 있으면 섹션을 숨긴다.후원 랭킹title,Color.gray900카드, 75pt 원형 프로필, 닉네임, rank number overlay를 구현한다.- 후원 랭킹 item은 최대 8명만 표시하고 한 줄에 4명씩 표시한다.
- Figma
전체보기버튼을 표시하고 tap action은 부모에서 주입한다. - 부모 action은 기존
AppStep.userProfileDonationAll(userId: creatorId)이동으로 연결한다.
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationRankingSection|후원 랭킹|MemberDonationRankingResponse|rank \\+ 1|75|DownsampledKFImage|전체보기|onTapViewAll" SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationRankingSection.swift
- 실행 명령:
- 대상 파일:
-
Task 3.3: 후원 item 공용화
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift - 생성 또는 이동:
SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCard.swift
- 수정:
- 작업 내용:
- 홈 탭 내부 private
CreatorChannelDonationCard를 후원 탭에서도 사용할 수 있는 공용 컴포넌트로 분리한다. - 기존 홈 탭 표시 규칙과 preview 동작을 유지한다.
- 홈 탭 내부 private
- 검증 기준:
- 실행 명령:
rg "struct CreatorChannelDonationCard|messageText|tierColor|relativeTimeText|CreatorChannelDonationSection" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift SodaLive/Sources/V2/CreatorChannel/Donation/Components
- 실행 명령:
- 대상 파일:
-
Task 3.4: Empty view 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationEmptyView.swift
- 생성:
- 작업 내용:
- Figma
290:9009기준으로아직 후원이 없습니다.\n처음으로 크리에이터를 후원해 보세요!문구를 표시한다. ic_new_donation아이콘과후원하기텍스트가 있는Color.soda400capsule button을 표시한다.- tap action은 부모에서 주입한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationEmptyView|아직 후원이 없습니다|처음으로 크리에이터를 후원해 보세요|ic_new_donation|Color\\.soda400|후원하기|onTapDonate" SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationEmptyView.swift
- 실행 명령:
- 대상 파일:
-
Task 3.5: 후원 탭 본문 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationTabView.swift
- 생성:
- 작업 내용:
- count bar, ranking section, donation list를 순서대로 배치한다.
- 첫 진입 시
fetchFirstPage(creatorId:)를 호출한다. - 마지막 donation item 노출 시
fetchNextPageIfNeeded를 호출한다. rankings.isEmpty && donationCount == 0이면CreatorChannelDonationEmptyView를 표시한다.- 내 채널인 경우 empty view 내부 후원하기 버튼을 숨긴다.
CreatorChannelDonationRankingSection의 전체보기 action은 부모로 전달한다.
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationTabView|CreatorChannelDonationCountBar|CreatorChannelDonationRankingSection|CreatorChannelDonationEmptyView|CreatorChannelDonationCard|fetchFirstPage|fetchNextPageIfNeeded|onTapViewAll|onTapDonate" SodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationTabView.swift
- 실행 명령:
- 대상 파일:
-
Task 3.6: 후원하기 floating button 구현
- 대상 파일:
- 생성:
SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationFloatingButton.swift
- 생성:
- 작업 내용:
- 홈 탭 plus button 위치에 표시할 후원하기 floating button을 구현한다.
- 버튼은
Color.soda400배경과ic_new_donation아이콘만 표시하고 텍스트는 표시하지 않는다. - tap action은 부모에서 주입한다.
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationFloatingButton|ic_new_donation|Color\\.soda400|Capsule|action" SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationFloatingButton.swift - 실행 명령:
rg "Text\\(" SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationFloatingButton.swift - 기대 결과: 첫 번째 검색으로 icon-only floating button 구현이 확인되고, 두 번째 검색은 결과가 없어야 한다.
- 실행 명령:
- 대상 파일:
Phase 4: CreatorChannelView 연결과 후원 성공 갱신
-
Task 4.1: 후원 탭 콘텐츠 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift
- 수정:
- 작업 내용:
@StateObject로 후원 탭 ViewModel을 보유한다.selectedTabContent에서.donation일 때CreatorChannelDonationTabView를 표시한다.- 랭킹
전체보기action은AppState.shared.setAppStep(step: .userProfileDonationAll(userId: creatorId))로 연결한다. - 후원하기 floating button은
selectedTab == .donation이고 내 채널이 아니며donationCount != 0 || !rankings.isEmpty일 때만 표시한다. rankings.isEmpty && donationCount == 0이면 empty view 내부 버튼만 사용하고 floating button은 숨긴다.- 내 채널인 경우 empty view 내부 후원하기 버튼과 floating button을 모두 숨긴다.
- 검증 기준:
- 실행 명령:
rg "CreatorChannelDonationViewModel|CreatorChannelDonationTabView|viewModel\\.selectedTab == \\.donation|CreatorChannelDonationFloatingButton|showDonationDialog|userProfileDonationAll|donationCount|rankings\\.isEmpty" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift
- 실행 명령:
- 대상 파일:
-
Task 4.2: 후원 성공 후 홈/후원 탭 갱신
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift
- 수정:
- 작업 내용:
ChannelDonationViewModel.postChannelDonation성공 콜백에서viewModel.fetchHome(creatorId:)와donationViewModel.fetchFirstPage(creatorId:)를 호출한다.
- 검증 기준:
- 실행 명령:
rg "postChannelDonation|fetchHome\\(creatorId: creatorId\\)|donationViewModel\\.fetchFirstPage\\(creatorId: creatorId\\)" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift
- 실행 명령:
- 대상 파일:
Phase 5: 프로젝트 등록과 검증
-
Task 5.1: 프로젝트 파일 등록과 정적 검증
- 대상 파일:
- 확인/수정:
SodaLive.xcodeproj/project.pbxproj
- 확인/수정:
- 검증 기준:
- 실행 명령:
git diff --check -- docs/20260704_크리에이터_채널_후원_탭 SodaLive/Sources/V2/CreatorChannel SodaLive/Sources/I18n/I18n.swift SodaLive.xcodeproj/project.pbxproj - 기대 결과: 공백 오류 없이 성공한다.
- 실행 명령:
plutil -lint SodaLive.xcodeproj/project.pbxproj - 기대 결과:
OK출력.
- 실행 명령:
- 대상 파일:
-
Task 5.2: 빌드 검증
- 대상 파일:
- 확인:
SodaLive.xcworkspace - 확인:
SodaLive.xcodeproj
- 확인:
- 검증 기준:
- 실행 명령:
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build - 기대 결과:
BUILD SUCCEEDED. - workspace 인식 실패 등 환경 문제가 있으면
xcodebuild -project "SodaLive.xcodeproj" -scheme "SodaLive-dev" -configuration Debug build를 대체 검증으로 실행하고 실패 원인을 검증 기록에 남긴다.
- 실행 명령:
- 대상 파일:
검증 기록
-
2026-07-04: Figma
get_design_context와get_screenshot으로290:9093,290:9097을 확인했다. -
2026-07-04:
rg와sed로 기존CreatorChannelView,CreatorChannelDonationSection,CreatorChannelSortBar,ChannelDonationViewModel,ChannelDonationAllView관련 파일을 확인했다. -
2026-07-04: 사용자 요청에 따라 랭킹
전체보기는 기존UserProfileDonationAllView로 이동하도록 범위를 보완했다.UserProfileDonationAllView와AppStep.userProfileDonationAll(userId:)기존 라우팅을 확인했다. -
2026-07-04: Figma
get_design_context와get_screenshot으로 empty view290:9009를 확인하고,rankings.isEmpty && donationCount == 0조건과 empty 내부 후원하기 버튼 요구사항을 반영했다. -
2026-07-04: 사용자 요청에 따라
donationCount == 0empty 상태에서는 하단 고정 후원하기 버튼을 숨기고,donationCount != 0 || !rankings.isEmpty일 때만 홈 탭 plus button 위치에ic_new_donationicon-only 후원하기 버튼을 표시하도록 범위를 보완했다. -
2026-07-04: Task 1.2~5.1 구현 완료. 신규
Donation/**Swift 파일과 공용CreatorChannelDonationCard,CreatorChannelView연결,project.pbxproj등록을 수행했고 문서의rg,plutil,git diff --check검증을 실행했다. -
2026-07-04:
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build를 실행해BUILD SUCCEEDED를 확인했다. -
2026-07-04: 사용자 요청에 따라 내 채널인 경우 후원 탭 empty view 내부 후원하기 버튼과 우측하단 icon-only 후원하기 버튼을 모두 표시하지 않도록 범위를 보완했다.
-
2026-07-04: 사용자 요청에 따라 후원 랭킹은 최대 8명만, 한 줄에 4명씩 표시하도록 범위를 보완했다.
-
2026-07-08: 사용자 요청에 따라 공용 후원 item의
can >= 501상단 영역에서nickname은 white, 상대 시간은gray100으로 표시하고, 그 외 후원can구간의 글자색은 기존 색상을 유지하도록 기록했다.