Files
sodalive-android/docs/20260627_콘텐츠_전체보기/plan-task.md

67 KiB

콘텐츠 전체보기 구현 계획/TASK

For agentic workers: REQUIRED SUB-SKILL: 구현 시 superpowers:subagent-driven-development 또는 superpowers:executing-plans를 사용해 task 단위로 진행한다. 각 단계는 체크박스(- [ ])로 추적하고, 완료 즉시 - [x]로 갱신한다. 구현 범위 변경이 생기면 이 문서를 먼저 수정한 뒤 코드에 반영한다.

Goal: 홈/콘텐츠 추천 섹션의 전체보기 chevron을 연결하고, 기존 콘텐츠 전체 탭 이동을 먼저 적용한 뒤 New&Hot처음부터 함께 성장! 전용 신규 전체보기 화면을 제공한다.

Architecture: 구현 순서는 chevron 표시 -> 기존 콘텐츠 전체 탭 이동 -> 신규 전체보기 페이지/API로 고정한다. 기존 화면 이동은 MainV2Activity, ContentMainFragment, ContentAllTabViewModel에 작은 public navigation contract를 추가해 처리한다. 신규 전체보기 화면은 마지막 단계에서 kr.co.vividnext.sodalive.v2.main.content.overview 하위 Activity/ViewModel/API/Repository/DTO/UI model/adapter로 격리한다.

Tech Stack: Kotlin, Android XML Views, ViewBinding, RecyclerView, Retrofit, Gson, RxJava3, Koin, JUnit4/Robolectric local unit test.


전제와 성공 기준

  • PRD: docs/20260627_콘텐츠_전체보기/prd.md
  • 구현 순서:
    • 1순위: 홈/콘텐츠 추천 섹션 chevron 표시.
    • 2순위: 신규 페이지가 필요 없는 섹션을 기존 콘텐츠 전체 탭으로 이동.
    • 3순위: 신규 콘텐츠 전체보기 페이지/API 생성 및 신규 페이지 대상 섹션 이동.
  • 전체보기 chevron 표시 섹션:
    • 홈 추천 탭: 처음부터 함께 성장!
    • 콘텐츠 추천 탭: 오직 보이스온에서만!, 새로 올라온 오디오, New&Hot, 무료 오디오, 포인트 오디오
  • 기존 콘텐츠 전체 탭 이동 섹션:
    • 오직 보이스온에서만! -> 콘텐츠 탭 전체 -> 오리지널 카테고리
    • 새로 올라온 오디오 -> 콘텐츠 탭 전체 -> 오디오 카테고리
    • 무료 오디오 -> 콘텐츠 탭 전체 -> 무료 카테고리 -> 인기순
    • 포인트 오디오 -> 콘텐츠 탭 전체 -> 포인트 카테고리 -> 인기순
  • 신규 전체보기 페이지 이동 섹션:
    • 홈 추천 탭 처음부터 함께 성장! -> 신규 콘텐츠 전체보기 -> FIRST_AUDIO_CONTENT
    • 콘텐츠 추천 탭 New&Hot -> 신규 콘텐츠 전체보기 -> NEW_AND_HOT_AUDIO
  • 댓글 많은 오디오, 추천 오디오에는 chevron을 표시하지 않는다.
  • 신규 API endpoint는 GET /api/v2/contents이다.
  • 신규 API query parameter key는 소문자 page, size, type만 사용한다.
  • 신규 API 기본값은 page=0, size=20, type=NEW_AND_HOT_AUDIO다.
  • 앱 구현 DTO annotation은 Gson @SerializedName을 사용한다.
  • 신규 전체보기 화면 title은 NEW_AND_HOT_AUDIO일 때 New&Hot, FIRST_AUDIO_CONTENT일 때 처음부터 함께 성장!이다.
  • 신규 전체보기 화면은 Figma node 482:15105 기준 2열 오디오 카드 grid를 사용한다.
  • 구현 완료 후 최소 다음 명령을 실행한다.
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.*"
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
    • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*"
    • ./gradlew :app:mergeDebugResources
    • ./gradlew :app:compileDebugKotlin
    • ./gradlew :app:ktlintCheck
    • git diff --check

Phase 순서

  • Phase 1: 기존 구조 확인과 작업 경계 고정
  • Phase 2: 홈/콘텐츠 추천 섹션 chevron 표시
  • Phase 3: 기존 콘텐츠 전체 탭 이동 contract 추가
  • Phase 4: 기존 콘텐츠 전체 탭 이동 섹션 연결
  • Phase 5: 신규 전체보기 API, DTO, Repository, UI model 추가
  • Phase 6: 신규 전체보기 ViewModel, Activity, Adapter 구현
  • Phase 7: 신규 전체보기 대상 섹션 이동 연결
  • Phase 8: 통합 검증과 수동 확인

Figma 참조 필요 Phase

  • Phase 1: 제한 참조
    • 기존 홈/콘텐츠 추천 섹션 title, 콘텐츠 전체 탭, MainV2 navigation 구조 확인 중심으로 진행한다.
  • Phase 2: 제한 참조
    • chevron 표시는 기존 view_section_title.xml과 홈/콘텐츠 추천 섹션 구조를 따른다.
  • Phase 3~4: Figma 참조 불필요
    • 기존 콘텐츠 전체 탭 이동은 기존 ContentAllTabViewModel의 type/sort 계약과 MainV2 tab 전환 구조를 따른다.
  • Phase 5: Figma 참조 불필요
    • API/DTO/Repository/UI model/mapper/ViewModel은 PRD 서버 계약과 기존 V2 data layer/paging 패턴을 따른다.
  • Phase 6: 필수 참조
    • 신규 전체보기 Activity layout은 Figma 482:15105의 title bar, black background, 2열 grid, card spacing을 기준으로 확인한다.
  • Phase 7~8: 필수 참조
    • 신규 페이지 대상 섹션 이동과 최종 수동 화면 검증은 PRD의 Figma reference와 실제 화면을 대조한다.

파일 구조

기존 화면 이동 선행 범위

  • Modify: app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
    • 처음부터 함께 성장! title chevron을 먼저 표시한다. 신규 페이지 이동은 Phase 7에서 연결한다.
  • Modify: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt
    • 콘텐츠 추천 섹션 chevron 표시, 기존 콘텐츠 전체 탭 이동, 신규 페이지 이동을 단계별로 추가한다.
  • Modify: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentAllTabViewModel.kt
    • 외부 진입용 type/sort 선택 API를 추가한다.
  • Modify: app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt
    • 콘텐츠 탭 내부 전체를 특정 type/sort로 여는 public method와 기존 fragment 재사용 처리를 추가한다.
  • Modify: app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentSourceTest.kt
    • 콘텐츠 추천 섹션 chevron/routing/source를 검증한다.
  • Modify: app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentAllTabViewModelTest.kt
    • 외부 type/sort 선택 API를 검증한다.
  • Create: app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentSourceTest.kt
    • 처음부터 함께 성장! chevron/source를 검증한다.
  • Modify: app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt
    • 콘텐츠 탭 내부 전체 type/sort routing contract를 검증한다.

신규 전체보기 후행 범위

  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/data/ContentOverviewApi.kt
    • GET /api/v2/contents Retrofit endpoint를 정의한다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/data/ContentOverviewModels.kt
    • ContentOverviewPageResponse, ContentOverviewType, ContentOverviewItemResponse DTO를 정의한다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/data/ContentOverviewRepository.kt
    • API 호출을 repository method로 감싼다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiState.kt
    • Loading, Content, Empty, Error 상태와 paging/loading-more 상태를 정의한다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiModels.kt
    • 신규 전체보기 화면 item/title/type UI model을 정의한다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewMappers.kt
    • DTO를 UI model로 변환하고 AudioContentTag를 매핑한다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewViewModel.kt
    • type/page/hasNext/loading-more/API 상태를 관리한다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivity.kt
    • title bar, 2열 RecyclerView, paging, empty/error/loading, 상세 routing을 연결한다.
  • Create: app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ui/ContentOverviewAdapter.kt
    • AudioContentCardView 기반 2열 grid item을 바인딩한다.
  • Create: app/src/main/res/layout/activity_content_overview.xml
    • 신규 전체보기 화면 layout이다.
  • Modify: app/src/main/AndroidManifest.xml
    • ContentOverviewActivity를 등록한다.
  • Modify: app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
    • 신규 API, Repository, ViewModel을 Koin에 등록한다.
  • Create: app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewMapperTest.kt
    • DTO -> UI model/tag/title mapping을 검증한다.
  • Create: app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewViewModelTest.kt
    • 첫 페이지, load-more, 실패, stale response 방지를 검증한다.
  • Create: app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivitySourceTest.kt
    • layout id, 2열 grid, intent extra, 상세 이동 source를 검증한다.

