# 메인 홈 추천 탭 UI와 API 연동 구현 계획 ## 기준 문서 - PRD: `docs/20260602_메인_홈_추천_UI_API_연동/prd.md` - Figma 추천 화면: `24:5514` - Figma FeedCommunityView 유료 미구매: `309:19774` - Figma FeedCommunityView 유료 구매함 또는 무료: `309:19775` - 코드 스타일: `docs/agent-guides/code-style.md` - 빌드/검증: `docs/agent-guides/build-test-verification.md` ## 재분류 원칙 - 2026-06-26 기준으로 기존 Phase와 완료 체크 상태는 구현 순서 판단에 사용하지 않는다. - 이전 검증 기록은 하단에 보존하되, 새 체크리스트는 신규 PRD 요구사항 기준으로 다시 작성한다. - 화면 UI는 섹션당 하나의 Phase로 나누어 작게 작업한다. - `MainHomeView`는 홈 상단 공통 shell과 추천/랭킹/팔로잉 탭 전환만 담당한다. - 추천/랭킹/팔로잉 탭 아래 콘텐츠는 각각 `Recommendation`, `Ranking`, `Following` 하위 폴더에 별도 View로 배치한다. - 기존에 이미 생성된 widget과 파일이 있으면 새로 만들지 않고 확인/보완한다. - `추천 필모그래피`, `또 다른 모습`, 사업자 정보 외 추가 하단 정보 섹션은 만들지 않는다. - 기존 `SodaLive/Sources/Home/HomeApi.swift`에는 `/api/v2/home/recommendations`를 추가하지 않는다. - 외부 라이브러리는 추가하지 않는다. ## 주요 대상 파일 ### 확인/보완 - `SodaLive/Sources/V2/Main/Home/MainHomeView.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Models/RecommendedActivityType.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Repository/MainHomeRecommendationApi.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Repository/MainHomeRecommendationRepository.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationViewModel.swift` - `SodaLive/Sources/V2/Component/AudioContentCard.swift` - `SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` - `SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift` - `SodaLive/Sources/I18n/I18n.swift` - `SodaLive.xcodeproj/project.pbxproj` ### 생성 후보 없는 경우에만 생성한다. - `SodaLive/Sources/V2/Main/Home/MainHomeView.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeLiveSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeBannerSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeActiveCreatorSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeRecentDebutCreatorSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeFirstAudioContentSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeAiCharacterSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeGenreCreatorSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeCheerCreatorSection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomePopularCommunitySection.swift` - `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeBusinessInfoSection.swift` - `SodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingView.swift` - `SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift` ## TASK 체크리스트 ### Phase 1: 기준 스펙과 기존 구현 점검 - [x] **Task 1.1: 문서/코드 기준점 확인** - 대상 파일: - 확인: `docs/20260602_메인_홈_추천_UI_API_연동/prd.md` - 확인: `SodaLive/Sources/V2/Main/Home/**` - 확인: `SodaLive/Sources/V2/Component/**` - 작업 내용: - PRD의 신규 API 응답 필드와 현재 Swift 모델 필드 차이를 확인한다. - 현재 `SodaLive/Sources/V2/Main/Home` 바로 아래에 있는 추천 전용 파일을 `Recommendation` 하위 폴더로 이동/이름 변경할 대상을 확인한다. - Figma 기준으로 재사용 가능한 기존 widget을 확인한다. - 이미 생성된 파일은 유지하고 필요한 보완만 계획한다. - 검증 기준: - 실행 명령: `find SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Component -maxdepth 4 -type f | sort` - 기대 결과: 현재 생성된 V2 홈/공용 컴포넌트 목록을 확인할 수 있다. - [x] **Task 1.2: 제외 범위 점검** - 대상 파일: - 확인: `SodaLive/Sources/V2/Main/Home/**` - 확인: `SodaLive/Sources/V2/Component/**` - 작업 내용: - `추천 필모그래피`, `또 다른 모습` 섹션 파일이나 View를 만들지 않는다. - Figma URL이나 localhost asset URL이 앱 코드에 직접 들어가지 않도록 확인한다. - 검증 기준: - 실행 명령: `rg "추천 필모그래피|또 다른 모습|figma.com|localhost:3845" SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Component` - 기대 결과: 검색 결과가 없어야 한다. ### Phase 2: 신규 API와 응답 모델 - [x] **Task 2.1: 추천 API endpoint 확인/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Repository/MainHomeRecommendationApi.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Repository/MainHomeRecommendationRepository.swift` - 이동/정리: `SodaLive/Sources/V2/Main/Home/Repository/MainHomeApi.swift` - 이동/정리: `SodaLive/Sources/V2/Main/Home/Repository/MainHomeRepository.swift` - 확인: `SodaLive/Sources/Home/HomeApi.swift` - 작업 내용: - `GET /api/v2/home/recommendations`를 신규 API 타입에만 둔다. - 추천 API 타입/Repository는 `Recommendation/Repository` 아래에 둔다. - 기존 `HomeApi`에는 endpoint를 추가하지 않는다. - 인증 헤더는 기존 token 패턴을 따른다. - 검증 기준: - 실행 명령: `rg "/api/v2/home/recommendations|getRecommendations" SodaLive/Sources/V2/Main/Home/Recommendation/Repository SodaLive/Sources/Home` - 기대 결과: 신규 경로는 `SodaLive/Sources/V2/Main/Home/Recommendation/Repository`에서만 검색된다. - [x] **Task 2.2: 신규 Response 모델 보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` - 이동/정리: `SodaLive/Sources/V2/Main/Home/Models/MainHomeRecommendationResponse.swift` - 작업 내용: - `HomeRecommendationResponse` 필드를 PRD와 맞춘다. - 추천 응답 모델은 `Recommendation/Models` 아래에 둔다. - `banners` 타입은 `RecommendationBannerResponse` 또는 Swift 대응 타입으로 명확히 한다. - `HomeLiveItem.roomId`, `creatorProfileImage`, `HomeActiveCreatorItem.targetId`, `HomeFirstAudioContentItem.price`, `coverImage`, `isPointAvailable`, `HomeAiCharacterItem.totalChatCount`, `originalWorkTitle`, `HomePopularCommunityPostItem.audioUrl` 누락 여부를 확인한다. - 과거 추정 필드는 실제 사용 경로가 없으면 제거하거나 호환 필요 시 명확히 분리한다. - 검증 기준: - 실행 명령: `rg "roomId|creatorProfileImage|targetId|price|coverImage|isPointAvailable|totalChatCount|originalWorkTitle|audioUrl" SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` - 기대 결과: PRD 핵심 필드가 모델에 반영되어야 한다. ### Phase 3: 활동 타입과 I18n - [x] **Task 3.1: RecommendedActivityType 변환 보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Models/RecommendedActivityType.swift` - 이동/정리: `SodaLive/Sources/V2/Main/Home/Models/RecommendedActivityType.swift` - 확인/보완: `SodaLive/Sources/I18n/I18n.swift` - 작업 내용: - `LIVE`, `LIVE_REPLAY`는 `라이브` 계열 문구로 표시한다. - `AUDIO`는 `오디오`, `COMMUNITY`는 `커뮤니티` 계열 문구로 표시한다. - 알 수 없는 값은 서버 코드를 그대로 표시하지 않는다. - ko/en/ja 문구를 I18n에 둔다. - 검증 기준: - 실행 명령: `rg "LIVE_REPLAY|activityLive|activityAudio|activityCommunity|ライブ|オーディオ|コミュニティ" SodaLive/Sources/V2/Main/Home/Recommendation/Models/RecommendedActivityType.swift SodaLive/Sources/I18n/I18n.swift` - 기대 결과: enum 변환과 I18n 문구가 확인된다. ### Phase 4: 추천 데이터 상태 계층 정리 - [x] **Task 4.1: 추천 ViewModel 데이터 로딩 계층 정리** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationViewModel.swift` - 이동/정리: `SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift` - 확인/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Repository/MainHomeRecommendationRepository.swift` - 작업 내용: - 추천 API 로딩/에러/섹션 상태는 `MainHomeRecommendationViewModel`에서 담당한다. - 기존 `MainHomeViewModel`이 추천 전용 상태만 가진다면 `MainHomeRecommendationViewModel`로 이동/이름 변경한다. - 추천 API 응답 데이터가 섹션별 View에서 바로 사용할 수 있는 상태로 노출되는지 확인한다. - UI 섹션 구현은 이 Phase에서 진행하지 않는다. - 검증 기준: - 실행 명령: `rg "final class MainHomeRecommendationViewModel|fetchRecommendations|HomeRecommendationResponse|MainHomeRecommendationRepository|isLoading|errorMessage" SodaLive/Sources/V2/Main/Home` - 기대 결과: 추천 API 로딩/에러/응답 상태가 `MainHomeRecommendationViewModel` 중심으로 정리되어야 한다. ### Phase 5: 추천 상세 진입 데이터/라우팅 guard - [x] **Task 5.1: 추천 탭 상세 진입 guard 적용** - 대상 파일: - 수정: `SodaLive/Sources/V2/Main/MainView.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/MainHomeView.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 확인: `SodaLive/Sources/Main/Home/HomeView.swift` - 확인: `SodaLive/Sources/Home/HomeTabView.swift` - 작업 내용: - 신규 추천 탭의 API 호출과 섹션 노출 자체는 막지 않고, 라이브/크리에이터/오디오 콘텐츠/AI 캐릭터/커뮤니티 등 상세 진입 탭 액션 앞에서 guard를 적용한다. - `MainHomeView`와 `MainHomeRecommendationView`는 직접 로그인/본인인증/민감 콘텐츠 설정 로직을 복사하지 않고, `MainView`에서 전달받은 callback으로 탭 이벤트만 올린다. - `MainView`에 이미 있는 `token`, `auth`, `isShowAuthView`, `isShowAuthConfirmView`, `pendingAction`, `authConfirmDialog`, `authView` 인프라를 재사용한다. - 토큰이 비어 있으면 `AppState.shared.setAppStep(step: .login)`으로 이동한다. - 민감/성인 콘텐츠 진입이 필요한 항목은 한국 사용자이고 `auth == false`이면 `pendingAction`에 원래 이동 액션을 저장하고 `isShowAuthConfirmView = true`로 본인인증 dialog를 띄운다. - 민감 콘텐츠 보기 설정이 꺼져 있으면 `AppState.shared.setPendingContentSettingsGuideMessage(I18n.Settings.adultContentEnableGuide)` 후 `AppState.shared.setAppStep(step: .contentViewSettings)`로 이동한다. - guard 통과 후에만 `liveDetail`, `creatorDetail`, `contentDetail`, `characterDetail` 등 실제 상세 이동을 실행한다. - 라이브 항목에 성인 여부 guard를 적용하려면 `HomeLiveItem` 응답에 `isAdult` 또는 동등한 필드가 필요하므로, 필드가 없으면 서버 필터링 전제인지 확인하고 임의 판단하지 않는다. - 검증 기준: - 실행 명령: `rg "pendingAction|isShowAuthConfirmView|setPendingContentSettingsGuideMessage|adultContentEnableGuide|contentViewSettings|MainHomeView\\(|MainHomeRecommendationView\\(" SodaLive/Sources/V2/Main/MainView.swift SodaLive/Sources/V2/Main/Home` - 기대 결과: 신규 추천 탭 상세 진입 callback이 기존 인증/민감 콘텐츠 guard 인프라를 재사용한다. - 수동 확인: `MainHomeView`, `MainHomeRecommendationView` 내부에 Bootpay 인증 UI를 중복 구현하지 않아야 한다. ### Phase 6: 홈 탭 shell과 탭별 루트 연결 - [x] **Task 6.1: 추천/랭킹/팔로잉 하위 폴더와 루트 View 준비** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingView.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift` - 작업 내용: - 추천 탭 콘텐츠 조립은 `MainHomeRecommendationView`에서 담당한다. - 랭킹/팔로잉 탭은 이번 추천 API 범위 밖이므로 placeholder 또는 최소 루트 View만 준비하고 추천 섹션 코드를 넣지 않는다. - 섹션별 UI 구현은 이후 섹션 UI Phase에서 진행한다. - 검증 기준: - 실행 명령: `find SodaLive/Sources/V2/Main/Home -maxdepth 3 -type f | sort` - 기대 결과: `Recommendation`, `Ranking`, `Following` 하위 폴더의 루트 View 파일이 확인된다. - [x] **Task 6.2: MainHomeView 탭 shell 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/MainHomeView.swift` - 확인: `SodaLive/Sources/V2/Component/HomeTitleBar.swift` - 작업 내용: - `MainHomeView`는 `HomeTitleBar`, 추천/랭킹/팔로잉 상단 탭, 선택된 탭 콘텐츠 조합만 담당한다. - 추천 탭 섹션 조립과 추천 API 호출을 `MainHomeView`에 직접 넣지 않는다. - 하단 `MainTabBarView`는 기존 `MainView` 구조에서 유지하고 `MainHomeView` 내부에 중복 생성하지 않는다. - 검증 기준: - 실행 명령: `rg "struct MainHomeView|HomeTitleBar|MainHomeRecommendationView|MainHomeRankingView|MainHomeFollowingView|MainTabBarView|fetchRecommendations" SodaLive/Sources/V2/Main/Home/MainHomeView.swift SodaLive/Sources/V2/Main/MainView.swift` - 기대 결과: `MainHomeView`는 탭별 루트 View를 조합하고, `fetchRecommendations`를 직접 호출하지 않으며, 탭바 중복 생성은 없어야 한다. - [x] **Task 6.3: MainView 홈 탭 연결** - 대상 파일: - 수정: `SodaLive/Sources/V2/Main/MainView.swift` - 작업 내용: - `.home` 분기에서 placeholder 대신 `MainHomeView()`를 표시한다. - 다른 탭 분기와 기존 이벤트 팝업/회원 정보 초기화 흐름은 변경하지 않는다. - 검증 기준: - 실행 명령: `rg "case \\.home|MainHomeView|MainPlaceholderTabView" SodaLive/Sources/V2/Main/MainView.swift` - 기대 결과: `.home`은 `MainHomeView()`를 표시하고, 다른 탭은 기존 동작을 유지한다. ### Phase 7: 데이터 기반 프로젝트 포함과 중간 빌드 검증 - [ ] **Task 7.1: 데이터 기반 신규 Swift 파일 프로젝트 포함 여부 확인** - 대상 파일: - 확인/보완: `SodaLive.xcodeproj/project.pbxproj` - 확인: `SodaLive/Sources/V2/Main/Home/**` - 작업 내용: - Phase 4~6에서 생성/이동한 데이터 상태, 라우팅, 탭 루트 Swift 파일이 빌드 대상에 포함되는지 확인한다. - 파일 시스템 동기화 방식으로 자동 포함되면 프로젝트 파일을 수정하지 않는다. - 프로젝트 파일 수정이 필요한 경우에만 최소 변경한다. - 검증 기준: - 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj` - 기대 결과: `OK` - 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` - 기대 결과: `BUILD SUCCEEDED` ### Phase 8: 현재 라이브 섹션 UI - [ ] **Task 8.1: 현재 라이브 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeLiveSection.swift` - 작업 내용: - `HomeLiveItem.roomId`, `creatorNickname`, `creatorProfileImage`로 라이브 아이템을 표시한다. - 데이터가 비어 있으면 섹션 제목과 컨테이너를 표시하지 않는다. - 아이템 터치 이동은 라우팅 규칙이 명확한 경우에만 연결한다. - 검증 기준: - 실행 명령: `rg "MainHomeLiveSection|roomId|creatorNickname|creatorProfileImage" SodaLive/Sources/V2/Main/Home/Recommendation` - 기대 결과: 라이브 섹션이 신규 응답 필드를 기준으로 구성된다. ### Phase 9: 배너 섹션 UI - [ ] **Task 9.1: 추천 배너 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeBannerSection.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift` - 확인/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` - 작업 내용: - `banners: List`를 표시할 Swift 모델을 확정한다. - 기존 `BannerCarousel`로 충분하면 재사용하고, 홈 전용 wrapper만 작성한다. - 배너 이동 규칙은 미확정이면 탭 액션을 임의 구현하지 않는다. - 검증 기준: - 실행 명령: `rg "RecommendationBannerResponse|HomeBanner|BannerCarousel|MainHomeBannerSection" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Component/Banner` - 기대 결과: 배너 응답 모델과 화면 조합이 확인된다. ### Phase 10: 최근 활동 크리에이터 섹션 UI - [ ] **Task 10.1: 최근 활동 크리에이터 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeActiveCreatorSection.swift` - 작업 내용: - `creatorNickname`, `creatorProfileImage`, `activityType`, `activityAt`, `targetId`를 사용한다. - `activityType`은 `RecommendedActivityType` 변환 결과를 표시한다. - 데이터가 비어 있으면 섹션을 표시하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeActiveCreatorSection|activityType|activityAt|targetId|RecommendedActivityType" SodaLive/Sources/V2/Main/Home/Recommendation` - 기대 결과: 최근 활동 섹션이 신규 응답 필드와 활동 타입 변환을 사용한다. ### Phase 11: 최근 데뷔한 크리에이터 섹션 UI - [ ] **Task 11.1: 최근 데뷔 크리에이터 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeRecentDebutCreatorSection.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Creator/CreatorProfileGrid.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Creator/CreatorProfileItem.swift` - 작업 내용: - `HomeCreatorItem.creatorId`, `creatorNickname`, `creatorProfileImage`를 사용한다. - 기존 `CreatorProfileGrid`와 `CreatorProfileItem`을 우선 재사용한다. - 데이터가 비어 있으면 섹션을 표시하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeRecentDebutCreatorSection|CreatorProfileGrid|CreatorProfileItem|creatorProfileImage" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Component/Creator` - 기대 결과: 최근 데뷔 섹션이 공용 Creator widget을 재사용한다. ### Phase 12: 처음 만나는 오디오 섹션 UI - [ ] **Task 12.1: AudioContentCardView 조건부 태그 보완** - 대상 파일: - 확인/보완: `SodaLive/Sources/V2/Component/AudioContentCard.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeFirstAudioContentSection.swift` - 작업 내용: - `HomeFirstAudioContentItem.isPointAvailable == true`이면 `ic_content_tag_point` 시각요소를 표시한다. - 오리지널 작품이면 `ic_content_tag_original` 시각요소를 표시한다. - `price == 0`이면 `무료` 텍스트를 표시한다. - 크리에이터의 첫 번째 콘텐츠이면 `FIRST` 표시를 보여준다. - 조건에 해당하지 않는 요소는 렌더링하지 않는다. - 오리지널/첫 콘텐츠 판단 필드가 응답에 없으면 임의 추정하지 않고 Open Question으로 유지한다. - 검증 기준: - 실행 명령: `rg "ic_content_tag_point|ic_content_tag_original|isPointAvailable|무료|FIRST|MainHomeFirstAudioContentSection" SodaLive/Sources/V2` - 기대 결과: 오디오 카드 조건부 시각요소와 섹션 조합이 확인된다. ### Phase 13: AI 캐릭터 섹션 UI - [ ] **Task 13.1: AI 캐릭터 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeAiCharacterSection.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Card/AiCharacterCard.swift` - 작업 내용: - `characterId`, `creatorId`, `name`, `description`, `profileImage`, `totalChatCount`, `originalWorkTitle`를 사용한다. - 기존 `AiCharacterCard`로 충분하면 재사용한다. - 데이터가 비어 있으면 섹션을 표시하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeAiCharacterSection|AiCharacterCard|totalChatCount|originalWorkTitle|profileImage" SodaLive/Sources/V2` - 기대 결과: AI 캐릭터 섹션이 신규 응답 필드를 기준으로 구성된다. ### Phase 14: 장르의 크리에이터 섹션 UI - [ ] **Task 14.1: 장르 크리에이터 그룹 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeGenreCreatorSection.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeCreatorGroupSection.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Creator/CreatorProfileGrid.swift` - 작업 내용: - `HomeGenreCreatorGroupItem.genreName`과 `creators`를 사용한다. - 그룹별 크리에이터 목록은 기존 Creator widget을 재사용한다. - 모두 팔로우 API가 이번 범위에 남아 있다면 현재 섹션의 `creatorId` 목록으로만 호출한다. - 데이터가 비어 있으면 섹션을 표시하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeGenreCreatorSection|MainHomeCreatorGroupSection|genreName|creators|followAll" SodaLive/Sources/V2/Main/Home/Recommendation` - 기대 결과: 장르 그룹 섹션과 그룹 재사용 구조가 확인된다. ### Phase 15: 최근 응원이 많은 크리에이터 섹션 UI - [ ] **Task 15.1: 응원 크리에이터 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeCheerCreatorSection.swift` - 확인/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeCreatorGroupSection.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Creator/CreatorProfileGrid.swift` - 작업 내용: - `cheerCreators`의 `creatorId`, `creatorNickname`, `creatorProfileImage`를 사용한다. - 장르 섹션과 같은 그룹 UI를 재사용한다. - 모두 팔로우 API가 이번 범위에 남아 있다면 응원 섹션의 `creatorId` 목록으로만 호출한다. - 데이터가 비어 있으면 섹션을 표시하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeCheerCreatorSection|cheerCreators|MainHomeCreatorGroupSection|CreatorProfileGrid" SodaLive/Sources/V2/Main/Home/Recommendation` - 기대 결과: 응원 섹션이 장르 그룹 UI를 재사용한다. ### Phase 16: 인기 커뮤니티 섹션 UI와 FeedCommunityView - [ ] **Task 16.1: FeedCommunityView/CommunityPostCard 요구 보완** - 대상 파일: - 확인/보완: `SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomePopularCommunitySection.swift` - 작업 내용: - 키워드 영역을 제거한다. - `imageUrl`이 있으면 이미지를 표시한다. - `price > 0 && existOrdered == false`이면 유료 미구매 UI를 표시한다. - `price <= 0 || existOrdered == true`이면 일반 이미지로 표시한다. - `구매완료` 버튼은 표시하지 않는다. - `creatorProfileImage`, `createdAt`, `likeCount`, `commentCount`를 표시한다. - `audioUrl` 재생 UI는 확정 전까지 추가하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomePopularCommunitySection|CommunityPostCard|imageUrl|audioUrl|existOrdered|구매완료" SodaLive/Sources/V2` - 기대 결과: 커뮤니티 섹션과 카드 조건 분기가 확인되고 `구매완료` 표시 구현은 없어야 한다. ### Phase 17: 사업자 정보 섹션 UI - [ ] **Task 17.1: 사업자 정보 더보기/접기 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeBusinessInfoSection.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift` - 작업 내용: - 추천 탭 UI 마지막에 사업자 정보 섹션을 배치한다. - 섹션 width는 화면에 채운다. - 기본 3줄 말줄임표와 `더보기`를 표시한다. - 더보기 터치 시 전체 표시와 `접기`를 제공한다. - 외부 라이브러리를 사용하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeBusinessInfoSection|ExpandableTextView|lineLimit|더보기|접기" SodaLive/Sources/V2` - 기대 결과: 사업자 정보 섹션과 확장 텍스트 구현이 확인된다. ### Phase 18: 섹션 조립 순서와 빈 섹션 처리 - [ ] **Task 18.1: MainHomeRecommendationView에 섹션 순서 반영** - 대상 파일: - 확인/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 작업 내용: - 섹션 순서를 PRD와 맞춘다. - 현재 라이브, 배너, 최근 활동, 최근 데뷔, 처음 만나는 오디오, AI 캐릭터, 장르, 응원, 인기 커뮤니티, 사업자 정보 순서로 배치한다. - 각 데이터 배열이 비어 있으면 섹션 제목과 컨테이너까지 숨긴다. - 검증 기준: - 실행 명령: `rg "MainHomeLiveSection|MainHomeBannerSection|MainHomeActiveCreatorSection|MainHomeRecentDebutCreatorSection|MainHomeFirstAudioContentSection|MainHomeAiCharacterSection|MainHomeGenreCreatorSection|MainHomeCheerCreatorSection|MainHomePopularCommunitySection|MainHomeBusinessInfoSection" SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 기대 결과: 모든 구현 대상 섹션이 올바른 순서로 조립된다. ### Phase 19: 최종 프로젝트 포함과 빌드 검증 - [ ] **Task 19.1: Xcode 프로젝트 포함 여부 확인** - 대상 파일: - 확인/보완: `SodaLive.xcodeproj/project.pbxproj` - 확인: `SodaLive/Sources/V2/Main/Home/**` - 확인: `SodaLive/Sources/V2/Component/**` - 작업 내용: - 신규 Swift 파일이 빌드 대상에 포함되는지 확인한다. - 파일 시스템 동기화 방식으로 자동 포함되면 프로젝트 파일을 수정하지 않는다. - 프로젝트 파일 수정이 필요한 경우에만 최소 변경한다. - 검증 기준: - 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj` - 기대 결과: `OK` - [ ] **Task 19.2: 정적 점검과 빌드** - 대상 파일: - 확인: `SodaLive/Sources/V2/Main/Home/**` - 확인: `SodaLive/Sources/V2/Component/**` - 확인: `SodaLive/Sources/Home/**` - 작업 내용: - 제외 섹션, 기존 홈 API 오염, Figma URL, 공백 오류를 확인한다. - 가능한 빌드 명령을 실행한다. - 검증 기준: - 실행 명령: `rg "추천 필모그래피|또 다른 모습" SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Component` - 기대 결과: 검색 결과가 없어야 한다. - 실행 명령: `rg "api/v2/home/recommendations" SodaLive/Sources/Home` - 기대 결과: 검색 결과가 없어야 한다. - 실행 명령: `rg "localhost:3845|figma.com" SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Component` - 기대 결과: 검색 결과가 없어야 한다. - 실행 명령: `git diff --check` - 기대 결과: 출력 없이 성공한다. - 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` - 기대 결과: `BUILD SUCCEEDED` ### Phase 20: 문서와 검증 기록 갱신 - [ ] **Task 20.1: PRD/계획 문서 갱신** - 대상 파일: - 수정: `docs/20260602_메인_홈_추천_UI_API_연동/prd.md` - 수정: `docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` - 작업 내용: - 구현 중 확정된 배너 이동 규칙, 표시 개수, 오디오 태그 판단 필드, 커뮤니티 `audioUrl` 표시 여부가 있으면 PRD를 먼저 갱신한다. - 완료한 task 체크박스를 실제 상태에 맞게 갱신한다. - 실행한 검증 명령과 결과를 이 문서 하단 검증 기록에 누적한다. - 검증 기준: - 실행 명령: `rg "### Phase [0-9]+:|- \\[[ x]\\] \\*\\*Task [0-9]+\\.[0-9]+:" docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` - 기대 결과: phase heading과 `Task N.N` 형식 체크박스가 검색된다. ## 검증 기록 ### 2026-06-26 Phase 4~6 구현 완료 - 목적: 추천 ViewModel 데이터 로딩 계층을 `Recommendation` 하위로 정리하고, 추천 탭 상세 진입 callback guard와 홈 탭 shell/루트 View를 연결 - 수행 내용: - `MainHomeViewModel.swift`를 `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationViewModel.swift`로 이동하고 `MainHomeRecommendationViewModel`로 이름 변경 - `MainHomeRecommendationView`를 추가해 추천 API 로딩/에러 toast 상태를 추천 탭 루트에서 관리하도록 구성 - `MainHomeView`를 추가해 `HomeTitleBar`, 추천/랭킹/팔로잉 `TextTabBar`, 탭별 루트 View 조합만 담당하도록 구성 - `MainHomeRankingView`, `MainHomeFollowingView`는 이번 추천 API 범위 밖이므로 최소 placeholder 루트 View만 추가 - `MainView`의 `.home` 분기를 `MainHomeView`로 교체하고, 추천 상세 진입 callback을 기존 `token`, `auth`, `pendingAction`, `isShowAuthConfirmView`, `authView` 인프라를 재사용하는 guard helper에 연결 - `HomeLiveItem`에 성인 여부 필드가 없어 라이브 항목 성인 여부는 임의 판단하지 않고, 향후 성인 여부가 명확한 호출에서 `requiresAdultContent`를 사용할 수 있게 중앙 helper만 준비 - 신규/이동 Swift 파일을 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - `rg "final class MainHomeRecommendationViewModel|fetchRecommendations|HomeRecommendationResponse|MainHomeRecommendationRepository|isLoading|errorMessage" SodaLive/Sources/V2/Main/Home` 실행, 추천 API 로딩/에러/응답 상태가 `MainHomeRecommendationViewModel` 중심으로 검색됨 확인 - `rg "pendingAction|isShowAuthConfirmView|setPendingContentSettingsGuideMessage|adultContentEnableGuide|contentViewSettings|MainHomeView\(|MainHomeRecommendationView\(" SodaLive/Sources/V2/Main/MainView.swift SodaLive/Sources/V2/Main/Home` 실행, 신규 추천 탭 callback이 `MainView` guard 인프라를 재사용함 확인 - `find SodaLive/Sources/V2/Main/Home -maxdepth 3 -type f | sort` 실행, `Recommendation`, `Ranking`, `Following` 하위 루트 파일 확인 - `rg "struct MainHomeView|HomeTitleBar|MainHomeRecommendationView|MainHomeRankingView|MainHomeFollowingView|MainTabBarView|fetchRecommendations" SodaLive/Sources/V2/Main/Home/MainHomeView.swift SodaLive/Sources/V2/Main/MainView.swift` 실행, `MainHomeView`가 탭별 루트 View를 조합하고 `fetchRecommendations`를 직접 호출하지 않음 확인 - `rg "case \\.home|MainHomeView|MainPlaceholderTabView" SodaLive/Sources/V2/Main/MainView.swift` 실행, `.home`이 `MainHomeView`를 표시하고 다른 placeholder 탭은 유지됨 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-26 Phase 1~3 코드 리뷰 보완 - 목적: Phase 2.2 리뷰에서 지적된 과거 추정 응답 필드 혼재를 제거하고, 추천 전용 request 모델 위치를 `Recommendation/Models` 구조로 일치 - 수행 내용: - `MainHomeRecommendationResponse.swift`에서 PRD 응답 스펙에 없는 legacy/추정 필드(`liveRoomId`, `profileImageUrl`, `thumbnailUrl`, `coverImageUrl`, `releaseDate`, `originalTitle` 등) 제거 - 배너는 상세 PRD 스펙이 별도로 없으므로 기존 표시/이동 판단에 필요한 `RecommendationBannerResponse` 최소 필드 유지 - `FollowRecommendedCreatorsRequest.swift`를 `SodaLive/Sources/V2/Main/Home/Recommendation/Models` 아래로 이동 - `SodaLive.xcodeproj/project.pbxproj`의 request/model/API/Repository 참조 경로 갱신 - 검증: - `rg "liveRoomId|profileImageUrl|thumbnailUrl|coverImageUrl|releaseDate|originalTitle|chatCount|creatorProfileImageUrl|genreId|debutDate|followerCount|cheerCount|nickname" SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` 실행, 검색 결과 없음 확인 - `rg "FollowRecommendedCreatorsRequest" SodaLive/Sources/V2/Main/Home SodaLive.xcodeproj/project.pbxproj` 실행, request 모델이 `Recommendation/Models`에 있고 호출부/프로젝트 참조가 유지됨 확인 - `rg --files SodaLive/Sources/V2/Main/Home | sort` 실행, 추천 전용 모델/API 파일이 `Recommendation` 하위에 위치함 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-26 Phase 4 이후 데이터 선행 순서 재배치 - 목적: Figma 기준 UI는 직접 확인하며 처리할 수 있도록, Phase 4 이후 작업을 네트워크 통신/상태/라우팅/중간 빌드 검증 선행 후 섹션 UI 구현 순서로 재배치 - 수행 내용: - Phase 4를 추천 ViewModel 데이터 로딩 계층 정리로 변경 - Phase 5를 상세 진입 데이터/라우팅 guard로 배치 - Phase 6을 홈 탭 shell과 탭별 루트 연결로 배치하되, 섹션 UI 구현은 이후 Phase로 미룸 - Phase 7에 데이터 기반 프로젝트 포함과 중간 빌드 검증을 추가 - 기존 섹션별 UI Phase를 Phase 8~17로 뒤로 이동하고, 섹션 조립/최종 검증/문서 갱신을 Phase 18~20으로 재번호 지정 - 검증: - `rg "^### Phase [0-9]+:|- \\[[ x]\\] \\*\\*Task [0-9]+\\.[0-9]+:" docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, Phase/Task 번호 형식 확인 - `git diff --check -- docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, 출력 없이 성공 확인 ### 2026-06-26 Phase 1~3 재점검 및 보완 - 목적: 신규 재분류 기준의 Phase 1~3에 맞춰 추천 API/모델/활동 타입 위치와 응답 필드를 `Recommendation` 하위 구조로 정리 - 수행 내용: - PRD와 현재 `SodaLive/Sources/V2/Main/Home`, `SodaLive/Sources/V2/Component` 구현 상태를 비교해 Phase 1 기준점과 제외 범위 확인 - 추천 API/Repository를 `SodaLive/Sources/V2/Main/Home/Recommendation/Repository` 아래로 이동하고 `MainHomeRecommendationApi`, `MainHomeRecommendationRepository`로 이름 정리 - 추천 응답 모델과 활동 타입을 `SodaLive/Sources/V2/Main/Home/Recommendation/Models` 아래로 이동 - `HomeRecommendationResponse.banners` 타입을 `RecommendationBannerResponse`로 명확히 하고 PRD 핵심 필드(`roomId`, `creatorProfileImage`, `targetId`, `price`, `coverImage`, `isPointAvailable`, `totalChatCount`, `originalWorkTitle`, `audioUrl`) 반영 - `RecommendedActivityType`의 `LIVE`, `LIVE_REPLAY`, `AUDIO`, `COMMUNITY` 변환과 `I18n.HomeRecommendation` ko/en/ja 문구 유지 확인 - `SodaLive.xcodeproj/project.pbxproj`의 이동/이름 변경된 Swift 파일 참조 갱신 - 검증: - `rg --files SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Component SodaLive/Sources/Home SodaLive/Sources/I18n | sort` 실행, V2 홈/공용 컴포넌트 및 기존 홈 파일 목록 확인 - `rg "추천 필모그래피|또 다른 모습|figma.com|localhost:3845" SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Component` 실행, 검색 결과 없음 확인 - `rg "/api/v2/home/recommendations|getRecommendations" SodaLive/Sources/V2/Main/Home/Recommendation/Repository SodaLive/Sources/Home` 실행, 신규 추천 endpoint가 `Recommendation/Repository`에서만 검색되고 기존 `SodaLive/Sources/Home`에는 없음 확인 - `rg "roomId|creatorProfileImage|targetId|price|coverImage|isPointAvailable|totalChatCount|originalWorkTitle|audioUrl" SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` 실행, PRD 핵심 필드 반영 확인 - `rg "LIVE_REPLAY|activityLive|activityAudio|activityCommunity|ライブ|オーディオ|コミュニティ" SodaLive/Sources/V2/Main/Home/Recommendation/Models/RecommendedActivityType.swift SodaLive/Sources/I18n/I18n.swift` 실행, 활동 타입 변환과 I18n 문구 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-26 MainHome 탭별 폴더 구조 반영 - 목적: `MainHomeView`에 추천/랭킹/팔로잉 콘텐츠 조립이 누적되지 않도록 탭별 하위 폴더와 루트 View 구조를 PRD/계획 문서에 반영 - 수행 내용: - `prd.md`에 `MainHomeView`는 홈 상단 shell, 추천/랭킹/팔로잉 탭 콘텐츠는 별도 View로 분리한다는 기준 추가 - 추천 탭 루트/모델/API/ViewModel/섹션 경로를 `SodaLive/Sources/V2/Main/Home/Recommendation/**` 기준으로 변경 - 랭킹/팔로잉 탭 루트 파일 후보를 `SodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingView.swift`, `SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift`로 추가 - Phase 4를 `MainHomeView 탭 shell과 탭별 루트 View`로 재정의하고, 추천 섹션 조립은 `MainHomeRecommendationView`에서 처리하도록 변경 - 검증: - `rg "MainHomeRecommendationView|MainHomeRankingView|MainHomeFollowingView|Recommendation/Components|Recommendation/Repository|Recommendation/Models" docs/20260602_메인_홈_추천_UI_API_연동/prd.md docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, 탭별 루트 View와 추천 탭 하위 경로 반영 확인 - `rg "### Phase [0-9]+:|- \\[[ x]\\] \\*\\*Task [0-9]+\\.[0-9]+:" docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, Phase/Task 형식 확인 - `git diff --check -- docs/20260602_메인_홈_추천_UI_API_연동/prd.md docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, 출력 없이 성공 확인 ### 2026-06-26 상세 진입 guard 요구사항 추가 - 목적: 신규 추천 탭의 상세 진입 시 기존 홈과 같은 로그인/본인인증/민감 콘텐츠 보기 설정 guard를 적용하도록 PRD와 계획 문서 보완 - 수행 내용: - `prd.md`에 `추천 탭 상세 진입 guard` 요구사항 추가 - `plan-task.md`의 Phase 4에 `Task 4.3: 추천 탭 상세 진입 guard 적용` 추가 - `MainHomeView`는 탭 이벤트만 올리고, V2 `MainView`의 기존 인증 인프라를 재사용하는 방향으로 명시 - `HomeLiveItem`에 `isAdult` 또는 동등한 필드가 필요하다는 Open Question 반영 - 검증: - `rg "추천 탭 상세 진입 guard|pendingAction|isShowAuthConfirmView|setPendingContentSettingsGuideMessage|HomeLiveItem.*isAdult|Task 4.3" docs/20260602_메인_홈_추천_UI_API_연동/prd.md docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, guard 요구사항과 Task 반영 확인 - `rg "### Phase [0-9]+:|- \\[[ x]\\] \\*\\*Task [0-9]+\\.[0-9]+:" docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, Phase/Task 형식 확인 - `git diff --check -- docs/20260602_메인_홈_추천_UI_API_연동/prd.md docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, 출력 없이 성공 확인 ### 2026-06-26 PRD/계획 문서 재분류 - 목적: 신규 API 응답 스펙, FeedCommunityView, AudioContentCardView, 사업자 정보 요구사항을 PRD와 계획 문서에 반영하고, 기존 Phase를 섹션 단위 Phase로 재분류 - 수행 내용: - `prd.md`를 신규 응답 스펙 기준으로 갱신 - `plan-task.md`의 기존 Phase/완료 상태를 새 작업 분류 기준으로 재작성 - UI 작업은 현재 라이브, 배너, 최근 활동, 최근 데뷔, 처음 만나는 오디오, AI 캐릭터, 장르, 응원, 인기 커뮤니티, 사업자 정보 섹션별 Phase로 분리 - 기존 검증 기록은 아래에 보존 - 검증: - `rg "GET /api/v2/home/recommendations|RecommendationBannerResponse|FeedCommunityView|AudioContentCardView|추천 필모그래피|또 다른 모습|node-id=309-19774|node-id=309-19775" docs/20260602_메인_홈_추천_UI_API_연동/prd.md docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, 신규 API/응답 타입/FeedCommunityView/AudioContentCardView/제외 섹션/Figma 노드 반영 확인 - `rg "### Phase [0-9]+:|- \\[[ x]\\] \\*\\*Task [0-9]+\\.[0-9]+:" docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, Phase heading과 Task 체크박스 형식 확인 - `git diff --check -- docs/20260602_메인_홈_추천_UI_API_연동/prd.md docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, 출력 없이 성공 확인 ### 2026-06-02 계획 문서 생성 - 목적: `docs/20260602_메인_홈_추천_UI_API_연동/prd.md`를 기준으로 구현 전 계획/TASK 문서 작성 - 수행 내용: - MainHome 페이지 루트, 신규 API 계층, 공용 컴포넌트, MainHome 전용 컴포넌트, 연결/검증 작업을 TASK 단위로 분리 - 공용 컴포넌트는 `SodaLive/Sources/V2/Component/**` 형태별 폴더 기준으로 배치 - MainHome 전용 컴포넌트는 `SodaLive/Sources/V2/Main/Home/Components` 기준으로 배치 - 아직 수행하지 않은 작업: - Swift 코드 구현 - Xcode 프로젝트 포함 여부 확인 - 빌드/기능 검증 ### 2026-06-02 Phase 1 구현 완료 - 목적: Phase 1 범위인 구현 전 구조 확인, 추천 API 모델, I18n 문구, 신규 API/Repository 작성 - 수행 내용: - `SodaLive/Sources/V2/Main/MainView.swift`의 `.home` placeholder 유지 상태와 기존 `HomeApi`, `HomeTabRepository`, `I18n` 구조 확인 - `SodaLive/Sources/V2/Main/Home/Models`에 `HomeRecommendationResponse`, `FollowRecommendedCreatorsRequest`, `RecommendedActivityType` 추가 - `SodaLive/Sources/I18n/I18n.swift`에 `I18n.HomeRecommendation` 문구 추가 - `SodaLive/Sources/V2/Main/Home/Repository`에 `MainHomeApi`, `MainHomeRepository` 추가 - 신규 Swift 파일 5개를 `SodaLive.xcodeproj/project.pbxproj`의 `SodaLive`, `SodaLive-dev` Sources에 포함 - 검증: - `rg "case \.home|MainPlaceholderTabView|enum HomeApi|enum I18n" SodaLive/Sources/V2/Main SodaLive/Sources/Home SodaLive/Sources/I18n/I18n.swift` 실행, `.home` placeholder와 기존 `HomeApi`, `I18n` 구조 확인 - `rg "struct HomeRecommendationResponse|struct FollowRecommendedCreatorsRequest|enum RecommendedActivityType" SodaLive/Sources/V2/Main/Home/Models` 실행, 모델 정의 검색 확인 - `rg "enum HomeRecommendation|activityLive|followAllCompleted|collapse" SodaLive/Sources/I18n/I18n.swift` 실행, 신규 I18n 문구 검색 확인 - `rg "/api/v2/home/recommendations|followRecommendedCreators|getRecommendations" SodaLive/Sources/V2/Main/Home/Repository` 실행, 신규 API 경로와 repository 메서드 검색 확인 - `rg "/api/v2/home/recommendations" SodaLive/Sources/Home` 실행, 검색 결과 없음 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -list` 실행, 별도 테스트 타깃 없음 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 - 아직 수행하지 않은 작업: - Phase 2 이후 ViewModel, UI 컴포넌트, 홈 탭 연결 - 테스트 타깃이 없어 Phase 1 전용 RED/GREEN 단위 테스트는 추가하지 않음 ### 2026-06-02 Phase 2 구현 완료 - 목적: Phase 2 범위인 `MainHomeViewModel`과 공용 UI 컴포넌트 작성 - 수행 내용: - `SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift`에 추천 API 로딩/오류/응답 상태와 모두 팔로우 완료/호출 중 상태 추가 - `SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift` 추가 - `SodaLive/Sources/V2/Component/Creator`에 `CreatorProfileItem`, `CreatorProfileGrid` 추가 - `SodaLive/Sources/V2/Component/Button`, `Banner`, `Card`에 `FollowAllButton`, `BannerCarousel`, `AiCharacterCard`, `CommunityPostCard` 추가 - `SodaLive/Resources/Assets.xcassets/v2`에 Phase 2 버튼/카드용 `ic_new_following`, `ic_new_follow`, `ic_new_community_lock` 이미지셋 포함 - 신규 Swift 파일 8개를 `SodaLive.xcodeproj/project.pbxproj`의 `SodaLive`, `SodaLive-dev` Sources에 포함 - 실제 파일이 없던 기존 `CustomView/ExpandableTextView.swift` stale 프로젝트 참조를 제거해 중복 빌드 산출물 오류 해결 - 검증: - `rg "final class MainHomeViewModel|fetchRecommendations|followAll|ApiResponse|ApiResponseWithoutData" SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift` 실행, ViewModel 상태/API 처리 메서드 검색 확인 - `rg "struct ExpandableTextView|lineLimit|moreTitle|collapseTitle|isExpanded" SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift` 실행, 확장/접기 상태와 3줄 제한 구현 키워드 검색 확인 - `rg "struct CreatorProfileItem|struct CreatorProfileGrid|creatorNickname|HomeCreatorItem|HomeRecommendationResponse|MainHome" SodaLive/Sources/V2/Component/Creator` 실행, 공용 Creator 컴포넌트 검색 및 API 응답 타입 의존 없음 확인 - `rg "struct FollowAllButton|ic_new_following|struct BannerCarousel|struct AiCharacterCard|struct CommunityPostCard|구매완료|HomeBannerItem|HomeAiCharacterItem|HomePopularCommunityPostItem|HomeRecommendationResponse" SodaLive/Sources/V2/Component` 실행, 공용 컴포넌트 검색 및 금지 문구/응답 타입 의존 없음 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 - 아직 수행하지 않은 작업: - Phase 3 이후 MainHome 전용 섹션, 페이지 조립, 홈 탭 연결 - 테스트 타깃이 없어 Phase 2 전용 RED/GREEN 단위 테스트는 추가하지 않음 ### 2026-06-12 Phase 2 코드 리뷰 보완 - 목적: Phase 2 코드 리뷰에서 확인된 ViewModel Combine 캡처 안정성과 커뮤니티 카드 잠금 아이콘 asset 불일치 보완 - 수행 내용: - `SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift`의 추천 API/모두 팔로우 API Combine callback 캡처를 `[unowned self]`에서 `[weak self]`와 early return으로 변경 - `SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift`의 잠금 아이콘을 기존 `ic_lock_bb`에서 Phase 2 신규 asset인 `ic_new_community_lock`으로 변경 - 검증: - `rg "unowned self" SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` 실행, 검색 결과 없음 확인 - `rg "weak self|ic_new_community_lock|ic_lock_bb" SodaLive/Sources/V2/Main/Home/MainHomeViewModel.swift SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` 실행, `weak self` 캡처 4곳과 `ic_new_community_lock` 사용 확인 - `git diff --check` 실행, 출력 없이 성공 확인 ### 2026-06-12 Phase 1/2 리뷰 추가 보완 - 목적: Phase 1/2 리뷰에서 확인된 커뮤니티 카드 PRD 표시 누락과 사업자 정보 더보기 판정 안정성 보완 - 수행 내용: - `SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift`에 생성 시간 표시용 `createdAt` 입력과 footer 렌더링 추가 - 잠금 이미지의 가격 표시를 단순 텍스트에서 pay capsule 형태로 변경 - `SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift`의 측정 높이 변화 감지를 추가해 부모 폭/레이아웃 변경 시 더보기 표시 판정이 갱신되도록 보완 - 검증: - `rg "createdAt|Capsule\(\)|onChange\(of: proxy.size.height\)" SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift` 실행, 생성 시간 입력/표시, pay capsule, 높이 변화 감지 검색 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인