# 메인 홈 추천 탭 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`를 추가하지 않는다. - 외부 라이브러리는 추가하지 않는다. ### 2026-07-12 장르 크리에이터 섹션 미표시 반영 - 목적: 메인 홈 추천 탭에서 서버 응답의 `genreCreators` 기반 장르(카테고리)별 크리에이터 UI를 표시하지 않는다. - 수행 내용: - `MainHomeRecommendationView`의 추천 탭 섹션 조립에서 `MainHomeGenreCreatorSection` 호출을 제거한다. - `HomeRecommendationResponse.genreCreators` 모델 필드는 API 응답 디코딩을 위해 유지한다. - 검증: - `MainHomeRecommendationView`에서 `genreCreators`와 `MainHomeGenreCreatorSection` 참조가 없어야 한다. - 추천 탭의 인접 섹션인 AI 캐릭터, 응원 크리에이터, 인기 커뮤니티, 사업자 정보 섹션은 기존 순서로 유지되어야 한다. ## 주요 대상 파일 ### 확인/보완 - `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/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/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`, `HomeAiCharacterItem.totalChatCount`, `originalWorkTitle`, `HomePopularCommunityPostItem.audioUrl` 누락 여부를 확인한다. - 과거 추정 필드는 실제 사용 경로가 없으면 제거하거나 호환 필요 시 명확히 분리한다. - 검증 기준: - 실행 명령: `rg "roomId|creatorProfileImage|targetId|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: 데이터 기반 프로젝트 포함과 중간 빌드 검증 - [x] **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 - [x] **Task 8.1: 현재 라이브 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeLiveSection.swift` - 작업 내용: - `HomeLiveItem.roomId`, `creatorNickname`, `creatorProfileImage`로 라이브 아이템을 표시한다. - `roomId`는 응답 스펙상 항상 존재하는 값으로 취급한다. - 섹션 제목은 표시하지 않는다. - 데이터가 비어 있으면 섹션 제목과 컨테이너를 표시하지 않는다. - 아이템 터치 시 기존 `LiveViewModel.enterLiveRoom(roomId:)` 흐름을 재사용해 로그인 guard 이후 입장 전 결제 확인, 비밀방 비밀번호 dialog, `LiveRoomViewV2` 입장을 처리한다. - 검증 기준: - 실행 명령: `rg "MainHomeLiveSection|roomId|creatorNickname|creatorProfileImage|enterLiveRoom|LivePaymentDialog|LiveRoomPasswordDialog" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Main/MainView.swift` - 기대 결과: 라이브 섹션이 신규 응답 필드를 기준으로 구성되고, 추천 라이브 탭이 기존 라이브 입장 흐름을 재사용한다. ### Phase 9: 배너 섹션 UI - [x] **Task 9.1: BannerCarousel 현재 구현과 Figma 요구사항 고정** - 대상 파일: - 확인/보완: `SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift` - 확인/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` - 작업 내용: - Figma 기준 노드는 `24:5525`로 고정한다. - `BannerCarousel`이 현재 `TabView(.page)` 기반 단일 페이지 노출 구조인지 확인한다. - `RecommendationBannerResponse`의 `imageUrl`, `eventItem`, `creatorId`, `seriesId`, `link`가 표시와 이동에 매핑 가능한지 확인한다. - 배너 이동 규칙은 미확정이면 탭 액션을 임의 구현하지 않는다. - 검증 기준: - 실행 명령: `rg "struct BannerCarousel|BannerCarouselItem|RecommendationBannerResponse|eventItem|creatorId|seriesId|link|imageUrl" SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` - 기대 결과: 기존 캐러셀 구조와 배너 응답 모델 필드를 확인할 수 있다. - [x] **Task 9.2: BannerCarousel을 Figma와 동일한 수평 캐러셀로 보완** - 대상 파일: - 수정: `SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift` - 작업 내용: - 배너 width는 `device width - 40`으로 계산한다. - 배너 이미지 영역은 1:1 비율을 유지한다. - 배너 사이 간격은 8로 둔다. - 현재 배너 좌우에 이전/다음 배너가 조금씩 보이도록 수평 inset과 item 배치를 조정한다. - 배너가 2개 이상이면 무한 스크롤이 가능하도록 첫/마지막 경계에서 자연스럽게 이어지게 처리한다. - 배너 corner radius는 Figma 기준 `14`를 유지한다. - Figma처럼 우측 상단에 현재/전체 페이지 인디케이터를 표시한다. - 인디케이터는 `01 / 20` 형식으로 두 자리 current/total을 표시하고, 배경은 반투명 검정 pill 형태로 둔다. - 로컬 Figma asset URL(`localhost:3845`)은 앱 코드에 넣지 않는다. - 검증 기준: - 실행 명령: `rg "SodaSpacing.s8|SodaSpacing.s14|BannerCarousel|GeometryReader|ScrollView|TabView|01|current|total|localhost:3845" SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift` - 기대 결과: 간격 8, radius 14, 페이지 인디케이터, 무한/수평 캐러셀 구현 근거가 확인되고 `localhost:3845`는 검색되지 않아야 한다. - 수동 확인: iPhone 15 기준 현재 배너 폭이 화면 폭보다 40 작고, 좌우에 이전/다음 배너 일부가 보여야 한다. - 수동 확인: 이미지 영역이 정사각형으로 표시되고 배너 간 간격이 8로 보여야 한다. - [x] **Task 9.3: 추천 홈 배너 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeBannerSection.swift` - 수정: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 확인/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` - 작업 내용: - `HomeRecommendationResponse.banners`를 `BannerCarouselItem` 배열로 변환한다. - `eventItem`, `creatorId`, `seriesId`, `link`, `imageUrl` 순서로 안정적인 carousel id를 만든다. - `imageUrl`이 비어 있는 배너는 이미지 placeholder 정책을 기존 `BannerCarousel` 동작과 맞춘다. - 데이터가 비어 있으면 배너 섹션 자체를 표시하지 않는다. - 기존 `MainHomeRecommendationView` 섹션 순서를 유지하면서 현재 라이브 섹션 다음 위치에 배너 섹션을 배치한다. - 배너 이동 규칙은 미확정이면 탭 액션을 임의 구현하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeBannerSection|BannerCarouselItem|BannerCarousel|banners|RecommendationBannerResponse" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Component/Banner` - 기대 결과: 추천 응답의 `banners`가 홈 배너 섹션을 통해 `BannerCarousel`에 연결되어야 한다. - [x] **Task 9.4: 배너 섹션 빌드 및 시각 회귀 검증** - 대상 파일: - 확인: `SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift` - 확인: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeBannerSection.swift` - 확인: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 확인: `SodaLive.xcodeproj/project.pbxproj` - 작업 내용: - 새로 만든 `MainHomeBannerSection.swift`가 빌드 대상에 포함되는지 확인한다. - 파일 시스템 동기화 방식으로 자동 포함되면 프로젝트 파일을 수정하지 않는다. - 프로젝트 파일 수정이 필요한 경우에만 최소 변경한다. - 검증 기준: - 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj` - 기대 결과: `OK` - 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` - 기대 결과: `BUILD SUCCEEDED` - 수동 확인: 추천 홈에서 배너가 Figma 노드 `24:5525`처럼 좌우 배너 일부 노출, 간격 8, 1:1 이미지, 우측 상단 인디케이터 형태로 표시되어야 한다. ### Phase 10: 최근 활동 크리에이터 섹션 UI - [x] **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 - [x] **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: AI 캐릭터 섹션 UI - [x] **Task 12.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 13: 장르의 크리에이터 섹션 UI - [x] **Task 13.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 14: 최근 응원이 많은 크리에이터 섹션 UI - [x] **Task 14.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 15: 인기 커뮤니티 섹션 UI와 FeedCommunityView - [x] **Task 15.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를 표시한다. - 기존 커뮤니티 구매 API를 재사용해 유료 미구매 포스트 구매를 지원한다. - `createdAt`은 UTC로 파싱해 디바이스 Timezone 기준 상대 날짜로 표시한다. - 검증 기준: - 실행 명령: `rg "MainHomePopularCommunitySection|CommunityPostCard|imageUrl|audioUrl|existOrdered|구매완료|purchaseCommunityPost|communityPostLike|toggleContent|relativeTimeText" SodaLive/Sources/V2 SodaLive/Sources/Common SodaLive/Sources/Explorer/Profile/CreatorCommunity` - 기대 결과: 커뮤니티 섹션과 카드 조건 분기, 오디오 재생, 구매/좋아요 연결, UTC 상대 날짜 변환이 확인되고 `구매완료` 표시 구현은 없어야 한다. ### Phase 16: 사업자 정보 섹션 UI - [x] **Task 16.1: 사업자 정보 더보기/접기 섹션 작성/보완** - 대상 파일: - 생성/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeBusinessInfoSection.swift` - 확인/보완: `SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift` - 작업 내용: - 추천 탭 UI 마지막에 사업자 정보 섹션을 배치한다. - 섹션 width는 화면에 채운다. - 기본 3줄 말줄임표와 `더보기`를 표시한다. - 더보기 터치 시 전체 표시와 `접기`를 제공한다. - 외부 라이브러리를 사용하지 않는다. - 검증 기준: - 실행 명령: `rg "MainHomeBusinessInfoSection|BusinessInfoExpandableTextView|ExpandableTextView|lineLimit|더보기|접기" SodaLive/Sources/V2` - 기대 결과: 사업자 정보 섹션과 확장 텍스트 구현이 확인된다. ### Phase 17: 섹션 조립 순서와 빈 섹션 처리 - [x] **Task 17.1: MainHomeRecommendationView에 섹션 순서 반영** - 대상 파일: - 확인/보완: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 작업 내용: - 섹션 순서를 PRD와 맞춘다. - 현재 라이브, 배너, 최근 활동, 최근 데뷔, AI 캐릭터, 장르, 응원, 인기 커뮤니티, 사업자 정보 순서로 배치한다. - 각 데이터 배열이 비어 있으면 섹션 제목과 컨테이너까지 숨긴다. - 검증 기준: - 실행 명령: `rg "MainHomeLiveSection|MainHomeBannerSection|MainHomeActiveCreatorSection|MainHomeRecentDebutCreatorSection|MainHomeAiCharacterSection|MainHomeGenreCreatorSection|MainHomeCheerCreatorSection|MainHomePopularCommunitySection|MainHomeBusinessInfoSection" SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 기대 결과: 모든 구현 대상 섹션이 올바른 순서로 조립된다. ### Phase 18: 최종 프로젝트 포함과 빌드 검증 - [x] **Task 18.1: Xcode 프로젝트 포함 여부 확인** - 대상 파일: - 확인/보완: `SodaLive.xcodeproj/project.pbxproj` - 확인: `SodaLive/Sources/V2/Main/Home/**` - 확인: `SodaLive/Sources/V2/Component/**` - 작업 내용: - 신규 Swift 파일이 빌드 대상에 포함되는지 확인한다. - 파일 시스템 동기화 방식으로 자동 포함되면 프로젝트 파일을 수정하지 않는다. - 프로젝트 파일 수정이 필요한 경우에만 최소 변경한다. - 검증 기준: - 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj` - 기대 결과: `OK` - [x] **Task 18.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 19: 문서와 검증 기록 갱신 - [x] **Task 19.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` 형식 체크박스가 검색된다. ### Phase 20: 추천 커뮤니티 게시물 상세 진입 보정 - [x] **Task 20.1: PRD/계획 문서에 커뮤니티 게시물 상세 이동 요구사항 추가** - 대상 파일: - 수정: `docs/20260602_메인_홈_추천_UI_API_연동/prd.md` - 수정: `docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` - 작업 내용: - 최근 활동 크리에이터의 `activityType == COMMUNITY` 탭 액션을 커뮤니티 게시물 상세 이동으로 명시한다. - 인기 커뮤니티 섹션의 게시물 탭 액션을 커뮤니티 게시물 상세 이동으로 명시한다. - `targetId`는 최근 활동 `COMMUNITY`일 때 커뮤니티 게시물 `postId`로 취급한다. - 검증 기준: - 실행 명령: `rg "activityType == COMMUNITY|커뮤니티 게시물 상세|targetId.*postId|인기 커뮤니티" docs/20260602_메인_홈_추천_UI_API_연동` - 기대 결과: PRD와 계획 문서에서 이번 상세 이동 요구사항이 검색된다. - [x] **Task 20.2: 추천 탭 커뮤니티 게시물 상세 라우팅 연결** - 대상 파일: - 수정: `SodaLive/Sources/V2/Main/MainView.swift` - 수정: `SodaLive/Sources/V2/Main/Home/MainHomeView.swift` - 수정: `SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` - 수정: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeActiveCreatorSection.swift` - 수정: `SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomePopularCommunitySection.swift` - 수정: `SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` - 작업 내용: - 추천 탭 커뮤니티 callback을 `postId` 기준으로 명확히 연결한다. - 최근 활동 크리에이터의 `COMMUNITY` 타입은 `targetId`를 `postId`로 전달한다. - 인기 커뮤니티 카드 일반 탭과 댓글 아이콘 탭은 `postId`로 커뮤니티 게시물 상세에 진입한다. - 좋아요, 구매, 오디오 재생 액션은 기존 동작을 유지한다. - 팔로잉 탭 스케줄의 기존 `.community` 라우팅은 이번 추천 탭 범위 밖이므로 변경하지 않는다. - 검증 기준: - 실행 명령: `rg "onTapCommunityPost|handleRecommendationCommunityPostTap|creatorChannelCommunityPostDetail|onTapPost|onTapComment|handleFollowingScheduleTap" SodaLive/Sources/V2/Main SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` - 기대 결과: 추천 탭 커뮤니티 액션은 `postId` 기반 상세 이동을 사용하고, 팔로잉 스케줄 community 라우팅은 기존 분기를 유지한다. - [x] **Task 20.3: 정적 검증과 빌드 검증** - 대상 파일: - 확인: `SodaLive/Sources/V2/Main/**` - 확인: `SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` - 확인: `SodaLive.xcodeproj/project.pbxproj` - 작업 내용: - 변경 파일의 공백 오류와 프로젝트 파일 유효성을 확인한다. - 가능한 빌드를 실행한다. - 실행 결과를 검증 기록에 누적한다. - 검증 기준: - 실행 명령: `git diff --check` - 기대 결과: 출력 없이 성공한다. - 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj` - 기대 결과: `OK` - 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` - 기대 결과: `BUILD SUCCEEDED` ## 검증 기록 ### 2026-07-10 Phase 20 추천 커뮤니티 게시물 상세 진입 보정 완료 - 목적: 메인 홈 추천 탭의 최근 활동 `COMMUNITY`와 인기 커뮤니티 게시물 탭 액션을 커뮤니티 게시물 상세 페이지로 연결 - 수행 내용: - PRD에 최근 활동 `activityType == COMMUNITY`의 `targetId`를 커뮤니티 게시물 `postId`로 취급한다는 기준을 추가 - PRD에 인기 커뮤니티 게시물 일반 탭/댓글 아이콘 탭이 커뮤니티 게시물 상세 페이지로 이동한다는 기준을 추가 - `MainHomeView`, `MainHomeRecommendationView`, `MainHomeActiveCreatorSection`, `MainHomePopularCommunitySection`의 추천 커뮤니티 callback 이름을 `onTapCommunityPost`로 정리 - `MainView.handleRecommendationCommunityPostTap(postId:)`를 추가해 추천 탭 커뮤니티 액션을 `AppStep.creatorChannelCommunityPostDetail(postId:onCommunityRefresh:)`로 연결 - `CommunityPostCard`에 기본 no-op `onTapPost`를 추가하고, 인기 커뮤니티 섹션에서 일반 탭과 댓글 아이콘 탭 모두 `postId` 기반 상세 이동으로 연결 - 팔로잉 스케줄의 기존 `.community` 라우팅은 `creatorCommunityAll(creatorId:)`로 유지하고 로그인 guard 흐름도 유지 - 검증: - `rg "activityType == COMMUNITY|커뮤니티 게시물 상세|targetId.*postId|인기 커뮤니티" docs/20260602_메인_홈_추천_UI_API_연동` 실행, PRD/계획 문서에 요구사항 반영 확인 - `rg -n "onTapCommunityPost|handleRecommendationCommunityPostTap|creatorChannelCommunityPostDetail|onTapPost|onTapComment|handleFollowingScheduleTap|creatorCommunityAll" SodaLive/Sources/V2/Main SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` 실행, 추천 탭 `postId` 상세 이동과 팔로잉 스케줄 기존 분기 확인 - `rg -n "onTapCommunity:|handleRecommendationCommunityTap" SodaLive/Sources/V2/Main SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` 실행, 기존 모호한 추천 커뮤니티 callback 이름 제거 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - 샌드박스 내 `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, CoreSimulator/로그 접근 제한으로 실패 확인 - 승인 후 동일 `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 재실행, `BUILD SUCCEEDED` 확인 ### 2026-06-30 Phase 17~19 최종 조립/검증/문서 갱신 완료 - 목적: V2 Main Home 추천 탭 섹션 조립 순서와 빈 섹션 숨김 조건을 최종 확인하고, 프로젝트 포함/정적 점검/빌드 검증 결과를 계획 문서에 반영 - 수행 내용: - `MainHomeRecommendationView`가 현재 라이브, 배너, 최근 활동, 최근 데뷔, AI 캐릭터, 장르, 응원, 인기 커뮤니티, 사업자 정보 순서로 섹션을 조립하는지 확인 - 데이터 기반 섹션 컴포넌트가 `items.isEmpty` 조건으로 섹션 제목과 컨테이너를 숨기는지 확인 - 신규 Swift 파일 프로젝트 포함은 기존 `SodaLive.xcodeproj/project.pbxproj` 상태로 충족되어 추가 수정하지 않음 - 배너 이동 규칙, 표시 개수, 커뮤니티 `audioUrl` 표시 여부에 새 확정 사항은 없어 `prd.md`는 수정하지 않음 - Phase 17, 18, 19 task 체크박스를 실제 완료 상태로 갱신 - 검증: - `rg "MainHomeLiveSection|MainHomeBannerSection|MainHomeActiveCreatorSection|MainHomeRecentDebutCreatorSection|MainHomeAiCharacterSection|MainHomeGenreCreatorSection|MainHomeCheerCreatorSection|MainHomePopularCommunitySection|MainHomeBusinessInfoSection" SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift` 실행, 모든 구현 대상 섹션이 요구 순서로 조립됨 확인 - 각 섹션 파일 확인, `MainHomeLiveSection`, `MainHomeBannerSection`, `MainHomeActiveCreatorSection`, `MainHomeRecentDebutCreatorSection`, `MainHomeAiCharacterSection`, `MainHomeGenreCreatorSection`, `MainHomeCheerCreatorSection`, `MainHomePopularCommunitySection`에서 빈 배열 guard 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `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` 실행, 기존 DerivedData `build.db` lock으로 실패 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug -derivedDataPath "/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/SodaLiveDerivedDataPhase18" build` 실행, 10분 제한으로 `BUILD INTERRUPTED` 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug -derivedDataPath "/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/SodaLiveDerivedDataPhase18Long" build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-30 Phase 16 사업자 정보 섹션 구현 완료 - 목적: V2 Main Home 추천 탭 마지막에 사업자 정보 더보기/접기 섹션을 연결 - 수행 내용: - `MainHomeBusinessInfoSection`을 추가해 기존 `I18n.Settings.companyInfo`를 표시 - 기존 `ExpandableTextView` 이름 충돌을 피하기 위해 파일 내부 전용 `BusinessInfoExpandableTextView`로 기본 3줄 `lineLimit`, `더보기`, `접기` 동작을 연결 - `MainHomeRecommendationView`에서 인기 커뮤니티 섹션 다음에 사업자 정보 섹션을 배치 - 신규 `MainHomeBusinessInfoSection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - `rg "MainHomeBusinessInfoSection|BusinessInfoExpandableTextView|ExpandableTextView|lineLimit|더보기|접기" SodaLive/Sources/V2` 실행, 사업자 정보 섹션/3줄 제한/더보기 접기 구현 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` 실행, `Scheme SodaLive-dev is not currently configured for the test action`으로 테스트 액션 미구성 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-30 Phase 15 isLiked 컴파일 보완 - 목적: `HomePopularCommunityPostItem.isLiked` 추가 이후 추천 인기 커뮤니티 섹션 컴파일 오류 보완 - 수행 내용: - `HomePopularCommunityPostItem`에 `isLiked` 필드를 유지하고, 섹션에서 사용하는 `relativeCreatedAtText(now:)` helper를 복구 - `MainHomePopularCommunitySection`이 `item.isLiked`를 `CommunityPostCard(isLike:)` 초기 상태로 전달하는지 확인 - 검증: - `rg -n "HomePopularCommunityPostItem\(|\.isLike\b|isLike: item|isLiked|relativeCreatedAtText"` 실행, 추천 섹션에 남은 `item.isLike` 참조 없음 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-29 Phase 15 인기 커뮤니티 섹션 세로 FeedCommunityView 보정 완료 - 목적: V2 Main Home 추천 탭의 인기 커뮤니티 섹션을 Figma `24:5645`, `567:17875`, `567:17878` 기준 세로 FeedCommunityView 형태로 보정 - 수행 내용: - `MainHomePopularCommunitySection`의 가로 `ScrollView`/`LazyHStack`/240폭 카드 구성을 제거하고, 부모 추천 ScrollView 안에서 세로 `VStack` 피드 목록으로 표시 - `CommunityPostCard`를 Figma FeedCommunityView 형태로 보정해 Text Only, Text + Image, Text + Image + Audio, 유료 미구매 잠금 상태를 지원 - `audioUrl`이 있으면 기존 `CreatorCommunityMediaPlayerManager`와 `ContentPlayManager.pauseAudio()` 흐름을 재사용해 이미지 중앙 재생/일시정지 버튼을 표시 - 기존 `CreatorCommunityRepository.communityPostLike(postId:)`, `purchaseCommunityPost(postId:)`, `CommunityPostPurchaseDialog`를 추천 ViewModel에 연결해 좋아요와 유료 미구매 포스트 구매를 지원 - `DateParser.relativeTimeText(fromUTC:fallback:now:)`를 공용 함수로 추가하고, 기존 커뮤니티 상세와 추천 홈 카드가 UTC 날짜를 디바이스 Timezone 기준 상대 날짜로 표시하도록 연결 - `HomePopularCommunityPostItem.isLiked`를 카드 좋아요 초기 상태와 연결 - 키워드 영역과 `구매완료` 버튼은 추가하지 않음 - `MainHomeRecommendationView`에서 응원 섹션 다음에 인기 커뮤니티 섹션을 배치하고, 댓글 아이콘 탭은 기존 `creatorCommunityAll(creatorId:)` 라우팅에 맞춰 `creatorId`를 전달 - 신규 `MainHomePopularCommunitySection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - Figma `24:5645`, `567:17875`, `567:17878` 디자인 컨텍스트와 스크린샷 확인, 인기 커뮤니티 섹션이 세로 리스트이고 Feed 카드가 14 padding, 16 gap, 14 radius, 댓글/좋아요 18 아이콘 구조임을 확인 - `rg -n "ScrollView\\(\\.horizontal|LazyHStack|frame\\(width: 240\\)" SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomePopularCommunitySection.swift SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift` 실행, 검색 결과 없음 확인 - `rg -n "ic_feed_community_heart|ic_feed_community_heart_fill|ic_feed_community_reply|CommunityPostPurchaseDialog|purchaseCommunityPost|communityPostLike|toggleContent\\(item:|relativeTimeText\\(fromUTC|relativeCreatedAtText|CreatorCommunityRepository" SodaLive/Sources` 실행, 좋아요/댓글 아이콘, 구매/좋아요 API, 오디오 재생, UTC 상대 날짜 연결 확인 - `rg -n "localhost:3845|figma.com" SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Component` 실행, 검색 결과 없음 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` 실행, `Scheme SodaLive-dev is not currently configured for the test action`으로 테스트 액션 미구성 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-29 Phase 14 최근 응원이 많은 크리에이터 섹션 구현 완료 - 목적: V2 Main Home 추천 탭에 Figma `24:5636`, `309:19196` 기준 최근 응원이 많은 크리에이터 섹션을 연결 - 수행 내용: - `MainHomeCheerCreatorSection`을 추가해 `HomeRecommendationResponse.cheerCreators`의 `creatorId`, `creatorNickname`, `creatorProfileImage` 기반 크리에이터 목록을 표시 - Phase 13의 `MainHomeCreatorGroupSection`을 재사용하되, 응원 섹션은 섹션 제목 아래 고정 1개 카드만 표시하도록 구성 - `MainHomeCreatorGroupSection`에 기본값 `true`인 `showTitle` 옵션을 추가해 장르 섹션 기본 동작은 유지하고, 응원 섹션 카드 내부 제목만 숨김 - 데이터가 비어 있으면 섹션 제목과 카드가 렌더링되지 않도록 구성 - `MainHomeRecommendationView`에서 장르 섹션 다음에 응원 섹션을 배치하고, 모두 팔로우는 응원 섹션의 `creatorId` 목록만 `followAll`로 전달 - 신규 `MainHomeCheerCreatorSection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - Figma `24:5636`, `309:19196` 디자인 컨텍스트와 스크린샷 확인, 섹션 제목/단일 카드/8개 프로필/모두 팔로우 버튼 구조 확인 - `rg -n "MainHomeCheerCreatorSection|cheerCreators|MainHomeCreatorGroupSection|CreatorProfileGrid|showTitle|followAll|localhost:3845|figma.com" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Component/Creator` 실행, 응원 섹션/필드/재사용 그룹/followAll 연결 확인 및 forbidden URL 미포함 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` 실행, `Scheme SodaLive-dev is not currently configured for the test action`으로 테스트 액션 미구성 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-29 Phase 13 장르 크리에이터 섹션 구현 완료 - 목적: V2 Main Home 추천 탭에 Figma `24:5611`, `24:5612`, `24:5615`, `24:5623`, `24:9092` 기준 장르 크리에이터 그룹 섹션과 모두 팔로우 상태를 연결 - 수행 내용: - `MainHomeGenreCreatorSection`을 추가해 `HomeGenreCreatorGroupItem.genreName`, `creators` 기반 가로 그룹 카드 목록을 표시 - `MainHomeCreatorGroupSection`을 같은 파일에 분리해 Phase 14에서도 재사용 가능한 그룹 카드 UI로 구성 - 그룹 카드는 Figma 기준 폭 `374`, padding/radius/gap `14`, 어두운 배경에서 `soda700`으로 이어지는 세로 gradient, 최대 8개 크리에이터 2행 x 4열 구조로 구현 - 크리에이터 아이템은 기존 `CreatorProfileItem`을 재사용하고, `75x75` 원형 이미지와 한 줄 말줄임 닉네임을 표시하며, 탭 시 기존 `onTapCreator` guard 경로를 재사용 - 모두 팔로우 버튼은 `ic_new_follow`, `ic_new_following` 아이콘과 Figma의 미완료/완료 상태를 반영하도록 보완 - `MainHomeRecommendationView`에서 AI 캐릭터 섹션 다음에 장르 섹션을 배치하고, 기존 `MainHomeRecommendationViewModel.followAll(creatorIds:completionKey:)`와 `POST /api/v2/home/recommendations/creators/follow` 경로를 재사용 - 신규 `MainHomeGenreCreatorSection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - Figma `24:5611`, `24:5612`, `24:5615`, `24:5623`, `24:9092` 디자인 컨텍스트와 스크린샷 확인, 카드 폭/내부 간격/프로필 크기/버튼 상태 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` 실행, `Scheme SodaLive-dev is not currently configured for the test action`으로 테스트 액션 미구성 확인 - `rg -n "MainHomeGenreCreatorSection|MainHomeCreatorGroupSection|genreCreators|genreName|creators|followAll|FollowAllButton|followRecommendedCreators|localhost:3845|figma.com" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Component/Button/FollowAllButton.swift` 실행, 섹션/필드/API 연결 및 forbidden URL 미포함 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 - 리뷰어 지적에 따라 `CreatorProfileItem` 재사용과 `project.pbxproj` 중복 Sources 등록 제거를 반영한 뒤 동일 빌드 재실행, `BUILD SUCCEEDED` 확인 ### 2026-06-29 Phase 12 카드 반응형 크기와 채팅 수 표기 보완 - 목적: AI 캐릭터와 최근 데뷔 크리에이터 썸네일 카드 크기를 `402` 기준으로 보정하고, AI 캐릭터 채팅 수 배지를 다국어 축약 표기로 표시 - 수행 내용: - `AiCharacterCard.responsiveSize(deviceWidth:)`를 추가해 최대 `185x278`, 디바이스 폭이 `402`보다 작으면 `deviceWidth / 402` 비율로 축소되도록 구성 - `MainHomeRecentDebutCreatorSection`의 아이템도 동일한 responsive size를 사용해 AI 캐릭터 카드와 최대 크기/축소 비율을 맞춤 - `I18n.HomeRecommendation.compactChatCount(_:)`를 추가해 한국어/일본어는 `천`, `만`, `억` 계열, 영어는 `K`, `M`, `B` 계열로 표시 - 축약 소수는 한 자리까지 표시하고 경계값 반올림으로 단위가 앞당겨지지 않도록 내림 처리 - 검증: - `rg -n "responsiveSize|baseDeviceWidth|maxCardWidth|maxCardHeight|compactChatCount|compactEastAsianCount|compactEnglishCount|100_000_000|1_000" SodaLive/Sources/V2 SodaLive/Sources/I18n/I18n.swift` 실행, 반응형 크기와 다국어 축약 로직 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-29 Phase 12 AI 캐릭터 섹션 구현 완료 - 목적: V2 Main Home 추천 탭에 Figma `24:5551`, `24:5554` 기준 AI 캐릭터 섹션을 연결 - 수행 내용: - `AiCharacterCard`를 Figma 기준 `185x278` 썸네일 카드로 보완하고, `profileImage`, `totalChatCount`, `name`, `description`, `originalWorkTitle` 표시를 반영 - `MainHomeAiCharacterSection`을 추가해 `HomeAiCharacterItem.characterId`, `creatorId`, `name`, `description`, `profileImage`, `totalChatCount`, `originalWorkTitle` 기반 가로 카드 목록을 표시 - 데이터가 비어 있으면 섹션 제목과 목록을 렌더링하지 않도록 구성 - `MainHomeRecommendationView`에서 최근 데뷔 크리에이터 섹션 다음 순서로 AI 캐릭터 섹션을 배치 - 신규 `MainHomeAiCharacterSection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - `I18n.HomeRecommendation.aiCharacterSectionTitle`의 한국어 문구를 Figma 섹션 제목인 `크리에이터와 이야기를 나눠요!`로 반영 - 검증: - Figma `24:5551`, `24:5554` 디자인 컨텍스트와 스크린샷 확인, 섹션 제목/간격 14/리스트 좌측 inset 14/아이템 간격 4/아이템 `185x278` 구조 확인 - 구현 전 `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` 실행, `Scheme SodaLive-dev is not currently configured for the test action`으로 테스트 액션 미구성 확인 - `rg -n "MainHomeAiCharacterSection|AiCharacterCard|aiCharacters|totalChatCount|originalWorkTitle|profileImage|localhost:3845|figma.com" SodaLive/Sources/V2 SodaLive/Sources/I18n/I18n.swift` 실행, 추천 응답 필드 연결 및 forbidden URL 미포함 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-29 Phase 12 제외 섹션 반영 - 목적: 요구사항 변경에 따라 제외된 추천 섹션 UI 구현 범위를 PRD와 계획 문서에서 제거 - 수행 내용: - `prd.md`에서 제외 섹션의 응답 모델, UI 요구, 검증 항목을 제거 - `plan-task.md`에서 기존 Phase 12 Task를 제거하고, 이후 Phase 13~20을 Phase 12~19로 한 단계씩 재번호 지정 - 섹션 조립 순서와 검증 명령에서 제외 섹션 참조를 제거 - 검증: - 제외 섹션 관련 키워드 검색 결과가 남지 않음을 확인 - 최종 Phase/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-29 Phase 11 최근 데뷔 크리에이터 섹션 구현 완료 - 목적: V2 Main Home 추천 탭에 Figma `24:5534`, `24:5537` 기준 최근 데뷔한 크리에이터 섹션을 연결 - 수행 내용: - `MainHomeRecentDebutCreatorSection`을 추가해 `HomeCreatorItem.creatorId`, `creatorNickname`, `creatorProfileImage` 기반 가로 카드 목록을 표시 - Figma 아이템 원본 `205x259`를 요청 기준에 맞춰 `185x234` 고정 크기로 표시하고, radius 14, 하단 dim gradient, 중앙 하단 크리에이터명을 적용 - 데이터가 비어 있으면 섹션 제목과 목록을 렌더링하지 않도록 구성 - `MainHomeRecommendationView`에서 현재 라이브, 배너, 최근 활동 다음 순서로 최근 데뷔 크리에이터 섹션을 배치 - 신규 `MainHomeRecentDebutCreatorSection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - Figma `24:5534`, `24:5537` 디자인 컨텍스트와 스크린샷 확인, 섹션 제목/간격 14/리스트 좌측 inset 14/아이템 간격 4/아이템 `185x234` 구조 확인 - `rg -n "itemWidth|itemHeight|frame\(width: Self\.itemWidth, height: Self\.itemHeight\)|MainHomeRecentDebutCreatorSection|recentDebutCreators|localhost:3845|figma.com" SodaLive/Sources/V2/Main/Home/Recommendation` 실행, `itemWidth 185`, `itemHeight 234`, 추천 응답 연결 확인 및 forbidden URL 미포함 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 - 리뷰어 게이트 재검토 결과 `Unconditional Approval` 확인 ### 2026-06-29 Phase 10 최근 활동 크리에이터 섹션 구현 완료 - 목적: V2 Main Home 추천 탭에 Figma `24:5529`, `24:5532` 기준 최근 활동 크리에이터 섹션을 연결 - 수행 내용: - `MainHomeActiveCreatorSection`을 추가해 `creatorNickname`, `creatorProfileImage`, `activityType`, `activityAt`, `targetId` 기반 pill 형태 가로 목록을 표시 - `RecommendedActivityType.title`로 활동 태그를 표시하고, `DateParser.parse`와 `I18n.Time` 기준 상대 시간을 표시 - 데이터가 비어 있으면 섹션 제목과 목록을 렌더링하지 않도록 구성 - `MainHomeRecommendationView`에서 현재 라이브, 배너 다음 순서로 최근 활동 크리에이터 섹션을 배치 - 신규 `MainHomeActiveCreatorSection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - Figma `24:5529`, `24:5532` 디자인 컨텍스트와 스크린샷 확인, 섹션 제목/가로 pill 아이템/52px 원형 이미지/활동 태그/상대 시간 구조 확인 - `rg "MainHomeActiveCreatorSection|activityType|activityAt|targetId|RecommendedActivityType" SodaLive/Sources/V2/Main/Home/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-29 Phase 9 배너 스펙 변경 반영 - 목적: 변경된 `RecommendationBannerResponse` 백엔드 응답과 배너 1:1 이미지 비율 요구사항을 반영 - 수행 내용: - `RecommendationBannerResponse`에서 과거 `bannerId`, `type`, `title`, `eventId` 필드를 제거하고 `imageUrl`, `eventItem`, `creatorId`, `seriesId`, `link` 구조로 변경 - 배너 탭 시 `eventItem`, `creatorId`, `seriesId`, `link` 순서로 첫 non-optional 목적지를 찾아 이동하도록 연결 - `eventItem`은 `eventDetail`, `creatorId`는 `creatorDetail`, `seriesId`는 `seriesDetail`, `link`는 외부 URL open 경로를 사용 - `BannerCarousel` 높이를 `itemWidth`와 동일하게 되돌려 이미지 영역 1:1 비율 유지 - `BannerCarousel_Previews`, `MainHomeBannerSection_Previews`, `MainHomeLiveSection_Previews`의 Preview 원격 이미지를 `placehold.co` 대신 JPEG를 반환하는 `picsum.photos/500/500`로 변경 - 검증: - `rg -n "bannerId|eventId|RecommendationBannerResponse\(|\.type|\.title" SodaLive/Sources/V2/Main/Home SodaLive/Sources/V2/Main/MainView.swift` 실행, V2 추천 배너 코드에서 과거 응답 필드 참조 제거 확인 - `curl -L -o /dev/null -w "%{http_code} %{content_type}\n" "https://placehold.co/500"` 실행, `200 image/svg+xml` 확인 - `curl -L -o /dev/null -w "%{http_code} %{content_type}\n" "https://picsum.photos/500/500"` 실행, `200 image/jpeg` 확인 - `rg -n "placehold\.co/500" SodaLive/Sources/V2/Main/Home/Recommendation/Components SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift` 실행, 검색 결과 없음 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 ### 2026-06-29 Phase 9 배너 섹션 구현 완료 - 목적: V2 Main Home 추천 탭에 Figma `24:5525` 기준 배너 캐러셀과 추천 배너 섹션을 연결 - 수행 내용: - `BannerCarousel`을 `device width - 40` 폭의 1:1 배너, 간격 8, radius 14, 좌우 인접 배너 일부 노출, 우측 상단 `01 / NN` pill 인디케이터 구조로 보완 - 배너가 2개 이상이면 첫/마지막에 복제 아이템을 두어 경계에서 이어지는 수평 캐러셀 동작을 구현 - `MainHomeBannerSection`을 추가해 `RecommendationBannerResponse.imageUrl`을 `BannerCarouselItem`으로 매핑하고, 원본 배너를 상위 탭 콜백으로 전달하며, 데이터가 비어 있으면 섹션을 렌더링하지 않도록 구성 - `MainHomeRecommendationView`에서 현재 라이브 섹션 다음에 배너 섹션을 배치 - 배너 이동 규칙은 미확정 상태로 유지하고 탭 액션을 새로 구현하지 않음 - 리뷰어 지적에 따라 무한 캐러셀 경계 reset은 animation 비활성 transaction으로 처리하고, 인디케이터 trailing 위치를 현재 배너 내부 기준으로 보정 - 신규 `MainHomeBannerSection.swift`를 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - Figma `24:5525` 디자인 컨텍스트와 스크린샷 확인, 3개 수평 배너/간격 8/radius 14/우측 상단 `01 / 20` 인디케이터 확인 - `rg "SodaSpacing\.s8|SodaSpacing\.s14|BannerCarousel|GeometryReader|ScrollView|TabView|01|current|total|localhost:3845" SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift` 실행, 간격/radius/수평 캐러셀/페이지 인디케이터 근거 확인 및 `localhost:3845` 미포함 확인 - `rg "MainHomeBannerSection|BannerCarouselItem|BannerCarousel|banners|RecommendationBannerResponse" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Component/Banner` 실행, 추천 응답 `banners`가 배너 섹션과 `BannerCarousel`에 연결됨 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 - 전용 테스트 타깃이 검색되지 않아 새 테스트 인프라를 추가하지 않고 계획서의 정적/빌드/수동 시각 기준으로 검증 ### 2026-06-29 Phase 9 배너 섹션 Task 세분화 - 목적: `BannerCarousel`을 Figma `24:5525` 기준으로 구현할 수 있도록 Phase 9 작업을 실행 가능한 단위로 세분화 - 수행 내용: - 기존 단일 `Task 9.1`을 `Task 9.1`~`Task 9.4`로 분리 - `BannerCarousel` 현재 구조 확인, Figma 레이아웃 보완, 추천 홈 배너 섹션 연결, 빌드/시각 검증 단계로 분리 - 무한 스크롤, 좌우 배너 일부 노출, 배너 간격 8, 이미지 1:1 비율, 배너 width `device width - 40`, 우측 상단 페이지 인디케이터 요구사항 반영 - Figma 컨텍스트에서 확인한 radius 14와 `01 / 20` 형태 인디케이터를 구현 요구사항에 반영 - 검증: - Figma `24:5525` 디자인 컨텍스트와 스크린샷 확인, 수평 배너 3개 구성과 우측 상단 `01 / 20` 인디케이터 확인 - `rg "Task 9\\.[1-4]|device width - 40|1:1|간격은 8|무한 스크롤|24:5525|01 / 20" docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, Phase 9 세부 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_연동/plan-task.md` 실행, 출력 없이 성공 확인 ### 2026-06-29 Phase 8.1 현재 라이브 섹션 구현 완료 - 목적: V2 Main Home 추천 탭에 현재 라이브 섹션을 API 응답 데이터 기반으로 표시 - 수행 내용: - `MainHomeLiveSection`을 `Recommendation/Components` 아래에 추가하고 `HomeLiveItem.roomId`, `creatorNickname`, `creatorProfileImage`를 사용해 렌더링 - Figma `24:5518` 라이브 아이템 메타데이터(`70x102`)와 스크린샷을 기준으로 단일 아이템 프레임과 프로필 이미지/라이브 배지 배치를 보정 - `MainHomeLiveSection_Previews`에 `Live Item` 고정 크기 Preview와 `Live Section` Preview를 추가해 Xcode Preview에서 확인 가능하도록 구성 - 섹션 제목을 제거하고 `roomId`를 non-optional 응답 값으로 반영 - 데이터가 비어 있으면 `SectionTitle`과 가로 목록이 렌더링되지 않도록 구성 - `MainHomeRecommendationView`에는 Phase 8 현재 라이브 섹션만 조립하고, 아이템 탭 시 `MainView`에서 로그인 guard 후 `LiveViewModel.enterLiveRoom(roomId:)`로 전달되도록 연결 - `MainView`에 이미 배치된 `LivePaymentDialog`, `LiveRoomPasswordDialog`, `LiveRoomViewV2` 표시 흐름을 재사용 - 신규 Swift 파일을 `SodaLive.xcodeproj/project.pbxproj` 빌드 대상에 포함 - 검증: - Figma `24:5518` 메타데이터 확인 결과: `live` 노드 크기 `70x102`, 스크린샷 기준 원형 프로필/하단 `LIVE` 배지/닉네임 말줄임 구성 확인 - `rg "MainHomeLiveSection|roomId|creatorNickname|creatorProfileImage|enterLiveRoom|LivePaymentDialog|LiveRoomPasswordDialog" SodaLive/Sources/V2/Main/Home/Recommendation SodaLive/Sources/V2/Main/MainView.swift` 실행, 라이브 섹션 필드와 기존 입장 흐름 재사용 확인 - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `git diff --check` 실행, 출력 없이 성공 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 2026-06-29 추천 응답 모델 optionality 정렬 - 목적: PRD의 "서버 nullable 필드는 Swift optional" 기준에 맞춰 `MainHomeRecommendationResponse.swift` 모델 optionality를 정리 - 수행 내용: - PRD 응답 스펙에서 `?`가 없는 필드를 Swift non-optional로 변경 - `targetId`, `profileImage`, `originalWorkTitle`, `creatorProfileImage`, `imageUrl`, `audioUrl` 등 PRD nullable 필드는 optional 유지 - `RecommendationBannerResponse`는 백엔드 변경 스펙에 맞춰 `imageUrl`, `eventItem`, `creatorId`, `seriesId`, `link` 기준으로 정렬 - `HomeLiveItem.creatorNickname`, `creatorProfileImage`가 non-optional이 되면서 라이브 섹션의 불필요한 nil fallback 제거 - 검증: - `rg -n "let (roomId|activityType|activityAt|characterId|totalChatCount|genreName|creators|postId|createdAt|likeCount|commentCount|existOrdered): .*\\?" SodaLive/Sources/V2/Main/Home/Recommendation/Models/MainHomeRecommendationResponse.swift` 실행, 검색 결과 없음 확인 예정 - `rg -n "\\?\\? \"\"" SodaLive/Sources/V2/Main/Home/Recommendation/Components/MainHomeLiveSection.swift` 실행, 검색 결과 없음 확인 예정 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행 예정 ### 2026-06-29 Phase 7 중간 빌드 검증 완료 - 목적: Phase 4~6에서 생성/이동한 데이터 상태, 라우팅, 탭 루트 Swift 파일이 프로젝트 빌드 대상에 포함되어 있는지 중간 검증 - 수행 내용: - `SodaLive.xcodeproj/project.pbxproj` 수정 없이 현재 프로젝트 파일 유효성 확인 - `SodaLive-dev` Debug 빌드로 신규/이동 Swift 파일 포함 상태 확인 - Phase 7 `Task 7.1` 완료 체크 반영 - 검증: - `plutil -lint SodaLive.xcodeproj/project.pbxproj` 실행, `OK` 확인 - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 실행, `BUILD SUCCEEDED` 확인 ### 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` 등) 제거 - 배너는 변경된 백엔드 스펙에 맞춰 `eventItem`, `creatorId`, `seriesId`, `link` 중 첫 non-optional 값으로 이동 판단 - `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`, `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|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, 사업자 정보 요구사항을 PRD와 계획 문서에 반영하고, 기존 Phase를 섹션 단위 Phase로 재분류 - 수행 내용: - `prd.md`를 신규 응답 스펙 기준으로 갱신 - `plan-task.md`의 기존 Phase/완료 상태를 새 작업 분류 기준으로 재작성 - UI 작업은 현재 라이브, 배너, 최근 활동, 최근 데뷔, AI 캐릭터, 장르, 응원, 인기 커뮤니티, 사업자 정보 섹션별 Phase로 분리 - 기존 검증 기록은 아래에 보존 - 검증: - `rg "GET /api/v2/home/recommendations|RecommendationBannerResponse|FeedCommunityView|추천 필모그래피|또 다른 모습|node-id=309-19774|node-id=309-19775" docs/20260602_메인_홈_추천_UI_API_연동/prd.md docs/20260602_메인_홈_추천_UI_API_연동/plan-task.md` 실행, 신규 API/응답 타입/FeedCommunityView/제외 섹션/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` 확인