47 KiB
메인 콘텐츠 탭 내부 추천 탭 구현 계획
기준 문서
- PRD:
docs/20260705_메인_콘텐츠_내부_추천_탭/prd.md - 코드 스타일:
docs/agent-guides/code-style.md - 빌드/검증:
docs/agent-guides/build-test-verification.md - 문서 정책:
docs/agent-guides/documentation-policy.md - Figma 전체 화면:
https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=24-6737&m=dev - Figma 전체 화면 node:
24:6737 - Figma title bar:
24:6738 - Figma 배너:
24:6741 - Figma 새로 올라온 오디오:
24:6751 - Figma New&Hot:
24:6758 - Figma 오직 보이스온에서만:
24:6745 - Figma 추천 시리즈:
24:6770(이번 범위 제외) - Figma 무료 오디오:
24:6807 - Figma 포인트 오디오:
24:6813 - Figma 크리에이터의 댓글 많은 오디오:
24:6820 - Figma 키워드의 오디오:
24:6829(이번 범위 제외) - Figma 추천 오디오:
24:6842
요구사항 요약
- 메인 하단
콘텐츠탭 안에 내부추천탭 화면을 구현한다. - API endpoint는
GET /api/v2/audio/recommendations를 사용한다. - title bar와 내부 tab bar는 고정하고, 배너부터 하위 콘텐츠만 세로 스크롤한다.
- title bar는 Figma
24:6738기준으로 좌측에 메인 탭명콘텐츠, 우측에cash/search/storage액션을 표시한다. - Figma에 보이는 섹션별로 Phase를 분리한다.
- 이번 범위에서
추천 시리즈,키워드의 오디오는 구현하지 않는다. V2패키지 하위에 구현된 재사용 가능한 위젯 후보를 먼저 확인하고 필요한 경우 최소 보완한다.오직 보이스온에서만!섹션은 보이스온 전용 시리즈 표시를 사용한다.ONLY표시는ic_series_original과img_new_only조합을 우선 재사용한다.- Figma localhost asset URL은 앱 코드에 넣지 않는다.
PRD 반영 기준
- PRD
7.1 API,7.2 Response model은 Phase 2에서 처리한다. - PRD
7.3 Fixed shell and scrolling은 Phase 1에서 처리한다. - PRD
7.4 Section visibility는 Phase 2 ViewModel과 각 섹션 Phase에서 처리한다. - PRD
7.5 구현 대상 섹션은 Phase 3~10에서 Figma 노드 순서대로 처리한다. - PRD
7.6 제외 대상 섹션은 Phase 11에서 검증한다. - PRD
7.7 Tag display는 Phase 4의MainContentAudioTagOverlay를 기준으로 이후 섹션에서 재사용한다. - PRD
7.8 Navigation은 Phase 3의 배너 callback 설계, Phase 6의 original series 탭, Phase 12의 전체 라우팅 검증에서 처리한다. - PRD
8. UX / UI Expectations중크리에이터의 댓글 많은 오디오댓글 preview bubble에는 nickname을 표시하지 않는다. - PRD
10. Success Criteria는 Phase 12의 빌드 검증과 각 Phase 검증 기준으로 확인한다. - PRD
11. Open Questions는 현재미결정 사항 없음이므로 계획 문서에 구현 보류 항목을 남기지 않는다.
접근안 검토
- 선택안:
SodaLive/Sources/V2/Main/Content/Recommendation/**하위에 API, 모델, ViewModel, 화면, 섹션 컴포넌트를 분리한다.- 장점: 기존
MainHomeRecommendation,MainHomeRanking,MainHomeFollowing구조와 가장 유사하고MainView의.contentplaceholder를 작게 교체할 수 있다. - 단점: 기존 legacy
SodaLive/Sources/Content/**와 별도 경로가 생긴다.
- 장점: 기존
- 대안 1: legacy
SodaLive/Sources/Content/**하위에 구현한다.- 장점: 기존 콘텐츠 전체/상세 화면과 가깝다.
- 단점: 신규 V2 우선 원칙과 맞지 않고 SwiftUI/V2 컴포넌트 재사용 흐름이 약해진다.
- 대안 2:
MainHomeRecommendation의 컴포넌트를 직접 확장한다.- 장점: 홈 추천 구현 일부를 바로 가져올 수 있다.
- 단점: 홈 추천과 콘텐츠 추천은 endpoint, 응답 모델, 섹션 구성이 달라 결합도가 커진다.
구현 원칙
- 신규 코드는
SodaLive/Sources/V2/Main/Content/Recommendation/**아래에 둔다. - 여러 화면에서 재사용 근거가 있는 UI만
SodaLive/Sources/V2/Component/**로 승격한다. MainView는.content탭에서 신규 콘텐츠 탭 root를 보여주고, 상세 진입 guard callback만 전달한다.- 콘텐츠 탭 root는 title bar와 내부 tab bar를 고정 영역으로 두고, 추천 탭 body 내부에서만
ScrollView를 사용한다. - 콘텐츠 탭 root의 title bar는
DefaultTitleBar(title: MainTab.content.title)를 사용하고, 홈 탭은 기존HomeTitleBar를 유지한다. - 섹션 배열이 비어 있으면 해당 섹션을 숨긴다.
- 전체 응답이 비어 있거나 API 실패/디코딩 실패 시 최소 empty 또는 error 상태를 표시한다.
- 오디오 상세 진입은 기존
handleRecommendationContentTap(contentId:)의 로그인/성인 콘텐츠 guard 흐름을 재사용한다. - 배너 탭은
eventItem,creatorId,seriesId,link매핑을 명시적으로 분기한다. seriesId는AppStep.seriesDetail(seriesId:)route로 연결한다.link는AppDeepLinkHandler.handle(urlString:)로 deep link를 먼저 확인하고, deep link가 아니면UIApplication.shared.open으로 외부 브라우저를 연다.- 외부 라이브러리는 추가하지 않는다.
API 응답 모델 기준
AudioRecommendationsResponsebanners: [AudioBannerResponse]originalSeries: [OriginalSeriesResponse]latestAudios: [AudioCardResponse]newAndHotAudios: [AudioCardResponse]freeAudios: [AudioCardResponse]pointAudios: [AudioCardResponse]mostCommentedAudios: [CommentedAudioResponse]recommendedAudios: [AudioCardResponse]
AudioBannerResponseimageUrl,eventItem,creatorId,seriesId,link
OriginalSeriesResponseseriesId,coverImageUrl
AudioCardResponseaudioContentId,title,duration,imageUrl,priceisAdult,isPointAvailable,isFirstContent,isOriginalSeries,creatorNickname
CommentedAudioResponseaudioContentId,title,imageUrl,latestComment,latestCommentWriterProfileImageUrl
재사용 가능한 V2 위젯 후보
SodaLive/Sources/V2/Component/DefaultTitleBar.swift- 콘텐츠 탭 title bar의 좌측 고정 title과 우측 액션 영역 기준 후보.
SodaLive/Sources/V2/Component/HomeTitleBar.swift- 홈 탭 title bar 기준 후보이며, 콘텐츠 탭에는 사용하지 않는다.
SodaLive/Sources/V2/Component/TextTabBar.swift- 내부
추천탭 bar 구성 후보.
- 내부
SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift- 배너 carousel 후보. 메인 홈 추천 탭과 동일한 1:1 비율, 무한 슬라이딩, 자동 슬라이딩 동작을 재사용한다.
SodaLive/Sources/V2/Component/SectionTitle.swift- 섹션 제목과 우측 chevron 표시 후보.
SodaLive/Sources/V2/Component/AudioContentCard.swift새로 올라온 오디오,무료 오디오,포인트 오디오,추천 오디오카드 후보. 태그 overlay가 없으므로 썸네일 overlay 슬롯 추가 또는 새 wrapper 컴포넌트 검토가 필요하다.
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swiftNew&Hot,크리에이터의 댓글 많은 오디오list row의 크기, 태그, 가격 표시 로직 참고 후보.
SodaLive/Sources/V2/CreatorChannel/Series/Components/CreatorChannelSeriesListItem.swiftic_series_original+img_new_only기반ONLY표시 참고 후보.
SodaLive/Resources/Assets.xcassets/v2/ic_series_original.imageset- 보이스온 전용 original 아이콘 asset.
SodaLive/Resources/Assets.xcassets/v2/img_new_only.imageset- 보이스온 전용
ONLY표시 asset.
- 보이스온 전용
주요 대상 파일
생성
SodaLive/Sources/V2/Main/Content/MainContentView.swiftSodaLive/Sources/V2/Main/Content/MainContentTab.swiftSodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationView.swiftSodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationViewModel.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Models/AudioRecommendationsResponse.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Repository/MainContentRecommendationApi.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Repository/MainContentRecommendationRepository.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioBannerSection.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentVoiceOnOnlySection.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioTagOverlay.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioEmptyStateView.swift
수정
SodaLive/Sources/V2/Main/MainView.swiftSodaLive/Sources/I18n/I18n.swift- 필요 시
SodaLive/Sources/V2/Component/AudioContentCard.swift - 필요 시
SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift - 필요 시
SodaLive.xcodeproj/project.pbxproj
확인
SodaLive/Sources/V2/Main/Home/MainHomeView.swiftSodaLive/Sources/V2/Main/Home/Recommendation/Repository/MainHomeRecommendationApi.swiftSodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationViewModel.swiftSodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swiftSodaLive/Sources/V2/CreatorChannel/Series/Components/CreatorChannelSeriesListItem.swiftSodaLive/Sources/V2/Component/AudioContentCard.swiftSodaLive/Sources/V2/Component/Banner/BannerCarousel.swiftSodaLive/Sources/V2/Component/SectionTitle.swiftSodaLive/Sources/V2/Component/TextTabBar.swiftSodaLive/Sources/App/AppDeepLinkHandler.swiftSodaLive/Sources/App/AppStep.swiftSodaLive/Sources/ContentView.swift
TASK 체크리스트
Phase 1: 기준점 점검과 콘텐츠 탭 shell 설계
-
Task 1.1: Figma와 기존 탭 구조 확인
- 대상 파일:
- 확인:
docs/20260705_메인_콘텐츠_내부_추천_탭/prd.md - 확인:
docs/20260705_메인_콘텐츠_내부_추천_탭/plan-task.md - 확인:
SodaLive/Sources/V2/Main/MainView.swift - 확인:
SodaLive/Sources/V2/Main/MainTab.swift - 확인:
SodaLive/Sources/V2/Main/Home/MainHomeView.swift
- 확인:
- 작업 내용:
- PRD의 Goals, Non-Goals, Core Requirements, Success Criteria를 다시 읽고 구현 범위를 확정한다.
.content탭이 현재MainPlaceholderTabView인지 확인한다.- 홈 탭의 title bar + tab bar + content 분리 구조를 참고한다.
- Figma
24:6737에서 title bar와 tab bar가 고정이고24:6741배너부터 스크롤 대상임을 확인한다.
- 검증 기준:
- 실행 명령:
rg "GET /api/v2/audio/recommendations|추천 시리즈|키워드의 오디오|Open Questions|미결정 사항 없음|seriesDetail|AppDeepLinkHandler|nickname" docs/20260705_메인_콘텐츠_내부_추천_탭/prd.md && sed -n '140,190p' SodaLive/Sources/V2/Main/MainView.swift && sed -n '1,120p' SodaLive/Sources/V2/Main/Home/MainHomeView.swift - 기대 결과: PRD의 확정 범위가 확인되고,
.content는 placeholder이며,MainHomeView는 fixed shell과 tab content를 분리한다.
- 실행 명령:
- 대상 파일:
-
Task 1.2: 내부 콘텐츠 탭 root 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/MainContentView.swift - 생성:
SodaLive/Sources/V2/Main/Content/MainContentTab.swift - 수정:
SodaLive/Sources/V2/Main/MainView.swift
- 생성:
- 작업 내용:
MainContentTab에 이번 범위의 내부recommendationcase를 둔다.MainContentView는 title bar와 내부 tab bar를 고정 영역으로 배치한다.- 추천 탭 콘텐츠만
MainContentRecommendationView로 분리한다. MainView의.contentplaceholder를MainContentView로 교체한다.
- 검증 기준:
- 실행 명령:
rg "enum MainContentTab|struct MainContentView|MainContentRecommendationView|case \\.content" SodaLive/Sources/V2/Main - 기대 결과: 콘텐츠 탭 root와 추천 탭 분기가 확인되고,
.contentplaceholder가 제거된다.
- 실행 명령:
- 대상 파일:
Phase 2: API, Repository, Response model, ViewModel
-
Task 2.1: 추천 오디오 응답 모델 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Models/AudioRecommendationsResponse.swift
- 생성:
- 작업 내용:
- 사용자 제공 Kotlin response class를 Swift
Decodable구조체로 대응한다. - id가 있는 항목은
Identifiable을 채택하고Int또는Int64대신 기존 프로젝트 관례에 맞춰Int를 우선 사용한다. @JsonProperty("isAdult"),@JsonProperty("isPointAvailable")등isprefix boolean은 Swift property명을 그대로 둔다.EventItem타입은 기존 모델을 재사용한다.
- 사용자 제공 Kotlin response class를 Swift
- 검증 기준:
- 실행 명령:
rg "struct AudioRecommendationsResponse|struct AudioBannerResponse|struct OriginalSeriesResponse|struct AudioCardResponse|struct CommentedAudioResponse|isAdult|isPointAvailable|isFirstContent|isOriginalSeries" SodaLive/Sources/V2/Main/Content/Recommendation/Models/AudioRecommendationsResponse.swift - 기대 결과: API 응답 필드가 모두 Swift 모델에 반영된다.
- 실행 명령:
- 대상 파일:
-
Task 2.2: 추천 오디오 API endpoint 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Repository/MainContentRecommendationApi.swift - 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Repository/MainContentRecommendationRepository.swift - 확인:
SodaLive/Sources/V2/Main/Home/Recommendation/Repository/MainHomeRecommendationApi.swift
- 생성:
- 작업 내용:
MainContentRecommendationApi를TargetType으로 만든다.- case는
getAudioRecommendations하나만 둔다. - path는
/api/v2/audio/recommendations, method는.get, task는.requestPlain로 둔다. - headers는 기존 V2 홈 API와 동일하게
Authorization: Bearer {token}패턴을 따른다. - repository는
getAudioRecommendations() -> AnyPublisher<Response, MoyaError>를 제공한다.
- 검증 기준:
- 실행 명령:
rg "/api/v2/audio/recommendations|getAudioRecommendations|Authorization|AnyPublisher<Response, MoyaError>" SodaLive/Sources/V2/Main/Content/Recommendation/Repository - 기대 결과: 신규 endpoint와 repository 메서드가 추천 오디오 전용 경로에만 존재한다.
- 실행 명령:
- 대상 파일:
-
Task 2.3: ViewModel 생성과 섹션 표시 상태 정리
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationViewModel.swift - 수정:
SodaLive/Sources/I18n/I18n.swift
- 생성:
- 작업 내용:
MainContentRecommendationViewModel을ObservableObject로 만든다.isLoading,isShowPopup,errorMessage,recommendations,hasLoaded상태를 둔다.fetchRecommendations()에서ApiResponse<AudioRecommendationsResponse>를 디코딩한다.- 섹션별 배열이 모두 비어 있으면
I18n.MainContentRecommendation.emptyStateMessage를 표시할 수 있게 한다. - 실패 시 기존 V2 홈 추천과 같은 toast/popup 흐름 또는 empty state 중 하나를 선택하되, 사용자 노출 문구는 I18n에 ko/en/ja로 둔다.
- 검증 기준:
- 실행 명령:
rg "final class MainContentRecommendationViewModel|fetchRecommendations|ApiResponse<AudioRecommendationsResponse>|hasLoaded|emptyStateMessage|ko:|en:|ja:" SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationViewModel.swift SodaLive/Sources/I18n/I18n.swift - 기대 결과: API 디코딩, 로딩/실패/empty 상태, I18n ko/en/ja 문구가 확인된다.
- 실행 명령:
- 대상 파일:
Phase 3: 배너 섹션
- Task 3.1: 배너 섹션 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioBannerSection.swift - 확인/보완:
SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift
- 생성:
- 작업 내용:
- Figma
24:6741기준으로 배너 carousel을 표시한다. AudioBannerResponse.imageUrl을BannerCarouselItem또는 신규 display model로 변환한다.- page indicator는
01 / 20형식을 유지한다. - 배너 탭 시
eventItem,creatorId,seriesId,link를 상위 callback으로 전달한다. seriesId가 있으면seriesDetailroute로 이동할 수 있도록 callback을 설계한다.link가 있으면 deep link 처리 결과가true인지 먼저 확인하고, 처리되지 않은 URL만 외부 브라우저로 연다.- 기존
BannerCarousel이 정사각형 고정 높이를 강제하면, 콘텐츠 추천 배너 전용 wrapper에서 Figma 비율을 맞추거나 공용 컴포넌트를 최소 보완한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "MainContentAudioBannerSection|BannerCarousel|AudioBannerResponse|imageUrl|eventItem|creatorId|seriesId|link|seriesDetail|AppDeepLinkHandler|UIApplication.shared.open" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/V2/Main/MainView.swift SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift - 기대 결과: 배너 섹션이 API 응답과 탭 callback을 연결한다.
- 실행 명령:
- 대상 파일:
Phase 4: 새로 올라온 오디오 섹션
- Task 4.1: 가로 카드 섹션 공통 컴포넌트 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift - 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioTagOverlay.swift - 확인/보완:
SodaLive/Sources/V2/Component/AudioContentCard.swift
- 생성:
- 작업 내용:
- Figma
24:6751의새로 올라온 오디오를latestAudios로 표시한다. AudioContentCard(size: .medium)를 우선 재사용한다.isOriginalSeries,isFirstContent,isPointAvailable,price == 0,isAdult상태를 태그 overlay로 표시한다.- 카드 탭 시
onTapContent(audioContentId)를 호출한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "MainContentAudioHorizontalCardSection|MainContentAudioTagOverlay|latestAudios|AudioContentCard|isOriginalSeries|isFirstContent|isPointAvailable|price == 0|isAdult|onTapContent" SodaLive/Sources/V2/Main/Content/Recommendation - 기대 결과: 최신 오디오 카드와 태그 overlay 조건이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 5: New&Hot 섹션
- Task 5.1: New&Hot list carousel 섹션 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift - 확인:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swift
- 생성:
- 작업 내용:
- Figma
24:6758의New&Hot을newAndHotAudios로 표시한다. - 한 페이지에 3개 list row를 세로로 묶고, 묶음 단위로 가로 스크롤한다.
- row는 88pt 썸네일, 제목 한 줄, creator nickname 한 줄 구조를 따른다.
MainContentAudioTagOverlay를 list thumbnail에도 재사용한다.- row 탭 시
onTapContent(audioContentId)를 호출한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "MainContentAudioListCarouselSection|newAndHotAudios|chunk|MainContentAudioTagOverlay|onTapContent" SodaLive/Sources/V2/Main/Content/Recommendation - 기대 결과: New&Hot 섹션이 3-row 묶음 가로 carousel로 구성된다.
- 실행 명령:
- 대상 파일:
Phase 6: 오직 보이스온에서만 섹션
- Task 6.1: 보이스온 전용 시리즈 섹션 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentVoiceOnOnlySection.swift - 확인:
SodaLive/Sources/V2/CreatorChannel/Series/Components/CreatorChannelSeriesListItem.swift - 확인:
SodaLive/Resources/Assets.xcassets/v2/ic_series_original.imageset - 확인:
SodaLive/Resources/Assets.xcassets/v2/img_new_only.imageset
- 생성:
- 작업 내용:
- Figma
24:6745의오직 보이스온에서만!을originalSeries로 표시한다. - 이번 섹션은
OriginalSeriesResponse.seriesId,coverImageUrl만 사용한다. - 카드 상단에는
ic_series_original+img_new_only조합으로ONLY표시를 붙인다. 추천 시리즈카드형 상세 정보는 이번 범위에서 만들지 않는다.- 카드 탭 시
onTapSeries(seriesId)를 호출하고 상위에서AppStep.seriesDetail(seriesId:)로 이동한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "MainContentVoiceOnOnlySection|originalSeries|OriginalSeriesResponse|ic_series_original|img_new_only|onTapSeries|seriesDetail" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/V2/Main/MainView.swift SodaLive/Resources/Assets.xcassets/v2 - 기대 결과: 보이스온 전용
ONLY표시와seriesDetail진입 연결이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 7: 무료 오디오 섹션
- Task 7.1: 무료 오디오 섹션 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationView.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift
- 수정:
- 작업 내용:
- Figma
24:6807의무료 오디오를freeAudios로 표시한다. price == 0또는 API 섹션 성격에 따라 무료 태그를 표시한다.- 섹션 배열이 비어 있으면 숨긴다.
- Figma
- 검증 기준:
- 실행 명령:
rg "freeAudios|무료 오디오|MainContentAudioHorizontalCardSection" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/I18n/I18n.swift - 기대 결과: 무료 오디오 섹션이 View에 조립된다.
- 실행 명령:
- 대상 파일:
Phase 8: 포인트 오디오 섹션
- Task 8.1: 포인트 오디오 섹션 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationView.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift
- 수정:
- 작업 내용:
- Figma
24:6813의포인트 오디오를pointAudios로 표시한다. isPointAvailable상태에 따라 포인트 태그를 표시한다.- 섹션 배열이 비어 있으면 숨긴다.
- Figma
- 검증 기준:
- 실행 명령:
rg "pointAudios|포인트 오디오|isPointAvailable|MainContentAudioHorizontalCardSection" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/I18n/I18n.swift - 기대 결과: 포인트 오디오 섹션과 포인트 태그 조건이 확인된다.
- 실행 명령:
- 대상 파일:
Phase 9: 크리에이터의 댓글 많은 오디오 섹션
- Task 9.1: 댓글 카드 carousel 섹션 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swift
- 생성:
- 작업 내용:
- Figma
24:6820의크리에이터의 댓글 많은 오디오를mostCommentedAudios로 표시한다. - 오디오 row와 댓글 preview bubble을 하나의 카드로 묶고, 카드 단위로 가로 스크롤한다.
latestComment를 댓글 본문으로 표시한다.latestCommentWriterProfileImageUrl을 댓글 작성자 profile image로 표시한다.- 댓글 preview bubble에는 nickname을 표시하지 않는다.
CommentedAudioResponse에는 creator nickname이 없으므로 댓글 영역에 nickname용 UI나 placeholder를 추가하지 않는다.- 카드 탭 시
onTapContent(audioContentId)를 호출한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "MainContentMostCommentedAudioSection|mostCommentedAudios|CommentedAudioResponse|latestComment|latestCommentWriterProfileImageUrl|onTapContent" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swift SodaLive/Sources/V2/Main/Content/Recommendation/Models/AudioRecommendationsResponse.swift - 기대 결과: 최근 댓글 섹션은 실제 댓글 본문, 댓글 작성자 profile image, 오디오 탭 callback을 사용한다.
- 실행 명령:
rg "nickname|creatorNickname" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swift - 기대 결과: 검색 결과가 없어야 한다. 댓글 bubble에는 nickname을 표시하지 않는다.
- 실행 명령:
- 대상 파일:
Phase 10: 추천 오디오 섹션
- Task 10.1: 추천 오디오 grid 섹션 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift - 수정:
SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationView.swift
- 생성:
- 작업 내용:
- Figma
24:6842의추천 오디오를recommendedAudios로 표시한다. - 2열 grid를 구성한다.
- 카드 크기는 부모 width 기반으로 계산하고, 고정 숫자 width만으로 화면을 제한하지 않는다.
MainContentAudioTagOverlay를 재사용한다.- grid item 탭 시
onTapContent(audioContentId)를 호출한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "MainContentRecommendedAudioGridSection|recommendedAudios|LazyVGrid|GridItem\\(\\.flexible|MainContentAudioTagOverlay|onTapContent" SodaLive/Sources/V2/Main/Content/Recommendation - 기대 결과: 추천 오디오 2열 grid와 태그 overlay가 확인된다.
- 실행 명령:
- 대상 파일:
Phase 11: 제외 섹션 미구현 확인
- Task 11.1: 추천 시리즈와 키워드의 오디오 제외 확인
- 대상 파일:
- 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/**
- 확인:
- 작업 내용:
- Figma
24:6770의추천 시리즈컴포넌트는 생성하지 않는다. - Figma
24:6829의#키워드의 오디오컴포넌트는 생성하지 않는다. originalSeries는오직 보이스온에서만!섹션에만 사용한다.
- Figma
- 검증 기준:
- 실행 명령:
rg "추천 시리즈|Keyword|키워드의 오디오|RecommendedSeries" SodaLive/Sources/V2/Main/Content/Recommendation - 기대 결과: 이번 범위 제외 섹션 구현 파일/문구가 검색되지 않는다.
- 실행 명령:
- 대상 파일:
Phase 12: 라우팅, 프로젝트 포함, 전체 검증
-
Task 12.1: 상세 진입 callback 연결
- 대상 파일:
- 수정:
SodaLive/Sources/V2/Main/MainView.swift - 확인:
SodaLive/Sources/App/AppStep.swift - 확인:
SodaLive/Sources/ContentView.swift
- 수정:
- 작업 내용:
- 오디오 카드/list/grid 탭은 기존 content detail guard callback을 재사용한다.
eventItem배너는 기존 event detail 흐름이 있으면 재사용한다.- creator 이동이 필요한 배너는 기존 creator detail guard callback을 재사용한다.
seriesId배너와originalSeries탭은AppStep.seriesDetail(seriesId:)route로 연결한다.link배너는AppDeepLinkHandler.handle(urlString:)로 deep link를 먼저 체크한다.- deep link가 아니면
UIApplication.shared.open으로 외부 브라우저를 연다.
- 검증 기준:
- 실행 명령:
rg "contentDetail|eventItem|eventDetail|creatorDetail|seriesDetail|AppDeepLinkHandler|UIApplication.shared.open|MainContentView" SodaLive/Sources/V2/Main/MainView.swift SodaLive/Sources/App/AppStep.swift SodaLive/Sources/ContentView.swift - 기대 결과: 상세 진입과 event/creator/series route가 기존 route와 guard 흐름을 재사용하고, link는 deep link 우선 후 외부 브라우저로 처리한다.
- 실행 명령:
- 대상 파일:
-
Task 12.2: 프로젝트 포함 및 빌드 검증
- 대상 파일:
- 확인/보완:
SodaLive.xcodeproj/project.pbxproj - 확인:
SodaLive/Sources/V2/Main/Content/**
- 확인/보완:
- 작업 내용:
- 생성한 Swift 파일이 빌드 대상에 포함되는지 확인한다.
- 파일 시스템 동기화 방식으로 자동 포함되면 project file은 수정하지 않는다.
- 프로젝트 파일 수정이 필요할 때만 최소 변경한다.
- 검증 기준:
- 실행 명령:
plutil -lint SodaLive.xcodeproj/project.pbxproj - 기대 결과:
OK - 실행 명령:
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build - 기대 결과:
BUILD SUCCEEDED
- 실행 명령:
- 대상 파일:
Phase 13: 오디오 row 공용 컴포넌트 정리
-
Task 13.1: 공용 오디오 list row 컴포넌트 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Component/AudioContent/AudioContentListRow.swift - 확인:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelHomeAudioContentListItem.swift - 확인:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swift
- 생성:
- 작업 내용:
- 크리에이터 채널 홈 탭 오디오 item과 크리에이터 채널 오디오 탭 item의 공통 row 구조를 기반으로
AudioContentListRow를 만든다. - 표시 데이터는 API 모델에 직접 의존하지 않는
AudioContentListRowItem으로 둔다. - 표시 변형은
AudioContentListRowStyle.compact(width:),AudioContentListRowStyle.purchaseState로 분리한다. compact는 title 1줄, subtitle 1줄, trailing 상태 없음으로 구성한다.purchaseState는 title 2줄, duration subtitle, owned/rented/free/price trailing 상태를 표시한다.- 기존 tag asset 조합(
ic_content_tag_original,ic_content_tag_first_star,ic_content_tag_point,ic_new_shield_small,무료)을 공용 row 안에서 재사용한다.
- 크리에이터 채널 홈 탭 오디오 item과 크리에이터 채널 오디오 탭 item의 공통 row 구조를 기반으로
- 검증 기준:
- 실행 명령:
rg "struct AudioContentListRow|struct AudioContentListRowItem|enum AudioContentListRowStyle|case compact|case purchaseState|ic_content_tag_original|ic_content_tag_point|ic_content_tag_first_star|ic_new_shield_small" SodaLive/Sources/V2/Component/AudioContent/AudioContentListRow.swift - 기대 결과: 공용 row, 표시 모델, style enum, tag asset 사용이 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 13.2: 메인 콘텐츠 추천 New&Hot에 공용 row 적용
- 대상 파일:
- 수정:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift
- 수정:
- 작업 내용:
- 기존 private
row(_:)직접 구현을 제거한다. AudioCardResponse를AudioContentListRowItem으로 매핑한다.- subtitle은 Figma 기준
creatorNickname을 사용한다. - style은
.compact(width: UIScreen.main.bounds.width - (SodaSpacing.s20 * 2))또는 동일한 column 폭 기준으로 사용한다.
- 기존 private
- 검증 기준:
- 실행 명령:
rg "AudioContentListRow|AudioContentListRowItem|\.compact|creatorNickname|private func row|MainContentAudioTagOverlay" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift - 기대 결과: 공용 row 사용이 확인되고, 기존 private row와
MainContentAudioTagOverlay의존이 제거된다.
- 실행 명령:
- 대상 파일:
-
Task 13.3: 크리에이터 채널 홈 오디오 섹션에 공용 row 적용
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift
- 수정:
- 작업 내용:
CreatorChannelHomeAudioContentListItem사용을 제거한다.CreatorChannelAudioContentResponse를AudioContentListRowItem으로 매핑한다.- subtitle은 기존과 동일하게
duration과seriesName을•로 조합한다. - style은 기존 row 폭과 동일하게
.compact(width: 346)을 사용한다.
- 검증 기준:
- 실행 명령:
rg "AudioContentListRow|AudioContentListRowItem|\.compact\(width: 346\)|CreatorChannelHomeAudioContentListItem" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift - 기대 결과: 공용 row 사용이 확인되고 기존 home item 참조는 없어야 한다.
- 실행 명령:
- 대상 파일:
-
Task 13.4: 크리에이터 채널 오디오/라이브 replay 탭에 공용 row 적용
- 대상 파일:
- 수정:
SodaLive/Sources/V2/CreatorChannel/Audio/CreatorChannelAudioTabView.swift - 수정:
SodaLive/Sources/V2/CreatorChannel/Live/CreatorChannelLiveTabView.swift
- 수정:
- 작업 내용:
CreatorChannelAudioContentListItem사용을 제거한다.CreatorChannelAudioContentResponse를AudioContentListRowItem으로 매핑한다.- style은
.purchaseState를 사용해 기존 가격/소유/대여/무료 재생 상태를 유지한다.
- 검증 기준:
- 실행 명령:
rg "AudioContentListRow|AudioContentListRowItem|\.purchaseState|CreatorChannelAudioContentListItem" SodaLive/Sources/V2/CreatorChannel/Audio/CreatorChannelAudioTabView.swift SodaLive/Sources/V2/CreatorChannel/Live/CreatorChannelLiveTabView.swift - 기대 결과: 공용 row 사용이 확인되고 기존 audio item 참조는 없어야 한다.
- 실행 명령:
- 대상 파일:
-
Task 13.5: 미사용 기존 item 컴포넌트 삭제와 프로젝트 정리
- 대상 파일:
- 삭제:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelHomeAudioContentListItem.swift - 삭제:
SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swift - 확인/보완:
SodaLive.xcodeproj/project.pbxproj
- 삭제:
- 작업 내용:
- 공용 row 적용 후 참조가 사라진 기존 item 컴포넌트 파일을 삭제한다.
- Xcode project의 file reference/build phase에서 삭제 파일을 제거하고 신규 공용 파일을 추가한다.
- 검증 기준:
- 실행 명령:
! rg "CreatorChannelHomeAudioContentListItem|CreatorChannelAudioContentListItem" SodaLive/Sources/V2 - 기대 결과: 삭제한 기존 item 컴포넌트 참조가 남아 있지 않아야 한다.
- 실행 명령:
plutil -lint SodaLive.xcodeproj/project.pbxproj - 기대 결과:
OK
- 실행 명령:
- 대상 파일:
-
Task 13.6: 공용 오디오 row 리팩터링 빌드 검증
- 대상 파일:
- 확인:
SodaLive/Sources/V2/Component/AudioContent/AudioContentListRow.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift - 확인:
SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift - 확인:
SodaLive/Sources/V2/CreatorChannel/Audio/CreatorChannelAudioTabView.swift - 확인:
SodaLive/Sources/V2/CreatorChannel/Live/CreatorChannelLiveTabView.swift
- 확인:
- 작업 내용:
- New&Hot, 크리에이터 채널 홈 오디오, 크리에이터 채널 오디오 탭, 라이브 replay 탭이 공용 row를 사용하도록 최종 확인한다.
SodaLive-dev빌드를 실행한다.
- 검증 기준:
- 실행 명령:
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build - 기대 결과:
BUILD SUCCEEDED
- 실행 명령:
- 대상 파일:
Phase 14: 오디오 card 공용 컴포넌트 정리
-
Task 14.1: 공용 오디오 card 컴포넌트 생성
- 대상 파일:
- 생성:
SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioTagOverlay.swift
- 생성:
- 작업 내용:
- 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 추천 오디오 섹션에서 공통으로 쓰는 카드형 오디오 item 컴포넌트를 만든다.
- 표시 데이터는 API 모델에 직접 의존하지 않는
AudioContentThumbnailCardItem으로 둔다. - title/subtitle typography는 기존
AudioContentCardSize규칙을 유지한다. - 이미지 좌측 상단에는 오리지널, 처음 업로드 오디오 태그를 표시한다.
- 이미지 우측 상단에는
isAdultshield 태그를 표시한다. - 이미지 좌측 하단에는 포인트, 무료 태그를 표시한다.
- 태그는 Figma node
567:18089,567:18090,567:18124,567:18272기준으로ic_content_tag_original,ic_content_tag_first_star,ic_content_tag_point,ic_new_shield_small,무료조합을 사용한다.
- 검증 기준:
- 실행 명령:
rg "struct AudioContentThumbnailCard|struct AudioContentThumbnailCardItem|ic_content_tag_original|ic_content_tag_first_star|ic_content_tag_point|ic_new_shield_small|무료" SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swift - 기대 결과: 공용 카드, 표시 모델, Figma 기준 태그 조합이 확인된다.
- 실행 명령:
- 대상 파일:
-
Task 14.2: 새로 올라온/무료/포인트 오디오 섹션에 공용 card 적용
- 대상 파일:
- 수정:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift
- 수정:
- 작업 내용:
AudioContentCard와MainContentAudioTagOverlay조합을 제거한다.AudioCardResponse를AudioContentThumbnailCardItem으로 매핑한다.- 기존과 동일하게 medium 카드 크기, title, creatorNickname subtitle을 유지한다.
- 검증 기준:
- 실행 명령:
rg "AudioContentThumbnailCard|AudioContentThumbnailCardItem|AudioContentCard\(|MainContentAudioTagOverlay" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift - 기대 결과: 공용 카드 사용이 확인되고 기존 직접 조합은 없어야 한다.
- 실행 명령:
- 대상 파일:
-
Task 14.3: 추천 오디오 grid 섹션에 공용 card 적용
- 대상 파일:
- 수정:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift
- 수정:
- 작업 내용:
- 기존 thumbnail/tag/title/subtitle 직접 구현을 제거한다.
GeometryReader에서 계산한 width를 공용 card에 전달한다.- 기존과 동일하게 grid item의
aspectRatio(0.78, contentMode: .fit)흐름을 유지한다.
- 검증 기준:
- 실행 명령:
rg "AudioContentThumbnailCard|AudioContentThumbnailCardItem|MainContentAudioTagOverlay|DownsampledKFImage|Text\(item.title\)" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift - 기대 결과: 공용 카드 사용이 확인되고 grid 내부 직접 구현은 없어야 한다.
- 실행 명령:
- 대상 파일:
-
Task 14.4: 기존 main content tag overlay 삭제와 프로젝트 정리
- 대상 파일:
- 삭제:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioTagOverlay.swift - 확인/보완:
SodaLive.xcodeproj/project.pbxproj
- 삭제:
- 작업 내용:
- 공용 card 적용 후 사용하지 않는 기존 main content 전용 tag overlay를 삭제한다.
- Xcode project의 file reference/build phase에서 삭제 파일을 제거하고 신규 공용 파일을 추가한다.
- 검증 기준:
- 실행 명령:
! rg "MainContentAudioTagOverlay" SodaLive/Sources/V2 SodaLive.xcodeproj/project.pbxproj - 기대 결과: 기존 tag overlay 참조가 남아 있지 않아야 한다.
- 실행 명령:
plutil -lint SodaLive.xcodeproj/project.pbxproj - 기대 결과:
OK
- 실행 명령:
- 대상 파일:
-
Task 14.5: 공용 오디오 card 리팩터링 빌드 검증
- 대상 파일:
- 확인:
SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift - 확인:
SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift
- 확인:
- 작업 내용:
- 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 추천 오디오 섹션이 공용 card를 사용하도록 최종 확인한다.
SodaLive-dev빌드를 실행한다.
- 검증 기준:
- 실행 명령:
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build - 기대 결과:
BUILD SUCCEEDED
- 실행 명령:
- 대상 파일:
검증 기록
-
2026-07-05 문서 작성:
- 실행/확인:
docs/agent-guides/documentation-policy.mddocs/agent-guides/build-test-verification.mddocs/agent-guides/code-style.mdSodaLive/Sources/V2/Main/Home/MainHomeView.swiftSodaLive/Sources/V2/Main/MainView.swiftSodaLive/Sources/V2/Component/**SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swiftSodaLive/Sources/V2/CreatorChannel/Series/Components/CreatorChannelSeriesListItem.swift- Figma node
24:6737,24:6741,24:6751,24:6758,24:6745,24:6770,24:6807,24:6813,24:6820,24:6829,24:6842
- 결과:
- 구현 대상/제외 대상 섹션을 Figma 기준으로 분리했다.
- 기존 V2 재사용 후보와 필요한 신규 파일 후보를 문서화했다.
- 이번 작업은 문서 작성만 수행했으므로 빌드/테스트는 실행하지 않았다.
- 실행/확인:
-
2026-07-05 문서 보완:
- 실행/확인:
SodaLive/Sources/App/AppDeepLinkHandler.swiftSodaLive/Sources/App/AppStep.swiftSodaLive/Sources/ContentView.swiftSodaLive/Sources/V2/Main/MainView.swift- Figma node
24:6820
- 결과:
- 크리에이터의 댓글 많은 오디오 댓글 bubble에는 nickname을 표시하지 않는 것으로 확정했다.
AudioBannerResponse.link는 deep link 우선 처리 후 외부 브라우저를 여는 것으로 확정했다.AudioBannerResponse.seriesId,OriginalSeriesResponse.seriesId는seriesDetailroute로 이동하는 것으로 확정했다.- 이번 작업은 문서 보완만 수행했으므로 빌드/테스트는 실행하지 않았다.
- 실행/확인:
-
2026-07-05 PRD 기반 계획 재보완:
- 실행/확인:
docs/20260705_메인_콘텐츠_내부_추천_탭/prd.mddocs/20260705_메인_콘텐츠_내부_추천_탭/plan-task.md
- 결과:
- PRD Core Requirements와 계획 Phase의 대응 관계를 추가했다.
- PRD에서 해소된 Open Questions가 계획 문서에 구현 보류 항목으로 남지 않게 정리했다.
- 크리에이터의 댓글 많은 오디오 댓글 bubble에 nickname이 없어야 한다는 검증 기준을 분리했다.
- 이번 작업은 문서 보완만 수행했으므로 빌드/테스트는 실행하지 않았다.
- 실행/확인:
-
2026-07-06 PRD 동기화 점검 후 계획 보완:
- 실행/확인:
docs/20260705_메인_콘텐츠_내부_추천_탭/prd.mddocs/20260705_메인_콘텐츠_내부_추천_탭/plan-task.md
- 결과:
- 신규 사용자 노출 문구를 I18n ko/en/ja로 추가한다는 기준을 Task 2.3에 명시했다.
- 배너
eventItem의 기존 event detail 흐름 재사용 기준을 Phase 12 최종 라우팅 검증에 추가했다. - 이번 작업은 문서 보완만 수행했으므로 빌드/테스트는 실행하지 않았다.
- 실행/확인:
-
2026-07-06 문서 기준 구현:
- 실행/확인:
SodaLive/Sources/V2/Main/Content/**SodaLive/Sources/V2/Main/MainView.swiftSodaLive/Sources/I18n/I18n.swiftSodaLive.xcodeproj/project.pbxprojrg "enum MainContentTab|struct MainContentView|MainContentRecommendationView|case \\.content" SodaLive/Sources/V2/Mainrg "/api/v2/audio/recommendations|getAudioRecommendations|Authorization|AnyPublisher<Response, MoyaError>" SodaLive/Sources/V2/Main/Content/Recommendation/Repositoryrg "MainContentAudioBannerSection|AudioBannerResponse|imageUrl|eventItem|creatorId|seriesId|link|seriesDetail|AppDeepLinkHandler|UIApplication.shared.open" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/V2/Main/MainView.swiftrg "MainContentVoiceOnOnlySection|originalSeries|OriginalSeriesResponse|ic_series_original|img_new_only|onTapSeries|seriesDetail" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/V2/Main/MainView.swift SodaLive/Resources/Assets.xcassets/v2! rg "추천 시리즈|Keyword|키워드의 오디오|RecommendedSeries" SodaLive/Sources/V2/Main/Content/Recommendationplutil -lint SodaLive.xcodeproj/project.pbxprojxcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
- 결과:
.content탭을 신규MainContentView로 교체하고 고정 title bar, 내부추천tab bar, 추천 body 스크롤 구조를 구현했다.GET /api/v2/audio/recommendationsendpoint, repository, response model, ViewModel 상태/디코딩/I18n 문구를 추가했다.- 배너, 오직 보이스온에서만, New&Hot, 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 크리에이터의 댓글 많은 오디오, 추천 오디오 순서로 섹션을 구현했다.
추천 시리즈,키워드의 오디오는 구현하지 않았고, 최근 댓글 섹션에는 nickname UI를 추가하지 않았다.plutil은OK,xcodebuild는BUILD SUCCEEDED로 통과했다.
- 실행/확인:
-
2026-07-06 오디오 card 공용 컴포넌트 정리:
- 실행/확인:
SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swiftSodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swiftSodaLive.xcodeproj/project.pbxprojrg "MainContentAudioTagOverlay|AudioContentThumbnailCard" "SodaLive/Sources/V2" "SodaLive.xcodeproj/project.pbxproj"plutil -lint "SodaLive.xcodeproj/project.pbxproj"xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
- 결과:
- 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 추천 오디오 섹션이
AudioContentThumbnailCard를 사용하도록 정리했다. - 기존
MainContentAudioTagOverlay.swift를 삭제하고 신규 공용 card 파일을 Xcode project에 추가했다. plutil은OK,xcodebuild는BUILD SUCCEEDED로 통과했다.
- 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 추천 오디오 섹션이
- 실행/확인:
-
2026-07-08 콘텐츠 탭 title bar Figma 반영:
- 실행/확인:
- Figma node
24:6738 SodaLive/Sources/V2/Main/Content/MainContentView.swiftSodaLive/Sources/V2/Main/MainView.swiftSodaLive/Sources/V2/Component/DefaultTitleBar.swiftSodaLive/Sources/V2/Component/HomeTitleBar.swift
- Figma node
- 결과:
- 콘텐츠 탭 title bar를
DefaultTitleBar(title: MainTab.content.title)로 변경해 좌측에 메인 탭명콘텐츠를 고정 표시하도록 반영했다. - 우측 액션은
ic_bar_cash,ic_bar_search,ic_bar_storage순서로 정리하고,ic_bar_storage는MainContentView.onTapStorage와MainView.handleContentStorageTap을 통해.myBox(currentTab: .orderlist)로 이동하도록 연결했다. - 홈 탭은 기존
HomeTitleBar와ic_bar_bell동작을 유지한다.
- 콘텐츠 탭 title bar를
- 실행/확인:
-
2026-07-12 섹션 타이틀 변경 기록:
- 실행/확인:
SodaLive/Sources/I18n/I18n.swiftdocs/20260705_메인_콘텐츠_내부_추천_탭/prd.mddocs/20260705_메인_콘텐츠_내부_추천_탭/plan-task.md
- 결과:
- 요청에 따라
최근 댓글이 많은 오디오섹션 타이틀을크리에이터의 댓글 많은 오디오로 변경했다.
- 요청에 따라
- 실행/확인: