Files
sodalive-ios/docs/20260704_크리에이터_채널_후원_탭/plan-task.md

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은 기존 LiveRoomDonationDialogViewChannelDonationViewModel.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_donation icon-only 후원하기 버튼을 표시한다.
  • CreatorChannelDonationResponse는 홈 탭 모델의 기존 타입을 재사용한다.
  • 후원 item UI는 홈 탭과 후원 탭에서 같은 표시 규칙을 갖도록 공용화한다.
  • 서버 응답에 없는 secret 여부는 클라이언트에서 추론하지 않는다.

주요 대상 파일

생성

  • SodaLive/Sources/V2/CreatorChannel/Donation/Models/CreatorChannelDonationTabResponse.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationApi.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/Repository/CreatorChannelDonationRepository.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationViewModel.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/CreatorChannelDonationTabView.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationRankingSection.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationCountBar.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationEmptyView.swift
  • SodaLive/Sources/V2/CreatorChannel/Donation/Components/CreatorChannelDonationFloatingButton.swift

수정

  • SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift
  • SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelDonationSection.swift
  • SodaLive/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
    • 작업 내용:
      • CreatorChannelDonationTabResponseMemberDonationRankingResponseDecodable로 생성한다.
      • 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은 포함하지 않는다.
    • 검증 기준:
      • 실행 명령: 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 동작을 유지한다.
    • 검증 기준:
      • 실행 명령: 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.soda400 capsule button을 표시한다.
      • tap action은 부모에서 주입한다.
    • 검증 기준:
      • 실행 명령: 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_contextget_screenshot으로 290:9093, 290:9097을 확인했다.

  • 2026-07-04: rgsed로 기존 CreatorChannelView, CreatorChannelDonationSection, CreatorChannelSortBar, ChannelDonationViewModel, ChannelDonationAllView 관련 파일을 확인했다.

  • 2026-07-04: 사용자 요청에 따라 랭킹 전체보기는 기존 UserProfileDonationAllView로 이동하도록 범위를 보완했다. UserProfileDonationAllViewAppStep.userProfileDonationAll(userId:) 기존 라우팅을 확인했다.

  • 2026-07-04: Figma get_design_contextget_screenshot으로 empty view 290:9009를 확인하고, rankings.isEmpty && donationCount == 0 조건과 empty 내부 후원하기 버튼 요구사항을 반영했다.

  • 2026-07-04: 사용자 요청에 따라 donationCount == 0 empty 상태에서는 하단 고정 후원하기 버튼을 숨기고, donationCount != 0 || !rankings.isEmpty일 때만 홈 탭 plus button 위치에 ic_new_donation icon-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명씩 표시하도록 범위를 보완했다.