223 lines
17 KiB
Markdown
223 lines
17 KiB
Markdown
# 크리에이터 채널 커뮤니티 탭 구현 계획
|
|
|
|
## 기준 문서
|
|
|
|
- PRD: `docs/20260705_크리에이터_채널_커뮤니티_탭/prd.md`
|
|
- 기존 오디오 탭 PRD: `docs/20260704_크리에이터_채널_오디오_탭/prd.md`
|
|
- 기존 팬Talk 탭 PRD: `docs/20260704_크리에이터_채널_팬Talk_탭/prd.md`
|
|
- 기존 커뮤니티 그리드/리스트 전환 계획: `docs/plan-task/20260305_크리에이터커뮤니티전체보기그리드리스트전환구현.md`
|
|
- 코드 스타일: `docs/agent-guides/code-style.md`
|
|
- 빌드/검증: `docs/agent-guides/build-test-verification.md`
|
|
- Figma 전체 리스트형: `290:9061`, `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-9061&m=dev`
|
|
- Figma 전체 썸네일형: `290:9073`, `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-9073&m=dev`
|
|
- Figma 전체 리스트형 + 본인 채널: `665:19021`, `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-19021&m=dev`
|
|
- Figma 전체 썸네일형 + 본인 채널: Figma 설명 기준, 썸네일 UI는 `290:9073`과 동일하고 하단 고정 `커뮤니티 글 올리기` 버튼을 표시한다.
|
|
- Figma 유료 미구매 게시글: `290:9066`, `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-9066&m=dev`
|
|
- Figma 유료 금액 우측 상단 표시: `665:19024`, `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-19024&m=dev`
|
|
- Figma Empty: `290:8994`, `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-8994&m=dev`
|
|
|
|
## 구현 원칙
|
|
|
|
- 기존 `CreatorChannelView`의 공통 shell, header, sticky tab-bar, title bar 동작은 유지한다.
|
|
- `CreatorChannelTab.community` 콘텐츠만 신규 `CreatorChannelCommunityTabView`로 교체한다.
|
|
- 커뮤니티 탭 API는 V2 신규 endpoint를 사용한다.
|
|
- 좋아요, 댓글 sheet, 구매 dialog, 신고, 수정, 삭제, 고정, 오디오 재생은 기존 커뮤니티 구현 흐름을 가능한 한 재사용한다.
|
|
- 리스트형/썸네일형 토글은 API 재호출 없이 현재 로드된 목록만 재배치한다.
|
|
- 게시글 상세 화면은 후속 범위이므로 item tap 상세 이동은 연결하지 않는다.
|
|
- GIF는 정지 이미지로 변환하지 않고 재생 가능한 이미지 컴포넌트를 사용한다.
|
|
|
|
## 주요 대상 파일
|
|
|
|
### 생성
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Models/CreatorChannelCommunityTabResponse.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Repository/CreatorChannelCommunityApi.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Repository/CreatorChannelCommunityRepository.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityViewModel.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityViewModeBar.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityGridItem.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityUploadButton.swift`
|
|
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityEmptyView.swift`
|
|
|
|
### 수정
|
|
- `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift`
|
|
- `SodaLive/Sources/I18n/I18n.swift`
|
|
- 필요 시 `SodaLive.xcodeproj/project.pbxproj`
|
|
|
|
### 확인/재사용
|
|
- `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllView.swift`
|
|
- `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllItemView.swift`
|
|
- `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllViewModel.swift`
|
|
- `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Player/CreatorCommunityMediaPlayerManager.swift`
|
|
- `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityRepository.swift`
|
|
- `SodaLive/Sources/Dialog/CommunityPostPurchaseDialog.swift`
|
|
|
|
## TASK 체크리스트
|
|
|
|
### Phase 1: 문서와 API 모델
|
|
|
|
- [x] **Task 1.1: PRD와 계획 문서 생성**
|
|
- 대상 파일:
|
|
- 생성: `docs/20260705_크리에이터_채널_커뮤니티_탭/prd.md`
|
|
- 생성: `docs/20260705_크리에이터_채널_커뮤니티_탭/plan-task.md`
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "290:9061|290:9073|665:19021|290:9066|665:19024|290:8994|CreatorChannelCommunityTabResponse" docs/20260705_크리에이터_채널_커뮤니티_탭`
|
|
- 기대 결과: 구현할 UI의 Figma URL과 응답 모델 요구사항이 문서에 기록된다.
|
|
|
|
- [x] **Task 1.2: 커뮤니티 탭 Response model 생성**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Models/CreatorChannelCommunityTabResponse.swift`
|
|
- 작업 내용:
|
|
- `CreatorChannelCommunityTabResponse`와 `CreatorChannelCommunityPostResponse`를 `Decodable`로 생성한다.
|
|
- Kotlin `Long` 필드는 Swift `Int`로 선언한다.
|
|
- `creatorProfileUrl`, `existOrdered`, `isPinned`를 포함한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "struct CreatorChannelCommunityTabResponse|communityPostCount|communityPosts|hasNext|struct CreatorChannelCommunityPostResponse|creatorProfileUrl|existOrdered|isPinned" SodaLive/Sources/V2/CreatorChannel/Community/Models/CreatorChannelCommunityTabResponse.swift`
|
|
|
|
### Phase 2: API, Repository, ViewModel
|
|
|
|
- [x] **Task 2.1: 커뮤니티 탭 API endpoint 생성**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Repository/CreatorChannelCommunityApi.swift`
|
|
- 작업 내용:
|
|
- `CreatorChannelCommunityApi.getCommunity(creatorId:page:size:)`를 만든다.
|
|
- path는 `/api/v2/creator-channels/{creatorId}/community`로 구성한다.
|
|
- query는 `page`, `size`를 `URLEncoding.queryString`으로 전송한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityApi|getCommunity|/api/v2/creator-channels/|/community|page|size|URLEncoding.queryString" SodaLive/Sources/V2/CreatorChannel/Community/Repository/CreatorChannelCommunityApi.swift`
|
|
|
|
- [x] **Task 2.2: 커뮤니티 탭 Repository 생성**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Repository/CreatorChannelCommunityRepository.swift`
|
|
- 작업 내용:
|
|
- `MoyaProvider<CreatorChannelCommunityApi>`를 사용하는 `getCommunity(...)` publisher를 제공한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityRepository|MoyaProvider<CreatorChannelCommunityApi>|AnyPublisher<Response, MoyaError>|getCommunity" SodaLive/Sources/V2/CreatorChannel/Community/Repository/CreatorChannelCommunityRepository.swift`
|
|
|
|
- [x] **Task 2.3: 커뮤니티 탭 ViewModel 생성**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityViewModel.swift`
|
|
- 작업 내용:
|
|
- 상태는 loading, response, `communityPosts`, view mode, page, size, hasNext, hasLoaded, error toast, 선택 post id/price/action 상태를 둔다.
|
|
- 첫 페이지 조회, 다음 페이지 조회, 새로고침, view mode 토글을 제공한다.
|
|
- `communityPostCount`는 sort-bar 표시용 computed property로 제공한다.
|
|
- 유료 미구매 판정 helper를 제공한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityViewModel|fetchFirstPage|fetchNextPageIfNeeded|toggleViewMode|communityPostCount|hasNext|page|size|isPaidLocked" SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityViewModel.swift`
|
|
|
|
### Phase 3: 리스트형/썸네일형 UI
|
|
|
|
- [x] **Task 3.1: 리스트형/썸네일형 토글 bar 구현**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityViewModeBar.swift`
|
|
- 수정: `SodaLive/Sources/I18n/I18n.swift`
|
|
- 작업 내용:
|
|
- 좌측에는 `전체 {communityPostCount}`를 표시한다.
|
|
- 우측 버튼은 리스트형/썸네일형 문구와 `ic_new_list` / `ic_new_grid` 아이콘을 표시한다.
|
|
- 정렬 popup이나 `ContentSort`는 사용하지 않는다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityViewModeBar|communityPostCount|ic_new_list|ic_new_grid|listView|thumbnailView" SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityViewModeBar.swift SodaLive/Sources/I18n/I18n.swift`
|
|
|
|
- [x] **Task 3.2: 리스트형 item 구현**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift`
|
|
- 작업 내용:
|
|
- Figma `290:9061`, `665:19021`, `290:9066`, `665:19024` 기준으로 작성자, 시간, 본문, 이미지/GIF, 오디오 재생 버튼, 가격, 더보기, 좋아요, 댓글 표시를 구성한다.
|
|
- 반응 정보는 댓글 아이콘/댓글 수를 먼저, 좋아요 아이콘/좋아요 수를 뒤에 표시한다.
|
|
- `isCommentAvailable == false`이면 댓글 영역을 숨긴다.
|
|
- 유료 미구매 상태이면 회색 `RoundedRectangle`과 가격 UI를 표시하고 오디오 재생 버튼을 숨긴다.
|
|
- `imageUrl == nil`이면 유/무료 관계없이 이미지 영역을 표시하지 않는다.
|
|
- GIF 재생은 `WebImage` 등 기존 재생 가능한 이미지 컴포넌트를 우선 사용한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityListItem|creatorProfileUrl|isCommentAvailable|RoundedRectangle|audioUrl|CommunityPostPurchase|isPinned|existOrdered" SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift`
|
|
|
|
- [x] **Task 3.3: 썸네일형 grid item 구현**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityGridItem.swift`
|
|
- 작업 내용:
|
|
- Figma `290:9073` 기준 3열 grid item을 만든다.
|
|
- 이미지/GIF가 있으면 정방형으로 표시한다.
|
|
- `imageUrl == nil`이면 유/무료 관계없이 기존 커뮤니티 전체보기 fallback처럼 글 일부를 표시한다.
|
|
- 유료 미구매 상태의 가격 UI는 중앙형으로 표시한다.
|
|
- 고정 표시는 별도로 분리한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityGridItem|aspectRatio\\(1|fallbackText|isPaidLocked|isPinned|WebImage|ic_pin" SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityGridItem.swift`
|
|
|
|
- [x] **Task 3.4: Empty view 구현**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityEmptyView.swift`
|
|
- 수정: `SodaLive/Sources/I18n/I18n.swift`
|
|
- 작업 내용:
|
|
- `communityPostCount == 0`일 때 Figma `290:8994` 기준 empty view를 만든다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityEmptyView|communityEmpty|290:8994" SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityEmptyView.swift SodaLive/Sources/I18n/I18n.swift docs/20260705_크리에이터_채널_커뮤니티_탭`
|
|
|
|
### Phase 4: 액션 재사용과 본인 채널 CTA
|
|
|
|
- [x] **Task 4.1: 커뮤니티 탭 화면 조립**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift`
|
|
- 작업 내용:
|
|
- 첫 진입 시 `fetchFirstPage(creatorId:)`를 호출한다.
|
|
- view mode에 따라 list 또는 grid를 표시한다.
|
|
- 마지막 item 노출 시 `fetchNextPageIfNeeded`로 append한다.
|
|
- 댓글 sheet, 구매 dialog, 신고 view, 삭제 confirm dialog, 더보기 menu 상태를 연결한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityTabView|CreatorChannelCommunityViewModeBar|CreatorChannelCommunityListItem|CreatorChannelCommunityGridItem|fetchFirstPage|fetchNextPageIfNeeded|CommunityPostPurchaseDialog|CreatorCommunityCommentListView" SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift`
|
|
|
|
- [x] **Task 4.2: 기존 커뮤니티 mutation/action 흐름 재사용**
|
|
- 대상 파일:
|
|
- 수정: `SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityViewModel.swift`
|
|
- 확인: `SodaLive/Sources/Explorer/Profile/CreatorCommunity/CreatorCommunityRepository.swift`
|
|
- 확인: `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/CreatorCommunityAllViewModel.swift`
|
|
- 작업 내용:
|
|
- 좋아요, 구매, 신고, 삭제, 고정 API 호출은 기존 repository와 request 모델을 재사용한다.
|
|
- 성공 후 첫 페이지를 다시 조회한다.
|
|
- 수정은 기존 `AppState.shared.setAppStep(step: .creatorCommunityModify(...))`로 이동한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "communityPostLike|purchaseCommunityPost|ReportType.COMMUNITY_POST|deleteCommunityPost|updateCommunityPostFixed|creatorCommunityModify" SodaLive/Sources/V2/CreatorChannel/Community SodaLive/Sources/Explorer/Profile/CreatorCommunity`
|
|
|
|
- [x] **Task 4.3: 본인 채널 업로드 버튼 구현**
|
|
- 대상 파일:
|
|
- 생성: `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityUploadButton.swift`
|
|
- 작업 내용:
|
|
- 본인 채널 하단 고정 `커뮤니티 글 올리기` 버튼을 만든다.
|
|
- 버튼 문구는 기존 다국어 문구를 우선 재사용한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityUploadButton|uploadCommunityPost|frame\\(maxWidth: \\.infinity|Capsule" SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityUploadButton.swift`
|
|
|
|
### Phase 5: CreatorChannelView 연결과 검증
|
|
|
|
- [x] **Task 5.1: 커뮤니티 탭 콘텐츠와 CTA 연결**
|
|
- 대상 파일:
|
|
- 수정: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift`
|
|
- 작업 내용:
|
|
- `CreatorChannelTab.community` 임시 화면을 `CreatorChannelCommunityTabView`로 교체한다.
|
|
- 본인 채널이고 커뮤니티 탭이면 `CreatorChannelCommunityUploadButton`을 하단 고정으로 표시한다.
|
|
- 작성 성공 후 홈과 커뮤니티 탭 첫 페이지를 갱신할 수 있도록 closure를 연결한다.
|
|
- 검증 기준:
|
|
- 실행 명령: `rg "CreatorChannelCommunityTabView|CreatorChannelCommunityUploadButton|viewModel\\.selectedTab == \\.community|showCommunityWrite" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift`
|
|
|
|
- [x] **Task 5.2: 프로젝트 파일 등록과 정적 검증**
|
|
- 대상 파일:
|
|
- 확인/수정: `SodaLive.xcodeproj/project.pbxproj`
|
|
- 검증 기준:
|
|
- 실행 명령: `git diff --check -- docs/20260705_크리에이터_채널_커뮤니티_탭 SodaLive/Sources/V2/CreatorChannel SodaLive/Sources/I18n/I18n.swift SodaLive.xcodeproj/project.pbxproj`
|
|
- 기대 결과: 공백 오류 없이 성공한다.
|
|
- 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj`
|
|
- 기대 결과: `OK`가 출력된다.
|
|
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
|
|
- 기대 결과: 빌드 성공.
|
|
|
|
## 검증 기록
|
|
|
|
- 2026-07-05: `docs/agent-guides/documentation-policy.md`를 확인해 신규 문서 경로를 `docs/20260705_크리에이터_채널_커뮤니티_탭/prd.md`, `docs/20260705_크리에이터_채널_커뮤니티_탭/plan-task.md`로 결정했다.
|
|
- 2026-07-05: 기존 `docs/20260704_크리에이터_채널_오디오_탭`, `docs/20260704_크리에이터_채널_팬Talk_탭`, `docs/plan-task/20260305_크리에이터커뮤니티전체보기그리드리스트전환구현.md`를 확인해 문서 형식과 구현 계획 단위를 맞췄다.
|
|
- 2026-07-05: `CreatorChannelView`, 기존 `CreatorCommunityAllView`, `CreatorCommunityAllItemView`, `CreatorCommunityAllViewModel`, `GetCommunityPostListResponse`를 확인해 V2 커뮤니티 탭 전용 신규 파일과 기존 커뮤니티 액션 재사용 범위를 정했다.
|
|
- 2026-07-05: 사용자 추가 확인으로 Empty Figma `290:8994`, 썸네일형 유료 미구매 가격 UI 중앙형, `imageUrl == nil`일 때 유/무료 관계없이 이미지 미표시 규칙을 반영했다.
|
|
- 2026-07-05: `CreatorChannelCommunityTabResponse`, `CreatorChannelCommunityApi`, `CreatorChannelCommunityRepository`, `CreatorChannelCommunityViewModel`을 생성하고 V2 커뮤니티 탭 목록 조회, 페이지네이션, 리스트/썸네일 전환, 기존 커뮤니티 mutation/action 재사용 흐름을 연결했다.
|
|
- 2026-07-05: `CreatorChannelCommunityTabView`와 하위 컴포넌트 5개를 생성해 리스트형/썸네일형/Empty/본인 채널 업로드 CTA를 연결하고, `CreatorChannelView`의 `.community` 탭 임시 화면을 신규 탭으로 교체했다.
|
|
- 2026-07-05: `I18n.CreatorChannelCommunity` 문구를 추가하고, `ic_new_grid`, `ic_new_list` 신규 asset을 사용하는 view mode toggle을 구현했다.
|
|
- 2026-07-05: `git diff --check`, `plutil -lint SodaLive.xcodeproj/project.pbxproj`, `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`로 정적 검증과 Debug 빌드를 확인했다.
|