Phase 1: 기존 구조 확인과 작업 경계 고정

  • Task 1.1: PRD와 기존 구현 상태 대조

    • 확인:
      • docs/20260627_콘텐츠_전체보기/prd.md
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt
      • app/src/main/res/layout/view_section_title.xml
    • 작업:
      • HomeMainFragmentViewSectionTitleBinding.setTitle(titleResId, showMore)가 chevron 표시를 이미 지원하는지 확인한다.
      • ContentMainFragmentViewSectionTitleBinding.setTitle(titleResId)가 현재 chevron을 항상 숨기는지 확인한다.
      • 이번 작업에서 레거시 audio_content/* 파일을 직접 수정하지 않는 것을 확인한다.
    • 검증:
      • Run: rg -n "setTitle\\(|ivSectionTitleChevron|viewHomeFirstAudioTitle|viewContentNewAndHotTitle|viewContentOriginalSeriesTitle" app/src/main/java/kr/co/vividnext/sodalive/v2/main app/src/main/res/layout/view_section_title.xml
      • Expected: 홈 title helper와 콘텐츠 title helper, chevron view id가 확인된다.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 실행: rg -n "setTitle\(|ivSectionTitleChevron|viewHomeFirstAudioTitle|viewContentNewAndHotTitle|viewContentOriginalSeriesTitle" app/src/main/java/kr/co/vividnext/sodalive/v2/main app/src/main/res/layout/view_section_title.xml
      • 결과: view_section_title.xmliv_section_title_chevron, HomeMainFragmentsetTitle(titleResId, showMore), ContentMainFragment의 section title 설정 지점을 확인했다.
      • 확인: 홈 title helper는 showMore로 chevron 표시를 이미 지원하며 viewHomeFirstAudioTitleshowMore = true 상태였다. 콘텐츠 title helper는 기존에 chevron을 숨기고 있어 Phase 2에서 helper 확장이 필요했다.
      • 확인: 이번 Phase 1~2 범위에서는 레거시 audio_content/* 파일을 직접 수정하지 않았다.
  • Task 1.2: 기존 콘텐츠 전체 탭 이동 가능 지점 확인

    • 확인:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentAllTabViewModel.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/data/MainContentAllTabModels.kt
    • 작업:
      • MainV2Activity의 bottom tab 전환과 fragment 재사용 위치를 확인한다.
      • ContentMainFragmentshowAllContent()ContentAllTabViewModel type/sort 변경 위치를 확인한다.
      • MainContentAllType.ORIGINAL, AUDIO, FREE, POINTContentSort.POPULAR, LATEST가 기존 목적지 요구를 충족하는지 확인한다.
    • 검증:
      • Run: rg -n "MainContentAllType|ContentSort|showAllContent|changeType|changeSort|clickTab\\(MainV2Tab.CONTENT\\)" app/src/main/java/kr/co/vividnext/sodalive/v2/main
      • Expected: type/sort 선택과 bottom tab 전환 지점이 확인된다.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 실행: rg -n "MainContentAllType|ContentSort|showAllContent|changeType|changeSort|clickTab\(MainV2Tab.CONTENT\)" app/src/main/java/kr/co/vividnext/sodalive/v2/main
      • 결과: MainV2Activity.clickTab(MainV2Tab.CONTENT), ContentMainFragment.showAllContent(), ContentAllTabViewModel.changeType/changeSort, MainContentAllType.ORIGINAL/AUDIO/FREE/POINT, ContentSort 사용 지점을 확인했다.
      • 확인: Phase 1에서는 기존 콘텐츠 전체 탭 이동 가능 지점만 확인했고, 실제 contract/API 추가는 Phase 3 범위로 남겼다.

Phase 2: 홈/콘텐츠 추천 섹션 chevron 먼저 표시

  • Task 2.1: 홈 추천 탭 FIRST 섹션 chevron 표시

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
    • 테스트:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentSourceTest.kt
    • 작업:
      • viewHomeFirstAudioTitle.setTitle(..., showMore = true) 상태를 유지하거나 누락되어 있으면 추가한다.
      • 이 Task에서는 신규 페이지 이동 click listener를 연결하지 않는다.
      • source test는 viewHomeFirstAudioTitle.setTitle 호출이 showMore = true임을 검증한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest"
      • Expected: 홈 FIRST chevron 표시 source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 확인: HomeMainFragmentviewHomeFirstAudioTitle.setTitle(R.string.home_recommendation_section_first_audio_contents, showMore = true)가 이미 적용되어 있었다.
      • 2026-06-27 테스트 추가: HomeMainFragmentSourceTest를 생성해 FIRST 섹션 showMore = true와 Phase 2 범위에서 click listener가 아직 연결되지 않았음을 검증했다.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest"
      • 결과: PASS.
  • Task 2.2: 콘텐츠 추천 탭 section title helper 확장

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt
    • 테스트:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentSourceTest.kt
    • 작업:
      • 콘텐츠 탭의 ViewSectionTitleBinding.setTitle(titleResId)setTitle(titleResId, showMore = false)로 확장한다.
      • 오직 보이스온에서만!, 새로 올라온 오디오, New&Hot, 무료 오디오, 포인트 오디오showMore = true로 설정한다.
      • 댓글 많은 오디오, 추천 오디오showMore = false를 유지한다.
      • 이 Task에서는 기존 전체 탭 이동과 신규 페이지 이동 click listener를 연결하지 않는다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • Expected: 콘텐츠 추천 chevron 표시/숨김 source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • RED 결과: 신규 content recommendation section titles show only Phase 2 chevrons 테스트가 ContentMainFragmentSourceTest.kt:463에서 실패했다. 원인은 콘텐츠 title helper가 showMore를 지원하지 않고 chevron을 항상 숨기는 기존 구현이었다.
      • 2026-06-27 구현: ContentMainFragmentViewSectionTitleBinding.setTitle(titleResId, showMore = false)를 추가하고 오직 보이스온에서만!, 새로 올라온 오디오, New&Hot, 무료 오디오, 포인트 오디오에만 showMore = true를 지정했다. 댓글 많은 오디오, 추천 오디오는 기본값 false를 유지했다.
      • 2026-06-27 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • GREEN 결과: PASS.
      • 참고: 홈/콘텐츠 source 테스트를 병렬 실행하던 중 한 번 :app:kspDebugKotlin generated file 접근 오류가 발생했으나, 동일 콘텐츠 테스트 단독 재실행 시 정상 PASS했다.

Phase 3: 기존 콘텐츠 전체 탭 이동 contract 추가

  • Task 3.1: ContentAllTabViewModel 외부 선택 API 추가

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentAllTabViewModel.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentAllTabViewModelTest.kt
    • 작업:
      • fun selectTypeAndSort(type: MainContentAllType, sort: ContentSort)를 추가한다.
      • 함수는 selectedType, selectedSort, selectedDayOfWeek를 갱신하고 page=0부터 재조회한다.
      • ORIGINAL, AUDIO, FREE, POINTdayOfWeek = null로 요청한다.
      • 기존 changeType, changeSort, loadInitial 테스트를 깨지 않는다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentAllTabViewModelTest"
      • Expected: 기존 테스트와 신규 외부 선택 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: ContentAllTabViewModel.selectTypeAndSort(type, sort)를 추가해 selectedType, selectedSort, selectedDayOfWeek를 갱신하고 첫 페이지를 재조회하도록 했다. SERIES가 아닌 type은 selectedDayOfWeekFor(type) 경로로 dayOfWeek = null을 유지한다.
      • 2026-06-27 테스트 추가: ContentAllTabViewModelTest에 외부 선택 요청 FREE + POPULAR, ORIGINAL + LATEST가 모두 page=0, dayOfWeek=null로 호출되는 검증을 추가했다.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentAllTabViewModelTest"
      • 결과: PASS.
  • Task 3.2: ContentMainFragment에 내부 전체 탭 선택 API 추가

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentSourceTest.kt
    • 작업:
      • fun selectAllTab(type: MainContentAllType, sort: ContentSort = ContentSort.LATEST)를 추가한다.
      • 함수는 binding.textTabBarContent.root의 선택을 전체로 전환하고 showContentTab(CONTENT_TAB_ALL)을 호출한다.
      • 이후 contentAllTabViewModel.selectTypeAndSort(type, sort)를 호출한다.
      • fragment view가 아직 생성되지 않은 경우를 대비해 pending type/sort를 fragment field에 저장하고 onViewCreated 이후 적용한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • Expected: 내부 전체 탭 선택 source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: ContentMainFragment.selectAllTab(type, sort)를 추가하고 view 생성 전 호출은 pendingAllTabSelection에 저장한 뒤 onViewCreated 이후 적용하도록 했다.
      • 2026-06-27 확인: pending 적용 시 hasSelectedAllTab = true를 먼저 설정한 뒤 textTabBarContent.root.selectTab(CONTENT_TAB_ALL)showContentTab(CONTENT_TAB_ALL)을 호출해 TextTabBarView.selectTab listener가 유발할 수 있는 기본 loadInitial() 중복 호출을 피했다. 실제 데이터 재조회는 contentAllTabViewModel.selectTypeAndSort(...) 단일 경로로 수행한다.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • 결과: PASS.
  • Task 3.3: MainV2Activity 콘텐츠 전체 탭 진입 API 추가

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt
    • 작업:
      • fun openContentAllTab(type: MainContentAllType, sort: ContentSort = ContentSort.LATEST)를 추가한다.
      • 현재 탭을 MainV2Tab.CONTENT로 전환한다.
      • changeFragment 이후 기존 또는 신규 ContentMainFragmentselectAllTab(type, sort)를 전달한다.
      • 이미 콘텐츠 탭에 있는 경우 fragment를 중복 생성하지 않고 현재 fragment method를 호출한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2ActivitySourceTest"
      • Expected: MainV2 콘텐츠 전체 탭 routing source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: MainV2Activity.openContentAllTab(type, sort)를 추가해 CONTENT 탭이 아니면 viewModel.clickTab(MainV2Tab.CONTENT)changeFragment(MainV2Tab.CONTENT)로 콘텐츠 Fragment를 준비한 뒤 기존/new ContentMainFragment.selectAllTab(type, sort)를 호출하도록 했다.
      • 2026-06-27 확인: 이미 CONTENT 탭인 경우 changeFragment를 직접 호출하지 않고 기존 ContentMainFragment를 찾아 selectAllTab만 호출하므로 fragment 중복 생성을 피한다.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2ActivitySourceTest"
      • 결과: PASS.

Phase 4: 기존 콘텐츠 전체 탭 이동 섹션 연결

  • Task 4.1: 콘텐츠 추천 탭 기존 전체 탭 목적지 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt
    • 테스트:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentSourceTest.kt
    • 작업:
      • 오직 보이스온에서만! chevron은 MainContentAllType.ORIGINAL, ContentSort.LATESTMainV2Activity.openContentAllTab을 호출한다.
      • 새로 올라온 오디오 chevron은 MainContentAllType.AUDIO, ContentSort.LATEST로 호출한다.
      • 무료 오디오 chevron은 MainContentAllType.FREE, ContentSort.POPULAR로 호출한다.
      • 포인트 오디오 chevron은 MainContentAllType.POINT, ContentSort.POPULAR로 호출한다.
      • New&Hot은 신규 페이지 대상이므로 이 Phase에서는 click listener를 연결하지 않는다.
      • 처음부터 함께 성장!은 신규 페이지 대상이므로 이 Phase에서는 click listener를 연결하지 않는다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • Expected: 기존 전체 탭 이동 섹션별 목적지 source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: 오직 보이스온에서만!, 새로 올라온 오디오, 무료 오디오, 포인트 오디오 chevron click listener를 ensureMainV2NavigationAllowed로 감싸고 (activity as? MainV2Activity)?.openContentAllTab(...) 경로에 연결했다.
      • 2026-06-27 확인: routing destination은 각각 ORIGINAL/LATEST, AUDIO/LATEST, FREE/POPULAR, POINT/POPULAR로 지정했다. New&Hot 및 홈 처음부터 함께 성장! click listener는 Phase 4 범위에서 연결하지 않았다.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • 결과: PASS.
  • Task 4.2: 기존 전체 탭 이동 수동 검증

    • 확인:
      • 콘텐츠 추천 탭 오직 보이스온에서만! chevron 클릭 시 콘텐츠 전체 -> 오리지널 진입.
      • 콘텐츠 추천 탭 새로 올라온 오디오 chevron 클릭 시 콘텐츠 전체 -> 오디오 진입.
      • 콘텐츠 추천 탭 무료 오디오 chevron 클릭 시 콘텐츠 전체 -> 무료 + 인기순 진입.
      • 콘텐츠 추천 탭 포인트 오디오 chevron 클릭 시 콘텐츠 전체 -> 포인트 + 인기순 진입.
      • 콘텐츠 추천 탭 New&Hot과 홈 처음부터 함께 성장!은 chevron만 표시되고 신규 페이지 이동은 아직 연결되지 않음.
    • 검증 기록:
      • 구현 시 이 Task 아래에 테스트 기기/빌드 variant/API 응답 조건과 확인 결과를 한국어로 누적한다.
      • 2026-06-27 상태: BLOCKED/미완료. 현재 작업 환경에서 Android 기기 또는 에뮬레이터를 통한 실제 화면 조작을 수행할 수 없어 수동 검증을 완료하지 못했다.
      • 2026-06-27 대체 확인: source 테스트로 Phase 4 click listener 연결 대상과 미연결 대상(New&Hot)은 검증했으나, 실제 앱 화면에서 chevron 클릭 후 콘텐츠 전체 탭 UI/type/sort 표시까지는 확인하지 못했다.

Phase 5: 신규 전체보기 API, DTO, Repository, UI model 추가

  • Task 5.1: ContentOverview API/DTO/Repository 추가

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/data/ContentOverviewApi.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/data/ContentOverviewModels.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/data/ContentOverviewRepository.kt
    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
    • 작업:
      • ContentOverviewApi.getContents(authHeader, page, size, type)@GET("/api/v2/contents")로 정의한다.
      • query annotation 이름은 page, size, type만 사용한다.
      • DTO는 @Keep@SerializedName을 사용한다.
      • ContentOverviewTypeNEW_AND_HOT_AUDIO, FIRST_AUDIO_CONTENT만 정의한다.
      • Repository는 Single<ApiResponse<ContentOverviewPageResponse>>를 반환한다.
      • Koin networkModule, repositoryModule에 신규 API/Repository를 등록한다.
    • 검증:
      • Run: ./gradlew :app:compileDebugKotlin
      • Expected: 신규 data layer와 DI 등록이 컴파일된다.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: ContentOverviewApi, ContentOverviewPageResponse, ContentOverviewType, ContentOverviewItemResponse, ContentOverviewRepository를 추가했다. endpoint는 GET /api/v2/contents, query key는 page, size, type만 사용한다.
      • 2026-06-27 DI 등록: AppDInetworkModuleContentOverviewApi, repositoryModuleContentOverviewRepository를 등록했다. ViewModel DI는 Phase 6.5에서 등록하도록 이 Task에서는 제외했다.
      • 2026-06-27 실행: ./gradlew :app:compileDebugKotlin
      • 결과: PASS.
      • 2026-06-27 코드 리뷰 확인: PRD/계획서의 응답 필드 계약은 items, contentId, coverImage인데 현재 DTO는 contents, audioContentId, imageUrl, totalCount를 사용한다. 서버 최신 계약 변경이 아니라면 API 응답 파싱 실패 위험이 있어 수정이 필요하다.
      • 2026-06-27 리뷰 후속 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*"
      • RED 결과: 테스트 fixture를 문서 계약인 items, contentId, coverImage로 변경하자 기존 DTO의 contents, audioContentId, imageUrl, totalCount 생성자와 맞지 않아 컴파일 실패했다.
      • 2026-06-27 리뷰 후속 구현: ContentOverviewPageResponseitems 기반으로, ContentOverviewItemResponsecontentId, coverImage 기반으로 수정하고 mapper도 동일 계약을 사용하도록 변경했다.
  • Task 5.2: Mapper RED 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewMapperTest.kt
    • 테스트 케이스:
      • NEW_AND_HOT_AUDIO title은 New&Hot이다.
      • FIRST_AUDIO_CONTENT title은 처음부터 함께 성장!이다.
      • price == 0이면 AudioContentTag.Free가 포함된다.
      • isPointAvailable == true이면 AudioContentTag.Point가 포함된다.
      • isFirstContent == true이면 AudioContentTag.First가 포함된다.
      • isOriginalSeries == true이면 AudioContentTag.Original이 포함된다.
      • isAdult == true이면 showAdultBadge == true다.
      • page, size, hasNext, type은 UI state에 보존된다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewMapperTest"
      • Expected: mapper 구현 전 RED 실패.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 RED 테스트 추가: ContentOverviewMapperTest를 생성해 type title resource, tag mapping, adult badge, paging metadata/type 보존을 검증하도록 했다.
      • 2026-06-27 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewMapperTest"
      • RED 결과: overview.model mapper/UI model 미구현으로 Unresolved reference 'model', toTitleResId, toUiModel, toContent 컴파일 실패를 확인했다.
  • Task 5.3: UI model과 mapper 구현

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiState.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewUiModels.kt
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/model/ContentOverviewMappers.kt
    • 작업:
      • ContentOverviewUiState.Loading, Content, Empty, Error를 정의한다.
      • ContentOverviewUiModelcontentId, title, coverImage, creatorNickname, tags, showAdultBadge를 포함한다.
      • ContentOverviewType.toTitleResId()를 정의한다.
      • NEW_AND_HOT_AUDIOR.string.content_recommendation_section_new_and_hot, FIRST_AUDIO_CONTENTR.string.home_recommendation_section_first_audio_contents로 매핑한다.
      • ContentOverviewItemResponse.toUiModel()에서 PRD tag mapping을 구현한다.
      • ContentOverviewPageResponse.toContent()에서 paging metadata와 item list를 보존한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewMapperTest"
      • Expected: mapper 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: ContentOverviewUiState, ContentOverviewUiModel, ContentOverviewType.toTitleResId(), ContentOverviewPageResponse.toContent(), ContentOverviewItemResponse.toUiModel()을 추가했다.
      • 2026-06-27 확인: NEW_AND_HOT_AUDIONew&Hot, FIRST_AUDIO_CONTENT처음부터 함께 성장! title resource로 매핑하고, Original/First/Point/Free tag 및 adult badge를 DTO boolean/price 기준으로 매핑했다.
      • 2026-06-27 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewMapperTest"
      • GREEN 결과: PASS.

Phase 6: 신규 전체보기 ViewModel, Activity, Adapter 구현

  • Task 6.1: ViewModel RED 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewViewModelTest.kt
    • 테스트 케이스:
      • 초기 로드는 전달받은 type으로 page=0, size=20을 요청한다.
      • 첫 페이지 성공 + items 있음은 Content 상태를 emit한다.
      • 첫 페이지 성공 + items empty는 Empty 상태를 emit한다.
      • 첫 페이지 실패는 Error 상태와 toast를 emit한다.
      • hasNext = true 상태에서 loadMore()는 다음 page를 요청하고 append한다.
      • hasNext = false이면 loadMore()가 repository를 추가 호출하지 않는다.
      • 추가 페이지 실패 시 기존 items를 유지하고 pagination error message를 emit한다.
      • type 변경 또는 새 화면 생성 상태 간 page/items를 공유하지 않는다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewViewModelTest"
      • Expected: ViewModel 구현 전 RED 실패.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 RED 테스트 추가: ContentOverviewViewModelTest를 생성해 초기 load, Content/Empty/Error, toast, load-more append, hasNext=false 추가 요청 방지, pagination error 보존, stale response 방지를 검증하도록 했다.
      • 2026-06-27 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewViewModelTest"
      • RED 결과: ContentOverviewViewModel 미구현으로 Unresolved reference 'ContentOverviewViewModel', loadFirstPage, loadMore, overviewStateLiveData 컴파일 실패를 확인했다.
  • Task 6.2: ViewModel 구현

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewViewModel.kt
    • 작업:
      • loadFirstPage(type: ContentOverviewType)를 구현한다.
      • loadMore()Content 상태, hasNext, isLoadingMore를 확인한 뒤 다음 page만 요청한다.
      • requestGeneration으로 stale response가 현재 화면 상태를 덮어쓰지 않게 한다.
      • auth header는 기존 ViewModel 패턴대로 Bearer ${SharedPreferenceManager.token}를 사용한다.
      • 첫 페이지 loading은 isLoading LiveData로 처리하고, 추가 페이지 loading은 Content.isLoadingMore로 처리한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewViewModelTest"
      • Expected: ViewModel 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: ContentOverviewViewModel을 추가해 page=0, size=20, Bearer ${SharedPreferenceManager.token}, requestGeneration, 첫 페이지 isLoading, 추가 페이지 Content.isLoadingMore/paginationErrorMessage 패턴을 구현했다.
      • 2026-06-27 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewViewModelTest"
      • GREEN 결과: PASS.
  • Task 6.3: Activity layout과 Adapter 구현

    • 생성:
      • app/src/main/res/layout/activity_content_overview.xml
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ui/ContentOverviewAdapter.kt
    • 수정:
      • app/src/main/AndroidManifest.xml
    • 작업:
      • layout root는 black background를 사용한다.
      • title bar는 60dp 높이, 좌측 back chevron, 22sp bold title을 배치한다.
      • RecyclerView는 2열 GridLayoutManager로 표시한다.
      • RecyclerView item은 기존 item_content_audio_card.xmlAudioContentCardView를 재사용한다.
      • Adapter는 setGridItemWidthPx(widthPx)를 호출해 2열 item width를 적용한다.
      • 이미지 로딩은 기존 loadUrl 확장을 사용한다.
      • manifest에 kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivity를 등록한다.
    • 검증:
      • Run: ./gradlew :app:mergeDebugResources
      • Expected: 신규 layout과 resource reference가 merge된다.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: Figma 482:15105 기준으로 black root, 60dp title bar, 좌측 ic_new_bar_back, 22sp bold title(Typography.Heading2), 2열 RecyclerView layout을 추가했다.
      • 2026-06-27 구현: ContentOverviewAdapter를 추가해 item_content_audio_card.xml/AudioContentCardView를 재사용하고 setGridItemWidthPx, setContent, setTags, setAdultVisible, loadUrl을 바인딩했다.
      • 2026-06-27 구현: AndroidManifest.xml.v2.main.content.overview.ContentOverviewActivity를 등록했다.
      • 2026-06-27 실행: ./gradlew :app:mergeDebugResources
      • 결과: PASS.
  • Task 6.4: Activity source RED 테스트 작성

    • 생성:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivitySourceTest.kt
    • 테스트 케이스:
      • ContentOverviewActivity.newIntent(context, type)가 type extra를 포함한다.
      • layout에 back button, title TextView, RecyclerView, empty/error TextView가 있다.
      • Activity가 GridLayoutManager(this, CONTENT_OVERVIEW_GRID_SPAN_COUNT)로 2열 grid를 설정한다.
      • scroll bottom에서 viewModel.loadMore()를 호출한다.
      • item click은 Constants.EXTRA_AUDIO_CONTENT_IDAudioContentDetailActivity를 연다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest"
      • Expected: Activity 구현 전 또는 연결 전 RED 실패.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 RED 테스트 추가: ContentOverviewActivitySourceTest를 생성해 newIntent, intent extra, Figma layout id, 2열 GridLayoutManager, 하단 scroll loadMore, 상세 이동 extra, manifest 등록, Phase 7 라우팅 미추가를 검증하도록 했다.
      • 2026-06-27 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest"
      • RED 결과: layout/manifest/Phase 7 미연결 검증은 통과했고 ContentOverviewActivity.kt 미생성으로 Activity source 관련 테스트 2건이 FileNotFoundException으로 실패하는 것을 확인했다.
  • Task 6.5: Activity 구현과 ViewModel 연결

    • 생성:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivity.kt
    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
    • 작업:
      • newIntent(context, type) companion method를 제공한다.
      • intent type extra가 없거나 enum parsing에 실패하면 NEW_AND_HOT_AUDIO를 fallback으로 사용한다.
      • title은 type mapping으로 표시한다.
      • back button은 finish()를 호출한다.
      • Content, Empty, Error, Loading 상태별 UI를 바인딩한다.
      • item click은 AudioContentDetailActivity를 열고 Constants.EXTRA_AUDIO_CONTENT_IDcontentId를 전달한다.
      • 성인 콘텐츠 접근 제한은 기존 AudioContentDetailActivity 정책을 따른다.
      • Koin viewModelModuleContentOverviewViewModel을 등록한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*"
      • Expected: overview mapper/ViewModel/source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 구현: ContentOverviewActivity를 추가해 newIntent(context, type), type title, back finish(), Loading/Content/Empty/Error 렌더링, 2열 grid width 계산, scroll bottom loadMore(), AudioContentDetailActivity 상세 이동을 연결했다.
      • 2026-06-27 구현: AppDI.viewModelModuleContentOverviewViewModel을 등록했다. intent type extra가 없거나 파싱 실패하면 계획서 기본값인 NEW_AND_HOT_AUDIO를 사용한다.
      • 2026-06-27 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*"
      • GREEN 결과: PASS.
      • 2026-06-27 추가 검증: 포맷 수정 후 동일 overview 테스트 재실행 결과 PASS.
      • 2026-06-27 코드 리뷰 확인: PRD edge case의 contentId <= 0 상세 이동 무시 조건이 현재 ContentOverviewActivity.openAudioContentDetail(contentId) 또는 adapter click 경로에 반영되어 있지 않다. 잘못된 id 응답 시 상세 화면을 열 수 있어 수정이 필요하다.
      • 2026-06-27 리뷰 후속 RED 테스트 추가: ContentOverviewActivitySourceTest에 Activity의 if (contentId <= 0) return 및 Adapter의 return@setOnClickListener 검증을 추가했다.
      • 2026-06-27 리뷰 후속 구현: ContentOverviewActivity.openAudioContentDetail(contentId)ContentOverviewAdapter click listener에 contentId <= 0 상세 이동 무시 조건을 추가했다.
  • Task 6.6: 신규 전체보기 loading UI 표시 후속 수정

    • 수정:
      • app/src/main/res/layout/activity_content_overview.xml
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivity.kt
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview/ContentOverviewActivitySourceTest.kt
    • 작업:
      • 첫 페이지 Loading 상태에서 사용자에게 보이는 중앙 progress view를 표시한다.
      • Content.isLoadingMore가 true일 때 기존 목록은 유지하고 하단 progress view를 표시한다.
      • Empty, Error, Content의 비로딩 상태에서는 progress view를 숨긴다.
      • skeleton loading, 신규 정렬/필터, Phase 7 신규 전체보기 라우팅은 추가하지 않는다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest"
      • Expected: first-page/loading-more progress source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 작업 결정: PRD의 첫 페이지 로딩/추가 페이지 로딩 상태 구분 요구를 엄격히 충족하기 위해 LoadingDialog가 아닌 inline progress view 2개를 추가하는 최소 수정으로 진행한다.
      • 2026-06-27 RED 테스트 추가: ContentOverviewActivitySourceTest에 first-page progress id, load-more progress id, viewModel.isLoading.observe(this), renderLoading() progress 표시, state.isLoadingMore에 따른 load-more progress 표시 검증을 추가했다.
      • 2026-06-27 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest"
      • RED 결과: ContentOverviewActivitySourceTest.kt:48, ContentOverviewActivitySourceTest.kt:59에서 예상 실패했다. 원인은 activity_content_overview.xml에 progress view가 없고 ContentOverviewActivity가 로딩 progress를 바인딩하지 않았기 때문이다.
      • 2026-06-27 구현: activity_content_overview.xmlpb_content_overview_initial_loading, pb_content_overview_load_more를 추가하고, ContentOverviewActivity에서 viewModel.isLoadingContent.isLoadingMore에 따라 progress visibility를 제어하도록 했다.
      • 2026-06-27 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest"
      • GREEN 결과: PASS.
      • 2026-06-27 코드 리뷰 및 검증 재확인: 첫 페이지/loading-more progress view와 Activity binding이 유지되어 있고, ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 재실행 결과 PASS.

Phase 7: 신규 전체보기 대상 섹션 이동 연결

  • Task 7.1: 홈 FIRST 신규 전체보기 이동 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
    • 테스트:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentSourceTest.kt
    • 작업:
      • viewHomeFirstAudioTitle.ivSectionTitleChevron.setOnClickListener를 추가한다.
      • 클릭 시 ContentOverviewActivity.newIntent(requireContext(), ContentOverviewType.FIRST_AUDIO_CONTENT)로 이동한다.
      • ensureMainV2NavigationAllowed로 기존 홈 navigation guard 패턴을 따른다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest"
      • Expected: 홈 FIRST 신규 전체보기 이동 source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 RED 테스트 수정: HomeMainFragmentSourceTest의 Phase 2 미연결 assertion을 Phase 7 라우팅 assertion으로 변경해 ContentOverviewActivity/ContentOverviewType import, viewHomeFirstAudioTitle.ivSectionTitleChevron.setOnClickListener, FIRST_AUDIO_CONTENT intent 생성을 요구하도록 했다.
      • 2026-06-27 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest"를 production 구현 전 병렬 실행했으나 Gradle/Kotlin daemon cache 충돌 및 동시 compile 오류로 테스트 assertion 결과까지 도달하지 못했다. 이후 ./gradlew --stop으로 daemon을 정리하고 순차 검증으로 전환했다.
      • 2026-06-27 구현: HomeMainFragmentContentOverviewActivity, ContentOverviewType import를 추가하고 viewHomeFirstAudioTitle.ivSectionTitleChevron.setOnClickListener에서 ensureMainV2NavigationAllowed를 거쳐 ContentOverviewActivity.newIntent(requireContext(), ContentOverviewType.FIRST_AUDIO_CONTENT)를 실행하도록 연결했다.
      • 2026-06-27 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest"
      • GREEN 결과: PASS.
      • 2026-06-27 리뷰 후속 보강: HomeMainFragmentSourceTestopenFirstAudioOverview() 함수 내부에서 ensureMainV2NavigationAllowedstartActivity보다 먼저 호출되고 FIRST_AUDIO_CONTENT intent를 생성하는 순서를 검증하도록 보강했다.
  • Task 7.2: 콘텐츠 New&Hot 신규 전체보기 이동 연결

    • 수정:
      • app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragment.kt
    • 테스트:
      • app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/ContentMainFragmentSourceTest.kt
    • 작업:
      • viewContentNewAndHotTitle.ivSectionTitleChevron.setOnClickListener를 추가한다.
      • 클릭 시 ContentOverviewActivity.newIntent(requireContext(), ContentOverviewType.NEW_AND_HOT_AUDIO)로 이동한다.
      • ensureMainV2NavigationAllowed로 기존 콘텐츠 navigation guard 패턴을 따른다.
      • 기존 전체 탭 이동 대상 섹션 click listener는 Phase 4 동작을 유지한다.
    • 검증:
      • Run: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • Expected: 콘텐츠 New&Hot 신규 전체보기 이동 source 테스트 PASS.
    • 검증 기록:
      • 구현 시 이 Task 아래에 명령, 결과, 확인 내용을 한국어로 누적한다.
      • 2026-06-27 RED 테스트 수정: ContentMainFragmentSourceTestNew&Hot 미연결 assertion을 Phase 7 라우팅 assertion으로 변경해 ContentOverviewActivity/ContentOverviewType import, viewContentNewAndHotTitle.ivSectionTitleChevron.setOnClickListener, NEW_AND_HOT_AUDIO 이동 helper를 요구하도록 했다.
      • 2026-06-27 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"를 production 구현 전 병렬 실행했으나 Gradle/Kotlin daemon cache 충돌 및 동시 compile 오류로 테스트 assertion 결과까지 도달하지 못했다. 이후 ./gradlew --stop으로 daemon을 정리하고 순차 검증으로 전환했다.
      • 2026-06-27 구현: ContentMainFragmentContentOverviewActivity, ContentOverviewType import를 추가하고 viewContentNewAndHotTitle.ivSectionTitleChevron.setOnClickListener에서 ensureMainV2NavigationAllowed를 거쳐 ContentOverviewActivity.newIntent(requireContext(), ContentOverviewType.NEW_AND_HOT_AUDIO) 경로로 이동하도록 연결했다. 기존 전체 탭 이동 대상 섹션의 openContentAllTab 연결은 유지했다.
      • 2026-06-27 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest"
      • GREEN 결과: PASS. 최초 GREEN 시도에서는 source assertion이 helper 구조가 아닌 literal intent 호출을 기대해 1회 실패했고, production 코드는 유지한 채 openContentOverview(ContentOverviewType.NEW_AND_HOT_AUDIO)/ContentOverviewActivity.newIntent(requireContext(), type) 구조를 검증하도록 테스트를 조정한 뒤 PASS했다.
      • 2026-06-27 리뷰 후속 보강: ContentMainFragmentSourceTestopenContentOverview(type) 함수 내부에서 ensureMainV2NavigationAllowedstartActivity보다 먼저 호출되고 ContentOverviewActivity.newIntent(requireContext(), type)를 실행하는 순서를 검증하도록 보강했다.

Phase 8: 통합 검증과 수동 확인

  • Task 8.1: 단위/source 테스트 실행

    • 실행:
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.*"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
      • ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*"
    • 기대 결과:
      • 수정된 홈/콘텐츠/MainV2 source 테스트와 신규 overview 테스트가 모두 PASS한다.
    • 검증 기록:
      • 구현 시 이 Task 아래에 실행 명령과 결과를 한국어로 누적한다.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.*"
      • 결과: PASS.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"
      • 결과: PASS.
      • 2026-06-27 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*"
      • 결과: PASS.
  • Task 8.2: 빌드/리소스/린트 검증

    • 실행:
      • ./gradlew :app:mergeDebugResources
      • ./gradlew :app:compileDebugKotlin
      • ./gradlew :app:ktlintCheck
      • git diff --check
    • 기대 결과:
      • resource merge, Kotlin compile, ktlint, whitespace 검증이 모두 PASS한다.
    • 검증 기록:
      • 구현 시 이 Task 아래에 실행 명령과 결과를 한국어로 누적한다.
      • 2026-06-27 실행: ./gradlew :app:mergeDebugResources
      • 결과: PASS.
      • 2026-06-27 실행: ./gradlew :app:compileDebugKotlin
      • 결과: PASS.
      • 2026-06-27 실행: ./gradlew :app:ktlintCheck
      • 결과: PASS.
      • 2026-06-27 실행: git diff --check
      • 결과: PASS(출력 없음).
  • Task 8.3: 수동 화면 검증

    • 확인:
      • 홈 추천 탭 처음부터 함께 성장! title 우측 chevron 표시.
      • 콘텐츠 추천 탭 오직 보이스온에서만!, 새로 올라온 오디오, New&Hot, 무료 오디오, 포인트 오디오 title 우측 chevron 표시.
      • 콘텐츠 추천 탭 댓글 많은 오디오, 추천 오디오에는 chevron이 표시되지 않음.
      • 콘텐츠 추천 탭 오직 보이스온에서만! chevron 클릭 시 콘텐츠 전체 -> 오리지널 진입.
      • 콘텐츠 추천 탭 새로 올라온 오디오 chevron 클릭 시 콘텐츠 전체 -> 오디오 진입.
      • 콘텐츠 추천 탭 무료 오디오 chevron 클릭 시 콘텐츠 전체 -> 무료 + 인기순 진입.
      • 콘텐츠 추천 탭 포인트 오디오 chevron 클릭 시 콘텐츠 전체 -> 포인트 + 인기순 진입.
      • 홈 추천 탭 처음부터 함께 성장! chevron 클릭 시 처음부터 함께 성장! 신규 전체보기 진입.
      • 콘텐츠 추천 탭 New&Hot chevron 클릭 시 New&Hot 신규 전체보기 진입.
      • 신규 전체보기 화면 title bar, back button, 2열 grid, tag, 성인 badge, 상세 이동.
      • 신규 전체보기 화면 하단 스크롤 시 page + 1 추가 요청.
    • 검증 기록:
      • 구현 시 이 Task 아래에 테스트 기기/빌드 variant/API 응답 조건과 확인 결과를 한국어로 누적한다.
      • 2026-06-27 상태: BLOCKED/미완료. 현재 작업 환경에서 Android 기기 또는 에뮬레이터를 통한 실제 화면 조작을 수행할 수 없어 홈/콘텐츠 chevron 표시, 기존 전체 탭 이동, 신규 전체보기 화면 진입/스크롤/상세 이동을 수동으로 확인하지 못했다.
      • 2026-06-27 대체 확인: Task 8.1의 source/unit 테스트와 Task 8.2의 resource merge/compile/ktlint/whitespace 검증은 모두 PASS했다. 실제 API 응답 기반 화면 표시와 사용자 조작 검증은 기기 또는 에뮬레이터가 준비된 환경에서 후속 확인이 필요하다.

Verification Log

  • 구현 완료 후 여러 Phase에 걸친 통합 검증, 회귀 검증, 최종 수동 확인 기록을 이 섹션에 누적한다.
  • 2026-06-27 Phase 3~4 범위 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentAllTabViewModelTest" 결과 PASS.
  • 2026-06-27 Phase 3~4 범위 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 3~4 범위 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.MainV2ActivitySourceTest" 결과 PASS.
  • 2026-06-27 Phase 3~4 범위 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 3~4 범위 실행: ./gradlew :app:ktlintCheck는 신규 source 테스트의 긴 줄로 1회 실패 후 포맷 수정, 재실행 결과 PASS. 기존 .editorconfigdisabled_rules deprecation 경고는 출력되었으나 실패 원인은 아니었다.
  • 2026-06-27 Phase 3~4 범위 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 수동 화면 검증: Android 기기/에뮬레이터를 사용할 수 없어 Phase 4 기존 전체 탭 이동 수동 클릭 검증은 완료하지 못했다. Task 4.2에 BLOCKED/미완료로 기록했다.
  • 2026-06-27 Phase 5~6 범위 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 인접 회귀 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 인접 회귀 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 범위 실행: ./gradlew :app:mergeDebugResources 결과 PASS.
  • 2026-06-27 Phase 5~6 범위 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 5~6 범위 실행: ./gradlew :app:ktlintCheck는 신규 overview 테스트의 긴 줄/unused import로 1회 실패 후 포맷 수정, 재실행 결과 PASS. 기존 .editorconfigdisabled_rules deprecation 경고는 출력되었으나 실패 원인은 아니었다.
  • 2026-06-27 Phase 5~6 범위 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 5~6 범위 확인: rg -n "viewHomeFirstAudioTitle\.ivSectionTitleChevron\.setOnClickListener|viewContentNewAndHotTitle\.ivSectionTitleChevron\.setOnClickListener" app/src/main/java/kr/co/vividnext/sodalive/v2/main/home app/src/main/java/kr/co/vividnext/sodalive/v2/main/content 결과 매치 없음. Phase 7 신규 전체보기 이동 라우팅은 아직 추가하지 않았다.
  • 2026-06-27 Phase 5~6 코드 리뷰 확인: 문서 기준 발견 사항 2건을 확인했다. 1) 신규 API DTO 필드명이 PRD/계획서의 items/contentId/coverImage와 달리 contents/audioContentId/imageUrl로 구현되어 서버 계약 확인 또는 수정이 필요하다. 2) contentId <= 0 item 상세 이동 무시 조건이 누락되어 수정이 필요하다.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:mergeDebugResources는 sandbox의 ~/.gradle lock 접근 제한으로 1회 실패 후 권한 상승 재실행 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:ktlintCheck 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 5~6 인접 회귀 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 인접 회귀 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 리뷰 후속 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 예상 실패. 테스트가 문서 계약 items/contentId/coverImage와 invalid contentId <= 0 guard를 요구하지만 production이 아직 이전 DTO 계약과 guard 누락 상태였음을 확인했다.
  • 2026-06-27 Phase 5~6 리뷰 후속 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 리뷰 후속 확인: rg -n "totalCount|contents|audioContentId|imageUrl" "app/src/main/java/kr/co/vividnext/sodalive/v2/main/content/overview" "app/src/test/java/kr/co/vividnext/sodalive/v2/main/content/overview" 실행 결과 audioContentId, imageUrl 잔여 참조는 없고 contents는 API path/문자열 이름의 정상 매치만 남았다.
  • 2026-06-27 Phase 5~6 리뷰 후속 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 리뷰 후속 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 리뷰 후속 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 리뷰 후속 재검증 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 5~6 리뷰 후속 재검증 실행: ./gradlew :app:ktlintCheck는 테스트 fixture 들여쓰기 문제로 1회 실패 후 수정, 재실행 결과 PASS. 기존 .editorconfigdisabled_rules deprecation 경고는 출력되었으나 실패 원인은 아니었다.
  • 2026-06-27 Phase 5~6 리뷰 후속 재검증 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Git 상태 확인: app/src/main/res/drawable-mdpi/ic_new_arrow_up_gray.png, app/src/main/res/drawable-mdpi/ic_new_arrow_up_white.pngAD 상태이며 현재 소스/문서에서 참조되지 않는다. 커밋 전 포함 여부 정리가 필요하다.
  • 2026-06-27 Phase 5~6 코드 리뷰 재확인: ContentOverviewActivity.renderLoading()은 RecyclerView와 empty/error TextView를 숨기기만 하고, activity_content_overview.xml에도 loading/progress view가 없어 PRD의 첫 페이지 로딩/추가 페이지 로딩 상태 구분 요구가 사용자에게 표시되지 않는다. ContentOverviewViewModel.isLoading도 Activity에서 observe하지 않는다. 코드 수정이 필요하다.
  • 2026-06-27 Phase 5~6 fresh 검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 fresh 검증 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 5~6 fresh 검증 실행: ./gradlew :app:ktlintCheck 결과 PASS.
  • 2026-06-27 Phase 5~6 fresh 검증 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 5~6 fresh 검증 실행: ./gradlew :app:mergeDebugResources는 sandbox의 ~/.gradle wrapper lock 접근 제한으로 1회 실패 후 권한 상승 재실행 결과 PASS.
  • 2026-06-27 Phase 5~6 인접 회귀 fresh 검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 인접 회귀 fresh 검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 loading UI 후속 작업 시작: PRD의 첫 페이지 로딩/추가 페이지 로딩 상태 구분 요구를 사용자에게 보이는 UI로 반영하기 위해 Task 6.6을 추가했다. Phase 7 라우팅과 legacy 파일 수정은 범위에서 제외한다.
  • 2026-06-27 Phase 5~6 loading UI 후속 RED 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest" 결과 예상 실패. layout progress id와 Activity 로딩 바인딩이 아직 없음을 확인했다.
  • 2026-06-27 Phase 5~6 loading UI 후속 GREEN 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest" 결과 PASS.
  • 2026-06-27 Phase 5~6 loading UI 후속 검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 loading UI 후속 검증 실행: ./gradlew :app:mergeDebugResources 결과 PASS.
  • 2026-06-27 Phase 5~6 loading UI 후속 검증 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 5~6 loading UI 후속 검증 실행: ./gradlew :app:ktlintCheck 결과 PASS. 기존 .editorconfigdisabled_rules deprecation 경고는 출력되었으나 실패 원인은 아니었다.
  • 2026-06-27 Phase 5~6 loading UI 후속 검증 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 5~6 코드 리뷰 및 검증 재확인: Phase 5 API/DTO/Repository/UI model과 Phase 6 ViewModel/Activity/Adapter 구현을 PRD/계획서 기준으로 재검토했고 추가 코드 수정이 필요한 발견 사항은 없었다. Task 6.6은 코드와 검증 기록이 완료 상태라 체크박스를 완료로 갱신했다.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*" 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:mergeDebugResources는 sandbox의 ~/.gradle wrapper lock 접근 제한으로 1회 실패 후 권한 상승 재실행 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: ./gradlew :app:ktlintCheck 결과 PASS.
  • 2026-06-27 Phase 5~6 재검증 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 7 범위 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest" 결과 PASS.
  • 2026-06-27 Phase 7 범위 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 7 범위 실행: ./gradlew :app:ktlintCheckHomeMainFragmentSourceTest의 긴 assertion 줄로 1회 실패 후 포맷 수정, 재실행 결과 PASS. 기존 .editorconfigdisabled_rules deprecation 경고는 출력되었으나 실패 원인은 아니었다.
  • 2026-06-27 Phase 7 범위 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 7 수동 화면 검증: 현재 작업 환경에서 Android 기기 또는 에뮬레이터를 통한 실제 화면 조작을 수행할 수 없어 홈 처음부터 함께 성장! 및 콘텐츠 New&Hot chevron 클릭 후 신규 전체보기 화면 진입은 실제 앱 화면에서 확인하지 못했다. source 테스트와 compile/ktlint로 라우팅 계약은 검증했다.
  • 2026-06-27 Phase 7 리뷰 게이트 결과: source 테스트가 신규 overview 라우팅의 ensureMainV2NavigationAllowed guard 경유를 충분히 고정하지 못한다는 지적으로 1회 Reject를 받았다. production 코드는 유지하고 홈/콘텐츠 source 테스트의 guard 내부 순서 검증을 보강했다.
  • 2026-06-27 Phase 7 리뷰 후속 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest" 결과 PASS.
  • 2026-06-27 Phase 7 리뷰 후속 재검증 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 7 리뷰 후속 재검증 실행: ./gradlew :app:ktlintCheck 결과 PASS. 기존 .editorconfigdisabled_rules deprecation 경고는 출력되었으나 실패 원인은 아니었다.
  • 2026-06-27 Phase 7 리뷰 후속 재검증 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 7 코드 리뷰 및 점검: 홈 처음부터 함께 성장!과 콘텐츠 New&Hot chevron이 각각 ContentOverviewType.FIRST_AUDIO_CONTENT, ContentOverviewType.NEW_AND_HOT_AUDIOContentOverviewActivity.newIntent(...)를 호출하고, 두 경로 모두 ensureMainV2NavigationAllowed guard를 먼저 경유하는 것을 확인했다. 추가 코드 수정이 필요한 발견 사항은 없었다.
  • 2026-06-27 Phase 7 코드 리뷰 및 점검 재검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.content.ContentMainFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.content.overview.ContentOverviewActivitySourceTest" 결과 PASS.
  • 2026-06-27 Phase 7 코드 리뷰 및 점검 재검증 실행: ./gradlew :app:compileDebugKotlin 결과 PASS.
  • 2026-06-27 Phase 7 코드 리뷰 및 점검 재검증 실행: ./gradlew :app:ktlintCheck 결과 PASS.
  • 2026-06-27 Phase 7 코드 리뷰 및 점검 재검증 실행: git diff --check 결과 PASS(출력 없음).
  • 2026-06-27 Phase 8 통합 검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.*" 결과 PASS.
  • 2026-06-27 Phase 8 통합 검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*" 결과 PASS.
  • 2026-06-27 Phase 8 통합 검증 실행: ./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.content.overview.*" 결과 PASS.
  • 2026-06-27 Phase 8 빌드/리소스/린트 검증 실행: ./gradlew :app:mergeDebugResources, ./gradlew :app:compileDebugKotlin, ./gradlew :app:ktlintCheck, git diff --check 결과 모두 PASS.
  • 2026-06-27 Phase 8 수동 화면 검증: Android 기기/에뮬레이터를 사용할 수 없어 실제 화면 조작 검증은 BLOCKED로 남겼다. 자동 테스트와 빌드 검증은 모두 통과했다.