152 KiB
메인 홈 팔로잉 탭 구현 계획/TASK
For agentic workers: REQUIRED SUB-SKILL: 구현 시
superpowers:subagent-driven-development또는superpowers:executing-plans를 사용해 task 단위로 진행한다. 각 단계는 체크박스(- [ ])로 추적하고, 완료 즉시- [x]로 갱신한다. 구현 범위 변경이 생기면 이 문서를 먼저 수정한 뒤 코드에 반영한다.
Goal: GET /api/v2/home/following 응답을 기반으로 메인 홈 팔로잉 탭에 팔로잉 크리에이터, On Air, 최근 대화, 이달의 스케줄, 최근 소식을 표시한다.
Architecture: 기존 HomeMainFragment의 title bar, TextTabBarView, 추천/랭킹 탭 구조는 유지하고, 팔로잉 선택 시 전용 content surface를 노출한다. 신규 API/Repository/DTO/UI state/mapper/ViewModel/adapter는 kr.co.vividnext.sodalive.v2.main.home 하위에 두며, ChatRoomListItemResponse, CreatorActivityType, formatUtcRelativeTimeText, 기존 feed/live/profile widget을 우선 재사용한다. 로그인 유도 화면은 아직 디자인/문구가 정해지지 않았으므로 이번 구현 계획에서는 isLoginRequired 상태 분기와 팔로잉 섹션 숨김까지만 고정한다.
Tech Stack: Kotlin, Android XML Views, ViewBinding, RecyclerView, Retrofit, Gson, RxJava3, Koin, JUnit4/Robolectric local unit test.
전제와 성공 기준
- PRD:
docs/20260625_메인_홈_팔로잉_탭/prd.md - Figma:
home_003팔로잉 탭24:5682 - API endpoint는
GET /api/v2/home/following이다. Authorizationheader는 optional이며, token이 blank이면 header를 보내지 않는다.- query parameter는 보내지 않는다.
isLoginRequired = true이면 팔로잉 섹션을 표시하지 않는다.- 로그인 유도 화면의 실제 UI, 문구, CTA, 로그인 완료 후 복귀 정책은 별도 확정 후 구현한다.
recentNews시간은visibleFromAtUtc를 디바이스 타임존 기준으로 상대 시간 표시한다.PHOTO_CONTENTlabel은 우선화보로 표시한다.recentNews는type에 대응하는 nested payload가 null이면 해당 news item을 표시하지 않는다.monthlySchedules는 서버가 이번 달 범위로 정렬해서 내려주며 앱은 재정렬하지 않는다.- 섹션 title chevron은 터치 콜백까지만 연결하고 실제 이동 목적지는 만들지 않는다.
- 구현 완료 후 최소 다음 명령을 실행한다.
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"./gradlew :app:mergeDebugResources./gradlew :app:compileDebugKotlin./gradlew :app:ktlintCheckgit diff --check
Figma 참조 필요 Phase
- Phase 1: 제한 참조
- 기존 홈 탭 구조, v2 위젯, DI/API 패턴 확인 중심으로 진행한다.
- Phase 2: Figma 참조 불필요
- API/DTO/Repository와 mapper 상태는 PRD 서버 계약과 기존 v2 data layer 패턴을 따른다.
- Phase 3: Figma 참조 불필요
- ViewModel 상태, optional auth header,
isLoginRequired분기는 단위 테스트 중심으로 검증한다.
- ViewModel 상태, optional auth header,
- Phase 4: 필수 참조
- 팔로잉 크리에이터, On Air, 최근 대화, 이달의 스케줄, 최근 소식 섹션 배치와 spacing은 Figma
24:5682를 기준으로 확인한다.
- 팔로잉 크리에이터, On Air, 최근 대화, 이달의 스케줄, 최근 소식 섹션 배치와 spacing은 Figma
- Phase 5: 필수 참조
- 최종 수동 화면 검증은 PRD의 포함/제외 항목과 실제 화면을 대조한다.
- Phase 9: Figma 참조 불필요
- 최근 소식 Response 계약 변경은 DTO/mapper/test fixture 중심으로 진행하고, 기존 Feed 위젯 표시 정책과 레이아웃은 유지한다.
파일 구조
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingApi.ktGET /api/v2/home/followingRetrofit endpoint를 정의한다.
- Create/Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingModels.ktHomeFollowingTabResponse,FollowingCreatorResponse,FollowingLiveResponse,FollowingScheduleResponse,FollowingNewsResponse,FollowingCreatorRankingNewsResponse,FollowingContentNewsResponse,FollowingContentRankingNewsResponse,FollowingCommunityPostNewsResponse,FollowingNewsTypeDTO를 정의한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingRepository.kt- API 호출을 repository method로 감싼다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingUiState.ktLoading,LoginRequired,Content,Empty,Error상태를 정의한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingUiModels.kt- 팔로잉 크리에이터, live, chat, schedule, news section/item UI model을 정의한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingMappers.kt- DTO를 UI model/state로 변환하고, matching nested payload null news 숨김,
PHOTO_CONTENTlabel,visibleFromAtUtc시간 기준을 적용한다.
- DTO를 UI model/state로 변환하고, matching nested payload null news 숨김,
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingAuthHeader.kt- blank token이면
null, 값이 있으면Bearer {token}을 반환한다.
- blank token이면
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingViewModel.kt- 팔로잉 탭 API 호출, loading/error/login-required/content 상태를 관리한다.
- Modify:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.ktHomeFollowingApi,HomeFollowingRepository,HomeFollowingViewModel을 Koin에 등록한다.
- Modify:
app/src/main/res/layout/fragment_v2_main_home.xml- 팔로잉 탭 content surface와 섹션 RecyclerView들을 추가한다.
- Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktHOME_TAB_FOLLOWING분기, ViewModel observer, adapter binding, section visibility, chevron click callback을 연결한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.ktfollowingCreatorshorizontal profile list를 바인딩한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingLiveAdapter.ktonAirLiveshorizontal live card list를 바인딩한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.ktrecentChatshorizontal chat card list를 바인딩한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingScheduleAdapter.ktmonthlySchedulesvertical schedule list를 바인딩한다.
- Create:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.ktrecentNewsvertical news list를 바인딩한다.
- Create:
app/src/main/res/layout/item_home_following_creator.xml- 팔로잉 크리에이터 profile item이다.
- Create:
app/src/main/res/layout/item_home_following_live.xml- On Air live item이다.
- Create:
app/src/main/res/layout/item_home_following_chat.xml- 최근 대화 compact card item이다.
- Create:
app/src/main/res/layout/item_home_following_schedule.xml- 이달의 스케줄 item이다.
- Reuse:
app/src/main/res/layout/view_feed_rank.xml,app/src/main/res/layout/view_feed_content.xml,app/src/main/res/layout/view_feed_community.xml- 최근 소식은 기존 Feed 위젯 layout을 재사용한다.
- Delete:
app/src/main/res/layout/item_home_following_news_rank.xml,app/src/main/res/layout/item_home_following_news_content.xml- Task 6.5에서 Feed 위젯 전환 후 obsolete 팔로잉 전용 최근 소식 layout을 제거했다.
- Modify:
app/src/main/res/values/strings.xml- 팔로잉 섹션 title,
On Air,화보, empty/error label을 추가한다.
- 팔로잉 섹션 title,
- Modify:
app/src/main/res/values-en/strings.xml- 팔로잉 섹션 title,
On Air, photo label, empty/error label을 추가한다.
- 팔로잉 섹션 title,
- Modify:
app/src/main/res/values-ja/strings.xml- 팔로잉 섹션 title,
On Air, photo label, empty/error label을 추가한다.
- 팔로잉 섹션 title,
- Create:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingAuthHeaderTest.kt- optional auth header 생성 규칙을 검증한다.
- Create:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingMapperTest.kt- DTO to UI mapping, login-required, rank null filtering, news label/time 기준을 검증한다.
- Create:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingViewModelTest.kt- API success/error/login-required/loading 상태 전환을 검증한다.
- Create:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt- layout id, adapter/ViewModel 연결,
HOME_TAB_FOLLOWING분기, chevron click callback 연결을 source-level로 검증한다.
- layout id, adapter/ViewModel 연결,
Phase 1: 기존 구조 확인과 작업 경계 고정
-
Task 1.1: 홈 탭 삽입 지점 확인
- 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/res/layout/fragment_v2_main_home.xmlapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeRecommendationViewModel.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeCreatorRankingViewModel.kt
- 작업:
- 기존
추천,랭킹,팔로잉Text Tab bar는 유지한다. showHomeTab(HOME_TAB_FOLLOWING)분기에서 팔로잉 surface를 표시할 위치를 확인한다.- 추천/랭킹 API와 ViewModel은 리팩터링하지 않는다.
- 기존
- 검증:
- Run:
rg -n "HOME_TAB_FOLLOWING|showHomeTab|nsvHomeRecommendationContent|rvHomeCreatorRankings|textTabBarHome" app/src/main/java/kr/co/vividnext/sodalive/v2/main/home app/src/main/res/layout/fragment_v2_main_home.xml - Expected: 팔로잉 탭 분기와 기존 추천/랭킹 surface visibility 제어 지점이 확인된다.
- Result: PASS.
HomeMainFragment.kt에서showHomeTab,HOME_TAB_FOLLOWING, 추천/랭킹 visibility 제어 지점을 확인했다.
- Run:
- 확인:
-
Task 1.2: 재사용 위젯과 신규 adapter 경계 확정
- 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeCreatorProfileImageLoader.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/widget/livethumbnail/LiveThumbnailDetailView.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedItem.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedRankView.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedContentView.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedCommunityView.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/model/ChatRoomMappers.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityType.kt
- 작업:
- 프로필 이미지 로딩은
HomeCreatorProfileImageLoader또는 같은 placeholder 정책 재사용으로 고정한다. - 채팅 데이터 변환은
ChatRoomListItemResponse.toUiItem()재사용으로 고정한다. - 스케줄 type label은
CreatorActivityType.labelResId재사용으로 고정한다. - Figma와 크기가 맞지 않는 카드들은 팔로잉 전용 adapter/layout 신규 생성으로 고정한다.
- 프로필 이미지 로딩은
- 검증:
- Run:
rg -n "HomeCreatorProfileImageLoader|class LiveThumbnailDetailView|sealed class FeedItem|fun ChatRoomListItemResponse.toUiItem|enum class CreatorActivityType" app/src/main/java/kr/co/vividnext/sodalive/v2 - Expected: 재사용 후보 클래스와 함수가 확인된다.
- Result: PASS.
LiveThumbnailDetailView,FeedItem,ChatRoomListItemResponse.toUiItem(),CreatorActivityType재사용 후보를 확인했다.
- Run:
- 확인:
-
Task 1.3: 제외 범위 확인
- 확인:
docs/20260625_메인_홈_팔로잉_탭/prd.md
- 제외:
- 로그인 유도 화면 실제 디자인/문구/CTA 구현
- 더보기 chevron 목적지 이동
- 팔로잉/언팔로잉 액션
- 스케줄 월 필터와 앱 내 재정렬
- 레거시 홈 화면 직접 수정
- 검증:
- Run:
rg -n "Non-Goals|로그인 유도|더보기|monthlySchedules|rank|PHOTO_CONTENT|Open Questions" docs/20260625_메인_홈_팔로잉_탭/prd.md - Expected: 제외 범위와 확정 정책이 확인된다.
- Result: PASS. 로그인 유도 UI 미확정, 더보기 목적지 제외,
monthlySchedules정렬 정책,rank == null제외,PHOTO_CONTENTlabel 정책을 확인했다.
- Run:
- 확인:
Phase 2: API, DTO, Repository, mapper 추가
-
Task 2.1: optional auth header 테스트 작성
- 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingAuthHeaderTest.kt
- 테스트 케이스:
- blank token은
null을 반환한다. - non-blank token은
Bearer {token}을 반환한다. - 앞뒤 공백이 있는 token은 trim 후
Bearer {token}을 반환한다.
- blank token은
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingAuthHeaderTest" - Expected: helper 구현 전 RED 실패.
- Result: RED 확인.
homeFollowingAuthHeader미구현으로compileDebugUnitTestKotlinunresolved reference 실패가 발생했다.
- Run:
- 생성:
-
Task 2.2: optional auth header helper 구현
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingAuthHeader.kt
- 작업:
fun homeFollowingAuthHeader(token: String): String?를 추가한다.token.trim().takeIf { it.isNotEmpty() }?.let { "Bearer $it" }규칙을 적용한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingAuthHeaderTest" - Expected: PASS.
- Result: PASS. blank/whitespace token은
null, non-blank token은 trim 후Bearer {token}으로 검증됐다.
- Run:
- 생성:
-
Task 2.3: API/DTO/Repository 계약 추가
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingApi.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingModels.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingRepository.kt
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
- 작업:
- Retrofit endpoint는
@GET("/api/v2/home/following")로 정의한다. @Header("Authorization") authHeader: String?를 사용한다.- query parameter는 정의하지 않는다.
- DTO는 PRD의 Android Response Contract 필드를 모두 포함하고
@Keep,@SerializedName을 사용한다. recentChats는 기존ChatRoomListItemResponse를 사용한다.FollowingScheduleResponse.type은 기존CreatorActivityType을 사용한다.- Koin
networkModule,repositoryModule에 신규 API/Repository를 등록한다.
- Retrofit endpoint는
- 검증:
- Run:
./gradlew :app:compileDebugKotlin - Expected: 신규 data layer와 DI 등록이 컴파일된다.
- Result: PASS.
HomeFollowingApi, DTO, Repository, API/Repository DI 등록이compileDebugKotlin에서 컴파일됐다.
- Run:
- 생성:
-
Task 2.4: string resource 추가
- 수정:
app/src/main/res/values/strings.xmlapp/src/main/res/values-en/strings.xmlapp/src/main/res/values-ja/strings.xml
- 작업:
- 섹션 title 문자열을 추가한다.
screen_home_following_creators_titlescreen_home_following_on_air_titlescreen_home_following_recent_chats_titlescreen_home_following_monthly_schedules_titlescreen_home_following_recent_news_title
- news/category 문자열을 추가한다.
screen_home_following_on_airscreen_home_following_photo_content
- empty/error 문자열을 추가한다.
screen_home_following_emptyscreen_home_following_error
- 섹션 title 문자열을 추가한다.
- 검증:
- Run:
./gradlew :app:mergeDebugResources - Expected: 3개 locale string resource가 중복 없이 merge된다.
- Result: PASS.
values,values-en,values-jastring resource merge가 통과했다.
- Run:
- 수정:
-
Task 2.5: mapper RED 테스트 작성
- 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingMapperTest.kt
- 테스트 케이스:
isLoginRequired = true응답은HomeFollowingUiState.LoginRequired로 매핑된다.isLoginRequired = false이고 모든 섹션이 비면HomeFollowingUiState.Empty로 매핑된다.followingCreators,onAirLives,recentChats,monthlySchedules,recentNews가 section UI model로 매핑된다.recentChats는ChatRoomListItemResponse.toUiItem()결과가 null인 항목을 제외한다.monthlySchedules는 서버 응답 순서를 유지한다.PHOTO_CONTENT는screen_home_following_photo_contentlabel로 매핑된다.CREATOR_RANKING,CONTENT_RANKING의rank == null항목은 제외된다.- news 상대 시간은
visibleFromAtUtc값을 formatter에 전달한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest" - Expected: UI model/mapper 구현 전 RED 실패.
- Result: RED 확인. DTO/UI model/mapper/string resource 미구현으로
compileDebugUnitTestKotlinunresolved reference 실패가 발생했다.
- Run:
- 생성:
-
Task 2.6: UI state/model과 mapper 구현
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingUiState.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingUiModels.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingMappers.kt
- 작업:
HomeFollowingUiState는Loading,LoginRequired,Content,Empty,Error를 정의한다.Content에는followingCreators,onAirLives,recentChats,monthlySchedules,recentNewssection을 둔다.Content.isEmptyhelper를 추가해 모든 section item이 비었는지 판정한다.- mapper는
UtcRelativeTimeTextFormatter를 받아visibleFromAtUtc상대 시간을 생성한다. - ranking news의
rank == null은 map 단계에서 제외한다. PHOTO_CONTENT는 photo label string resource id를 매핑한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest" - Expected: PASS.
- Result: PASS. login-required, empty, content mapping, invalid chat 제외, schedule 순서 유지,
PHOTO_CONTENTlabel, null rank filtering,visibleFromAtUtcformatter 전달이 검증됐다.
- Run:
- 생성:
Task 2.7: 미사용 팔로잉 string resource 정리
Goal 실행 P2-R1: 확정 review 항목 REV-P2-001에 따라 후속 UI·오류 처리 변경 후 참조되지 않는 팔로잉 문자열 리소스만 제거한다.
- 시작 조건:
reviews/phase2-following-data-mapper-review.md의REV-P2-001확정. - 완료 증거: 3개 미사용 key의 참조 0건 재확인 → 3개 locale 선언 제거 → resource merge·Kotlin compile·팔로잉 회귀·diff 검증 PASS.
- 범위 밖: 사용 중인
screen_home_following_on_air, empty·ranking·section title 문자열 변경, 표시 문구 재기획, UI 구조 변경. - TDD 예외 사유: 실행 로직이 아닌 미사용 Android resource 선언 삭제이며, 이를 위한 신규 source test는 저장소 테스트 정책에 맞지 않는다.
- 대체 검증 방법:
rg로 참조 0건을 재확인하고 resource merge, Kotlin compile, 기존 팔로잉 회귀 테스트,git diff --check를 실행한다.
Files:
-
Modify:
app/src/main/res/values/strings.xml -
Modify:
app/src/main/res/values-en/strings.xml -
Modify:
app/src/main/res/values-ja/strings.xml -
screen_home_following_creators_title,screen_home_following_on_air_title,screen_home_following_error의 production/test 참조가 0건인지 재확인한다. -
3개 locale에서 위 3개 key만 제거하고 사용 중인 팔로잉 문자열은 유지한다.
-
./gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlin과./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"를 실행한다. -
git diff --check를 실행하고 검증 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-31:
rg -n "screen_home_following_creators_title|screen_home_following_on_air_title|screen_home_following_error" app/src/main/java app/src/main/res/layout app/src/test결과 선언 외 참조 0건을 확인했다. 3개 localestrings.xml에서 위 3개 key만 제거하고screen_home_following_on_air, empty, ranking, section title 문자열은 유지했다../gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlinPASS. 이후 팔로잉 전체 회귀 첫 실행에서R.stringid 변경 증분 캐시로HomeFollowingMapperTest2건이 실패해./gradlew --no-daemon --rerun-tasks :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest"로 재빌드했고 PASS. 최종./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS.
Task 2.8: 미사용 최근 소식 label UI model 정리
Goal 실행 P2-R2: 확정 review 항목 REV-P2-002에 따라 Feed category로 대체된 후 production에서 사용하지 않는 HomeFollowingNewsUiItem.Content.labelResId와 전용 mapper를 제거한다.
- 시작 조건:
reviews/phase2-following-data-mapper-review.md의REV-P2-002확정. - 완료 증거: production 참조 0건 재확인 → UI model·mapper·fixture의 미사용 label 경로 제거 → Feed
Photocategory의 locale label 회귀·Kotlin compile·ktlint PASS. - 범위 밖:
FeedContentCategory구조,screen_home_following_photo_content문구, 최근 소식 API/DTO·표시·라우팅 변경. - TDD 예외 사유: 실행 동작 수정이 아닌 미사용 UI model 필드와 mapper 제거이며, 기존 Feed category 회귀로 동작 무변경을 검증한다.
- 대체 검증 방법:
rg로 production/test 참조를 대조하고 mapper·adapter focused test, Kotlin compile, ktlint,git diff --check를 실행한다.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingUiModels.kt -
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingMappers.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingMapperTest.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingNewsAdapterTest.kt -
rg -n "labelResId|toLabelResId"결과로 최근 소식Content.labelResId와FollowingNewsType.toLabelResId()가 production 표시에서 사용되지 않는지 재확인한다. -
HomeFollowingNewsUiItem.Content.labelResId, mapper 대입과 전용toLabelResId()만 제거하고 FeedAudio/Photocategory mapping은 유지한다. -
mapper/adapter test fixture에서 제거된 필드를 정리하고
PHOTO_CONTENT표시가FeedContentCategory.Photo와 locale string을 사용하는 회귀를 유지한다. -
mapper·news adapter focused test, 팔로잉 전체 회귀,
:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행하고 결과를 누적한다.
검증 기록:
- 2026-07-31:
rg -n -- "labelResId|toLabelResId" app/src/main/java/kr/co/vividnext/sodalive/v2/main/home app/src/test/java/kr/co/vividnext/sodalive/v2/main/home로 팔로잉 최근 소식Content.labelResId와FollowingNewsType.toLabelResId()의 production 표시 참조가 없음을 재확인했다.HomeFollowingNewsUiItem.Content.labelResId, mapper 대입, 전용toLabelResId()를 제거했고,HomeFollowingNewsAdapterTest에PHOTO_CONTENT가 실제FeedContentCategory.Photolocale label로 표시되는 회귀를 추가했다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest", 팔로잉 전체 회귀,:app:mergeDebugResources,:app:compileDebugKotlin,:app:ktlintCheckPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
Phase 3: ViewModel 상태와 API 호출 연결
-
Task 3.1: ViewModel RED 테스트 작성
- 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingViewModelTest.kt
- 테스트 케이스:
loadFollowing()은 loading 후 content 상태를 발행한다.- blank token이면 repository에 null auth header를 전달한다.
- token이 있으면 repository에
Bearer {token}auth header를 전달한다. isLoginRequired = true응답은 login-required 상태를 발행한다.- API success이지만 data가 null이면 error 상태와 toast를 발행한다.
- API failure throwable이면 error 상태와 toast를 발행한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingViewModelTest" - Expected: ViewModel 구현 전 RED 실패.
- Result: RED 확인.
HomeFollowingViewModel미구현으로compileDebugUnitTestKotlinunresolved reference 실패가 발생했다.
- Run:
- 생성:
-
Task 3.2: HomeFollowingViewModel 구현
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingViewModel.kt
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
- 작업:
HomeFollowingViewModel(repository, relativeTimeTextFormatter)를 추가한다.SharedPreferenceManager.token을homeFollowingAuthHeader()로 변환해 repository에 전달한다.- RxJava3
subscribeOn(Schedulers.io()),observeOn(AndroidSchedulers.mainThread())패턴을 따른다. - success data는 mapper로 UI state 변환한다.
- error는
HomeFollowingUiState.Error와 기존 unknown error toast 패턴을 따른다. - Koin
viewModelModule에HomeFollowingViewModel(get(), get())를 등록한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingViewModelTest" - Expected: PASS.
- Result: PASS. loading/content, optional auth header, login-required, null data error/toast, throwable error/toast 상태 전환이 검증됐다.
- Run:
- 생성:
-
Task 3.3: data/model/ViewModel 통합 컴파일 확인
- 확인:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingApi.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingModels.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingMappers.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingViewModel.ktapp/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt
- 검증:
- Run:
./gradlew :app:compileDebugKotlin - Expected: 팔로잉 data/model/ViewModel/DI 코드가 컴파일된다.
- Result: PASS. 팔로잉 data/model/ViewModel/DI 코드가
compileDebugKotlin에서 컴파일됐다.
- Run:
- 검증 기록:
- 2026-06-25 코드 리뷰: Phase 1~3 범위의 API/DTO/Repository/mapper/ViewModel/DI/string/test 변경을 검토했으며, 현재 코드 기준으로 blocking finding은 발견하지 못했다.
- 2026-06-25 검증:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS.
- 확인:
Task 3.4: ViewModel Loading → 결과 상태 발행 순서 회귀 검증
Goal 실행 P3-R1: 확정 review 항목 REV-P3-001에 따라 loadFollowing()의 Loading과 최종 상태 발행 순서를 실행 가능한 테스트로 고정한다.
- 시작 조건:
reviews/phase3-following-viewmodel-review.md의REV-P3-001확정. - 완료 증거: 상태 이력 assertion 추가 → Phase 3 focused test와 팔로잉 전체 회귀 PASS.
- 범위 밖:
HomeFollowingViewModel상태 구조 변경, scheduler 교체, repository/API 변경. - TDD 예외 사유: production은 이미
Loading과 결과 상태를 순서대로 발행하며, 확정 항목은 동작 결함이 아니라 기존 테스트의 assertion 누락이므로 의도적인 production 변조 없이 RED를 만들지 않는다. - 대체 검증 방법: observer 상태 이력으로
Loading → Content를 직접 assertion하고 기존 error/login-required 테스트와 전체 팔로잉 회귀를 실행한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingViewModelTest.kt -
observer가 수집한 상태 이력이
Loading과Content를 순서대로 포함하도록 테스트 fixture와 assertion을 최소 보완한다. -
production 파일 변경이 없고 기존 error/login-required 테스트가 그대로 유지되는지 diff로 확인한다.
-
GREEN 확인:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingViewModelTest"를 실행한다. -
회귀 검증:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"와git diff --check를 실행하고 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-30:
HomeFollowingViewModelTest.loadFollowing은 loading 후 content 상태를 발행한다에 observer 상태 이력 assertion을 추가해Loading → Content순서를 고정했다. production 파일은 변경하지 않았다. focused test와 팔로잉 전체 회귀,git diff --check가 PASS했다.
Phase 4: 팔로잉 탭 UI surface와 adapter 연결
-
Task 4.1: Fragment source RED 테스트 작성
- 생성:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt
- 테스트 케이스:
fragment_v2_main_home.xml에nsv_home_following_content가 있다.- layout에
rv_home_following_creators,rv_home_following_on_air_lives,rv_home_following_recent_chats,rv_home_following_monthly_schedules,rv_home_following_recent_news가 있다. HomeMainFragment가HomeFollowingViewModel을 주입한다.HOME_TAB_FOLLOWING분기에서 팔로잉 surface를 visible 처리한다.- section title chevron click listener가 연결되어 있고 실제 route 호출은 없다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: layout/fragment 수정 전 RED 실패.
- Result: RED 확인. layout ID와
HomeMainFragment팔로잉 wiring 미구현 상태에서 6개 source test가 모두 실패했다.
- Run:
- 생성:
-
Task 4.2: 팔로잉 content layout 추가
- 수정:
app/src/main/res/layout/fragment_v2_main_home.xml
- 생성:
app/src/main/res/layout/item_home_following_creator.xmlapp/src/main/res/layout/item_home_following_live.xmlapp/src/main/res/layout/item_home_following_chat.xmlapp/src/main/res/layout/item_home_following_schedule.xmlapp/src/main/res/layout/item_home_following_news_rank.xmlapp/src/main/res/layout/item_home_following_news_content.xml
- 작업:
nsv_home_following_content를text_tab_bar_home아래에 추가하고 기본visibility="gone"으로 둔다.- 섹션 순서는
followingCreators,On Air,recentChats,monthlySchedules,recentNews로 둔다. - 각 섹션 title은
view_section_title을 include한다. - 로그인 유도 화면 전용 layout은 이번 phase에서 추가하지 않는다.
- 검증:
- Run:
./gradlew :app:mergeDebugResources - Expected: 신규 layout/resource가 merge된다.
- Result: PASS.
nsv_home_following_content, 5개 섹션 RecyclerView, 6개 item layout이 resource merge를 통과했다.
- Run:
- 수정:
-
Task 4.3: 팔로잉 adapter 구현
- 생성:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingLiveAdapter.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingScheduleAdapter.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt
- 작업:
- 각 adapter는
submitItems()와 item click callback을 제공한다. - profile image는 기존
loadHomeCreatorProfileImage()또는 동일 placeholder 정책을 사용한다. - recent chat은
ChatRoomListUiItem을 바인딩한다. - schedule은
CreatorActivityType.labelResId,isOnAir,scheduledAtUtc표시 모델을 사용한다. - news adapter는 rank item과 content item view type을 분리한다.
- 각 adapter는
- 검증:
- Run:
./gradlew :app:compileDebugKotlin - Expected: 신규 adapter가 컴파일된다.
- Result: PASS. 팔로잉 creator/live/chat/schedule/news adapter 5개가
compileDebugKotlin에서 컴파일됐다.
- Run:
- 생성:
-
Task 4.4: HomeMainFragment에 팔로잉 탭 연결
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
- 작업:
private val homeFollowingViewModel: HomeFollowingViewModel by viewModel()을 추가한다.- 팔로잉 adapter 5개를 초기화한다.
showHomeTab(HOME_TAB_FOLLOWING)에서 추천/랭킹 surface를 숨기고 팔로잉 surface를 표시한다.- 팔로잉 탭 최초 선택 시
homeFollowingViewModel.loadFollowing()을 1회 호출한다. LoginRequired상태에서는 팔로잉 섹션 content를 숨긴다.Content상태에서는 각 section item이 비어 있으면 해당 섹션을 숨긴다.- section title chevron은
onFollowingSectionMoreClick(section)callback까지만 연결하고 route는 호출하지 않는다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: PASS.
- Result: PASS. 팔로잉 ViewModel 주입, adapter 연결, 탭 surface 전환, 최초 1회 load, login-required/empty/error 섹션 숨김, content 섹션 binding이 source test로 검증됐다.
- Run:
- 수정:
-
Task 4.5: UI routing skeleton 연결
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
- 작업:
- creator item click은 기존
openCreatorProfile(creatorId)를 재사용한다. - recent chat item click은 기존 v2 chat/DM 진입 flow를 확인해 재사용 가능한 메서드로 연결한다.
- live, schedule, news item click은
type/targetId별 route 함수로 분리한다. - 목적지가 확정되지 않은 더보기 chevron은 route 없이 callback만 받는다.
- creator item click은 기존
- 검증:
- Run:
rg -n "openFollowing|onFollowing|HomeFollowingSection|openCreatorProfile|HOME_TAB_FOLLOWING" app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt - Expected: 팔로잉 item click과 more click 콜백 함수가 확인된다.
- Result: PASS. creator click은
openCreatorProfile, recent chat click은 기존 AI/DM chat 진입 flow로 연결했고 live/schedule/news/more click은 route 없는 callback skeleton으로 유지했다.
- Run:
- 검증 기록:
- 2026-06-25 Phase 4 코드 리뷰: Figma
24:5682와 PRD 기준으로On Air시작 시간, 이달의 스케줄 프로필/타입 label/On Air 상태, 최근 소식 label/title 바인딩 누락을 확인했다. 누락 항목은HomeFollowingFragmentSourceTestRED로 고정한 뒤 adapter/layout 최소 수정으로 보완했다. - 2026-06-25 Phase 4 재코드 리뷰: 현재 워킹트리 기준
HomeMainFragment, 팔로잉 adapter 5개, 팔로잉 layout,HomeFollowingFragmentSourceTest를 Figma24:5682/PRD와 대조했으며 blocking finding은 발견하지 못했다.
- 2026-06-25 Phase 4 코드 리뷰: Figma
- 수정:
Task 4.6: On Air·스케줄 item 상세 이동 연결
Goal 실행 P4-R1: 확정 review 항목 REV-P4-001에 따라 On Air와 이달의 스케줄 item 터치가 기존 공통 도메인 액션으로 실제 이동하도록 한다.
- 시작 조건:
reviews/phase4-following-ui-routing-review.md의REV-P4-001확정과FollowingLiveResponse.liveId,FollowingScheduleResponse.type/targetId계약 확인. - 완료 증거: no-op 재현 RED → 기존 Live/Creator/Content/Community Action을 재사용한 GREEN → focused test와 공통 액션 회귀 PASS.
- 범위 밖: 더보기 chevron 목적지, 최근 소식
CONTENT_RANKING·PHOTO_CONTENT이동, 공통 액션 정책 변경.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLoginGuardSourceTest.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
RED: On Air와 schedule type별 공통 액션 호출을 요구하는 테스트를 추가해 현재
Unit구현에서 실패하는지 확인한다. -
GREEN: On Air는
liveActionCoordinator.enterLiveRoom(item.liveId)를 사용하고, 스케줄은CreatorActivityType과targetId를 기존 최근 활동 route 정책에 맞춰 Live/Content/Community 공통 액션으로 전달한다. -
방어 검증:
targetId <= 0L과 지원하지 않는 route는 공통 액션 호출 전에 무시하고, 직접Intent또는 legacy extra를 만들지 않는지 검증한다. -
회귀 검증: home focused test,
v2.live.action.*,v2.content.action.*,v2.community.action.*,:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행한다.
검증 기록:
- 2026-07-30 RED:
HomeMainFragmentLoginGuardSourceTest에 팔로잉 On Air와 스케줄 type별 공통 Action 호출 assertion을 추가했고, 구현 전onFollowingLiveClick()/onFollowingScheduleClick()이Unit이라 focused test가 실패하는 것을 확인했다. - 2026-07-30 GREEN: On Air는
liveActionCoordinator.enterLiveRoom(item.liveId), 스케줄은targetId > 0L일 때CreatorActivityType.Live는 live action,LiveReplay/Audio는ContentActionCommand.AudioDetail,Community는CommunityActionCommand.PostDetail로 연결했다. 직접Intent조립은 추가하지 않았다. focused test, 팔로잉 전체 회귀, 공통 action 테스트,:app:compileDebugKotlin,:app:ktlintCheck,git diff --checkPASS.
Task 4.7: LoginRequired 당겨서 새로고침 종료 보장
Goal 실행 P4-R2: 확정 review 항목 REV-P4-002에 따라 팔로잉 새로고침 응답이 LoginRequired여도 spinner와 refresh 추적 상태를 종료한다.
- 시작 조건:
reviews/phase4-following-ui-routing-review.md의REV-P4-002확정과 기존finishHomePullRefresh(HOME_TAB_FOLLOWING)정책 확인. - 완료 증거:
LoginRequired분기의 refresh 종료 누락 RED → 최소 분기 보완 GREEN → 팔로잉·홈 refresh 회귀 PASS. - 범위 밖: 로그인 유도 UI/문구/CTA,
ensureV2Access정책, ViewModel API 계약 변경.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
Test:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLayoutTest.kt -
RED: pull refresh 중
LoginRequired상태가finishHomePullRefresh(HOME_TAB_FOLLOWING)을 호출하지 않는 현재 분기를 재현한다. -
GREEN:
LoginRequired에서 section 숨김 후 팔로잉 refresh를 종료하고, 일반 진입에서는 불필요한 scroll 변경이 없는 최소 분기를 적용한다. -
GREEN 확인: 팔로잉 Fragment focused test와 홈 pull-refresh 관련 focused test를 실행한다.
-
회귀 검증: 팔로잉 전체 회귀,
:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행하고 결과를 누적한다.
검증 기록:
- 2026-07-30 RED:
HomeFollowingFragmentSourceTest가LoginRequired분기에서finishHomePullRefresh(HOME_TAB_FOLLOWING)호출을 요구하도록 보강했고, 구현 전 focused test 실패로 누락을 확인했다. - 2026-07-30 GREEN:
LoginRequired분기에서 섹션을 숨긴 뒤 팔로잉 pull-refresh 종료를 호출하도록 최소 보완했다. focused test, 팔로잉 전체 회귀,:app:compileDebugKotlin,:app:ktlintCheck,git diff --checkPASS.
Task 4.8: blank 프로필 이미지의 이전 Coil 요청 해제
Goal 실행 P4-R3: 확정 review 항목 REV-P4-003에 따라 재사용된 프로필 ImageView에 blank URL을 바인딩할 때 이전 Coil 요청을 해제해 다른 item의 이미지가 뒤늦게 표시되지 않도록 한다.
- 시작 조건:
reviews/phase4-following-ui-routing-review.md의REV-P4-003확정과 PRD의 blank profile image fallback 정책 확인. - 완료 증거: 이전 Coil 요청이 남는 재사용 시나리오 RED → blank 분기에서 요청 해제와 drawable 초기화 GREEN → profile loader focused test와 팔로잉 전체 회귀 PASS.
- 범위 밖: non-blank 이미지 transformation/placeholder 디자인 변경, Coil 전역 설정 변경, adapter 구조 변경.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeCreatorProfileImageLoader.kt -
Create:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeCreatorProfileImageLoaderTest.kt -
Modify:
docs/agent-guides/build-test-style.md -
RED: Robolectric
ImageView에 Coil 요청을 연결한 뒤 blank URL을 바인딩하고, 기존 요청이 해제되지 않는 현재 동작을coil.result또는 동등한 요청 상태 assertion으로 재현한다. -
GREEN:
loadHomeCreatorProfileImage()의 blank 분기에서coil.dispose()로 이전 요청을 해제한 뒤 drawable을 비우는 최소 수정만 적용한다. -
GREEN 확인:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorProfileImageLoaderTest"를 실행한다. -
회귀 검증: 팔로잉 전체 회귀,
:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행하고 신규 테스트 단일 실행 예시를 빌드 가이드에 반영한다.
검증 기록:
- 2026-07-30 RED:
HomeCreatorProfileImageLoaderTest를 추가해 blank profile URL 바인딩 시 기존 CoilDisposable이 해제되어야 함을 검증했고, 구현 전assertTrue(disposable.isDisposed)실패로 현재 요청이 남는 동작을 확인했다. - 2026-07-30 GREEN:
loadHomeCreatorProfileImage()blank 분기에서dispose()후setImageDrawable(null)을 호출하도록 최소 수정했다. focused test, 팔로잉 전체 회귀와 신규 프로필 테스트,:app:mergeDebugResources,:app:compileDebugKotlin,:app:ktlintCheck,git diff --checkPASS.build-test-style.md에HomeCreatorProfileImageLoaderTest단일 실행 예시를 추가했다.
Task 4.9: 팔로잉 공용 source test 이름 규칙 정합성 보완
Goal 실행 P4-R4: 확정 review 항목 REV-P4-004에 따라 HomeFollowingFragmentSourceTest에 남은 영문 문장형 테스트명을 검증 의도가 드러나는 한글 문장으로 변경한다.
- 시작 조건:
reviews/phase4-following-ui-routing-review.md의REV-P4-004확정과docs/agent-guides/build-test-style.md의 신규 Kotlin 테스트명 규칙 확인. - 완료 증거: 영문 문장형 테스트명 11개 한글화 → assertion·production 코드 무변경 확인 → Fragment focused test·팔로잉 전체 회귀·ktlint·diff 검증 PASS.
- 범위 밖: 테스트 assertion 재설계, production 코드·resource 변경, 다른 테스트 클래스의 기존 이름 일괄 수정.
- TDD 예외 사유: runtime 동작 결함이 아니라 테스트 이름 규칙 정합성 수정이므로 production RED/GREEN을 만들지 않는다.
- 대체 검증 방법: 대상 파일의
@Test함수명을rg로 확인하고 변경 전후 assertion diff, focused test, 팔로잉 전체 회귀를 대조한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
완전한 영문 문장으로 남은 backtick 테스트명 11개를 각 검증 의도가 드러나는 한글 문장으로 변경한다.
-
테스트 본문의 assertion과 helper, production 코드·resource가 변경되지 않았는지 diff로 확인한다.
-
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest"를 실행한다. -
팔로잉 전체 회귀,
:app:ktlintCheck,git diff --check를 실행하고 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-31:
HomeFollowingFragmentSourceTest의 완전한 영문 문장형 backtick 테스트명 11개를 검증 의도가 드러나는 한글 문장으로 변경했다. Task 9.6의 신규 한글 테스트 추가 외 기존 assertion/helper와 production/resource 변경은 포함하지 않았다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest", 팔로잉 전체 회귀와:app:compileDebugKotlin,:app:ktlintCheckPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
Phase 5: 통합 검증과 문서 기록
-
Task 5.1: 팔로잉 관련 단위 테스트 실행
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 팔로잉 관련 local unit/source test가 모두 PASS.
- Run:
- 검증 기록:
- 2026-06-25 Phase 4 리뷰 보완 후 실행 결과 PASS. 팔로잉 관련 local unit/source test가 모두 통과했다.
- 검증:
-
Task 5.2: 리소스/컴파일/린트 검증
- 검증:
- Run:
./gradlew :app:mergeDebugResources - Expected: 신규 layout/string resource merge PASS.
- Run:
./gradlew :app:compileDebugKotlin - Expected: Kotlin compile PASS.
- Run:
./gradlew :app:ktlintCheck - Expected: ktlint PASS.
- Run:
git diff --check - Expected: whitespace error 없음.
- Run:
- 검증 기록:
- 2026-06-25 Phase 4 리뷰 보완 후
./gradlew :app:mergeDebugResourcesPASS. 최초 sandbox lock 권한 오류 후 승인 실행으로 통과했다. - 2026-06-25 Phase 4 리뷰 보완 후
./gradlew :app:compileDebugKotlinPASS. - 2026-06-25 Phase 4 리뷰 보완 후
./gradlew :app:ktlintCheckPASS. 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-25 Phase 4 리뷰 보완 후
git diff --checkPASS.
- 2026-06-25 Phase 4 리뷰 보완 후
- 검증:
-
Task 5.3: Figma 기준 수동 확인
- 확인:
- Figma
24:5682 app/src/main/res/layout/fragment_v2_main_home.xml
- Figma
- 수동 확인 항목:
팔로잉탭 선택 시 추천/랭킹 content가 겹쳐 보이지 않는다.- 섹션 순서가
팔로잉 크리에이터→On Air→최근 대화→이달의 스케줄→최근 소식이다. - title bar와 tab bar는 고정되고 팔로잉 content만 세로 스크롤된다.
- empty section은 숨겨진다.
isLoginRequired상태에서 팔로잉 섹션 content는 표시되지 않는다.- 더보기 chevron 터치 시 앱이 크래시하지 않고 화면 이동은 발생하지 않는다.
- 검증 기록:
- 2026-06-25 Figma
24:5682디자인 컨텍스트와 스크린샷 기준 정적 대조를 수행했다. 실제 기기/에뮬레이터에서의 수동 화면 확인은 아직 실행하지 않았다. - 2026-06-25 Phase 5 진행: Figma
24:5682스크린샷과fragment_v2_main_home.xml,HomeMainFragment.kt를 대조했다. 팔로잉 탭 전용nsv_home_following_content가 title bar/tab bar 아래 별도 scroll surface로 배치되어 있고, 팔로잉 선택 시 추천/랭킹 surface를 숨기는 분기, 섹션 순서, empty/login-required 섹션 숨김, 더보기 chevron no-op callback 연결을 정적으로 확인했다. - 2026-06-25 Phase 5 진행: 실제 기기 검증을 위해
adb devices에서2cec640c34017ece연결을 확인한 뒤./gradlew :app:installDebug를 실행했으나, 설치 중 디바이스 연결이 해제되어device '2cec640c34017ece' not found로 실패했다. 재확인 시adb devices에 연결된 디바이스가 없어 실제 화면 수동 확인은 blocked 상태로 남긴다. - 2026-07-31 Task 2.7 완료 후 재확인:
adb devices는 정상 실행됐지만List of devices attached아래 연결 기기가 없어 Figma/API 데이터 기반 실기기 수동 확인은 계속 보류한다. - 2026-07-31 Task 4.9/9.6 완료 중 재확인:
adb devices에서2cec640c34017ece연결을 확인했고./gradlew --no-daemon :app:installDebug,adb shell monkey -p kr.co.vividnext.sodalive.debug -c android.intent.category.LAUNCHER 1PASS. 다만adb exec-out screencap -p로 저장한/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/sodalive-home-after-launch.png와 5초 대기 후 재촬영한sodalive-home-after-launch-2.png가 모두 검은 화면으로 분석되어 팔로잉 탭 content와 Figma24:5682상세 대조는 완료하지 못했다.
- 2026-06-25 Figma
- 확인:
Phase 6: Figma 디자인 재대조 후속 수정
-
Task 6.1: 디자인 불일치 RED 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt
- 작업:
- 팔로잉 크리에이터 섹션에 header include가 없는지 검증한다.
- 최근 대화 RecyclerView가 horizontal인지 검증한다.
- 최근 대화 item이 Figma box 카드 폭/프로필/Direct badge/상대시간 바인딩을 갖는지 검증한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: 구현 전 RED 실패.
- Result: RED 확인. 팔로잉 크리에이터 header 제거, 최근 대화 horizontal box list, 최근 대화 Figma box field 검증 3개가 현재 구현과 맞지 않아 실패했다.
- Run:
- 수정:
-
Task 6.2: 팔로잉 크리에이터와 최근 대화 UI 수정
- 수정:
app/src/main/res/layout/fragment_v2_main_home.xmlapp/src/main/res/layout/item_home_following_creator.xmlapp/src/main/res/layout/item_home_following_chat.xmlapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.kt
- 작업:
- 팔로잉 크리에이터 section header를 제거한다.
- 팔로잉 크리에이터 profile item을 Figma의 simple profile 크기에 맞춘다.
- 최근 대화 RecyclerView를 horizontal로 변경한다.
- 최근 대화 item을 Figma의 box card 형태로 조정하고 Direct badge와 상대시간 표시를 유지한다.
- 최근 대화 시간은 기존
formatChatRoomLastMessageTime()을 유지해 server ISO 시간을 디바이스 timezone 기준 상대시간/날짜로 표시한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: PASS.
- Result: PASS. 팔로잉 크리에이터 header 제거, 75dp simple profile item, 최근 대화 horizontal box list, Direct badge/상대시간 바인딩이 source test로 검증됐다.
- Run:
- 수정:
-
Task 6.3: 후속 변경 통합 검증
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 팔로잉 관련 local unit/source test가 모두 PASS.
- Run:
./gradlew :app:mergeDebugResources - Expected: layout/resource merge PASS.
- Run:
./gradlew :app:compileDebugKotlin - Expected: Kotlin compile PASS.
- Run:
./gradlew :app:ktlintCheck - Expected: ktlint PASS.
- Run:
git diff --check - Expected: whitespace error 없음.
- Run:
- 검증 기록:
- 2026-06-26 후속 변경 검증:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"최초 병렬 실행 중HomeFollowingViewModelTest.blank token이면 repository에 null auth header를 전달한다1건이 실패했으나, 동일 테스트 단독 재실행과 전체 팔로잉 테스트 단독 재실행은 모두 PASS했다. 실패는SharedPreferenceManager전역 상태를 쓰는 테스트의 병렬 Gradle 실행 간섭으로 판단했다. - 2026-06-26 후속 변경 검증:
./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-26 실제 표면 검증:
adb devices에서2cec640c34017ece연결을 확인했고,./gradlew :app:installDebug로kr.co.vividnext.sodalive.debug설치 PASS.adb shell monkey -p kr.co.vividnext.sodalive.debug -c android.intent.category.LAUNCHER 1로 런처 실행 PASS. 팔로잉 탭 내부 API 데이터 기반 화면 대조는 자동 조작/테스트 계정 상태가 없어 정적 source test와 설치/실행 검증으로 대체했다. - 2026-06-26 리뷰 지적 수정: 최근 대화 adapter가 XML
284dp폭을 런타임MATCH_PARENT로 덮는 문제를 확인했다.HomeFollowingFragmentSourceTest.following recent chat item matches figma box fields에 RED 검증을 추가했고,HomeFollowingChatAdapter를recyclerItemLayoutParams(parent)사용으로 변경해 XML 폭을 유지했다. 해당 테스트 재실행 PASS. - 2026-06-26 테스트 안정화:
SharedPreferenceManager.resetForTest()가 DataStore 저장값을 지우지 않아HomeFollowingViewModelTest묶음 실행 시 token이 이전 값으로 복원될 수 있음을 확인했다. 테스트setUp()의 시작 token을 빈 값으로 명시해 테스트 격리를 보강했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"재실행 PASS. - 2026-06-26 후속 요청 반영: 최근 대화 item의 대화 내용 표시를 한 줄로 제한하고
ellipsize="end"를 유지했다.HomeFollowingFragmentSourceTest.following recent chat item matches figma box fields에maxLines="1"/ellipsis 검증을 추가해 RED 확인 후 GREEN 전환했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest.following recent chat item matches figma box fields",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,git diff --check모두 PASS.
- 2026-06-26 후속 변경 검증:
- 검증:
-
Task 6.4: 최근 소식 Feed 위젯 재사용과 chevron 후속 수정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt
- 작업:
- 최근 소식 section title의 chevron을 표시하지 않는다.
COMMUNITY_POST최근 소식은 기존v2.widget.feed.FeedCommunityView와view_feed_community.xml을 재사용한다.- ranking 최근 소식은 기존
v2.widget.feed.FeedRankView와view_feed_rank.xml을 재사용한다. - 오디오/화보 content 최근 소식은 기존
v2.widget.feed.FeedContentView와view_feed_content.xml을 재사용한다. - 최근 소식 API에 없는 댓글 수, 좋아요 수, 잠금/오너 액션 값은 임의 생성하지 않고 현재 모델 범위에서 0 또는 빈 값으로 둔다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: PASS.
- Run:
- 검증 기록:
- 2026-06-26 최근 소식 후속 수정: 먼저
HomeFollowingFragmentSourceTest에 최근 소식 chevron 제거와 Feed 위젯 재사용 검증을 추가해 RED를 확인했다. 이후HomeMainFragment에서 최근 소식showMore = true와 chevron listener를 제거했고,HomeFollowingNewsAdapter가COMMUNITY_POST는FeedCommunityView, ranking은FeedRankView, audio/photo content는FeedContentView를 inflate/bind하도록 변경했다. - 2026-06-26 최근 소식 후속 검증:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
- 2026-06-26 최근 소식 후속 수정: 먼저
- 수정:
Task 6.5: Feed 위젯 전환 후 obsolete 최근 소식 layout 제거
Goal 실행 P6-R1: 확정 review 항목 REV-P6-001에 따라 runtime에서 사용하지 않는 팔로잉 전용 news layout과 잘못된 preview 참조를 제거한다.
- 시작 조건:
reviews/phase6-figma-follow-up-review.md의REV-P6-001확정과HomeFollowingNewsAdapter의 Feed 위젯 사용 확인. - 완료 증거: resource 참조 검색 → preview를 실제 Feed layout으로 교체 → obsolete layout 2개 삭제 → resource merge와 source test PASS.
- 범위 밖: Feed 위젯 UI 재설계, 최근 소식 DTO/mapper/routing 변경.
Files:
-
Delete:
app/src/main/res/layout/item_home_following_news_rank.xml -
Delete:
app/src/main/res/layout/item_home_following_news_content.xml -
Modify:
app/src/main/res/layout/fragment_v2_main_home.xml -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
RED:
rg와 source test로 두 obsolete layout이 runtime adapter에서 사용되지 않고tools:listitem만 과거 layout을 가리키는 상태를 고정한다. -
GREEN: 최근 소식 preview를 실제
view_feed_content로 교체하고 obsolete layout 2개를 삭제한다. -
GREEN 확인:
./gradlew --no-daemon :app:mergeDebugResources와HomeFollowingFragmentSourceTest를 실행한다. -
회귀 검증: 팔로잉 전체 회귀,
:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행한다.
검증 기록:
- 2026-07-30 RED:
HomeFollowingFragmentSourceTest가 최근 소식 previewtools:listitem과 obsolete layout 파일 제거를 요구하도록 보강했고, 구현 전 과거 layout 참조/파일 존재로 실패했다. - 2026-07-30 GREEN:
fragment_v2_main_home.xml의 최근 소식 preview를@layout/view_feed_content로 교체하고item_home_following_news_rank.xml,item_home_following_news_content.xml을 삭제했다.:app:mergeDebugResources, focused test, 팔로잉 전체 회귀,:app:compileDebugKotlin,:app:ktlintCheck,git diff --checkPASS.
Task 6.6: 삭제된 최근 소식 layout의 파일 구조 문서 정합성 보완
Goal 실행 P6-R2: 확정 review 항목 REV-P6-002에 따라 상단 파일 구조가 Feed 위젯 전환 후 현재 resource 구성을 정확히 설명하도록 갱신한다.
- 시작 조건:
reviews/phase6-figma-follow-up-review.md의REV-P6-002확정과 Task 6.5의 obsolete layout 삭제 완료. - 완료 증거: 상단 파일 구조에서 삭제된 두 layout의 Create 항목 제거 또는 삭제 이력 명시 → 실제 Feed layout 참조와 문서 대조 → 문서 diff 검증 PASS.
- 범위 밖: 삭제된 layout 복원, Feed 위젯 UI·adapter·DTO·routing 변경.
- TDD 예외 사유: 계획 문서의 현재 파일 목록을 바로잡는 문서 전용 수정이므로 실행 가능한 실패 test를 만들지 않는다.
- 대체 검증 방법:
rg로 삭제된 layout의 runtime 참조와 상단 파일 구조 문구를 대조하고git diff --check를 실행한다.
Files:
-
Modify:
docs/20260625_메인_홈_팔로잉_탭/plan-task.md -
상단
파일 구조에서item_home_following_news_rank.xml,item_home_following_news_content.xml을 현재 생성 파일로 오인하지 않도록 정리한다. -
HomeFollowingNewsAdapter가 재사용하는view_feed_rank,view_feed_content,view_feed_community와 Task 6.5 삭제 이력을 문서에서 확인 가능하게 유지한다. -
rg -n "item_home_following_news_(rank|content)|view_feed_(rank|content|community)" docs/20260625_메인_홈_팔로잉_탭/plan-task.md app/src/main으로 문서와 runtime 참조를 대조한다. -
git diff --check를 실행하고 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-30: 상단
파일 구조의 obsolete 최근 소식 layout 2개를 Create 항목에서 제거하고, runtime Feed layout 3종 재사용 및 Task 6.5 삭제 이력을 명시했다.rg -n "item_home_following_news_(rank|content)|view_feed_(rank|content|community)" docs/20260625_메인_홈_팔로잉_탭/plan-task.md app/src/main대조 결과 runtime adapter는view_feed_rank,view_feed_content,view_feed_community를 참조하고 삭제 layout은 문서/이력 참조로만 남는 것을 확인했다.git diff --checkPASS.
Task 6.7: 최근 대화 고정 폭 LayoutParams 보존
Goal 실행 P6-R3: 확정 review 항목 REV-P6-003에 따라 최근 대화 item의 XML 284dp 폭을 런타임에서도 유지하면서 기존 item 간격을 보존한다.
- 시작 조건:
reviews/phase6-figma-follow-up-review.md의REV-P6-003확정. - 완료 증거: inflate 직후
284dpwidth를WRAP_CONTENT로 교체하는 경로 제거 → 기존 layout parameter에 end margin만 적용 → resource merge·Kotlin compile·팔로잉 회귀 PASS → 연결 기기 준비 시 Task 5.3에서 폭/간격 수동 확인. - 범위 밖: 최근 대화 카드의 Figma 크기 변경, 공통 helper의 전체 호출부 리팩터링, 다른 팔로잉 adapter 수정.
- TDD 예외 사유:
docs/agent-guides/code-style.md가 View width·margin 같은 UI 표현 속성 테스트 추가를 금지하므로 새 자동 UI 크기 테스트를 작성하지 않는다. - 대체 검증 방법:
item_home_following_chat.xml,HomeFollowingChatAdapter.kt,HomeRecyclerItemLayoutParams.kt를 정적 대조하고 resource merge·Kotlin compile·기존 팔로잉 로직 회귀 및 가능한 경우 실기기 수동 확인을 수행한다.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.kt -
Verify:
app/src/main/res/layout/item_home_following_chat.xml -
HomeFollowingChatAdapter.onCreateViewHolder()가 inflate된 root의 기존 width/height를 보존하고 end margin만 추가하도록 최소 수정한다. -
공통 helper나 다른 adapter를 불필요하게 변경하지 않았는지 diff로 확인한다.
-
./gradlew --no-daemon :app:mergeDebugResources,:app:compileDebugKotlin, 팔로잉 전체 회귀를 실행한다. -
연결 기기가 있으면 Task 5.3에서 최근 대화 카드 폭과 item 간격을 확인하고, 없으면 미실행 사유를 기록한다.
검증 기록:
- 2026-07-30:
HomeFollowingChatAdapter.onCreateViewHolder()에서recyclerItemLayoutParams(parent)사용을 제거하고 inflate된RecyclerView.LayoutParams의 width/height를 유지한 채spacing_12end margin만 적용했다. 공통 helper와 다른 adapter는 변경하지 않았다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint가 PASS했다.adb devices에 연결 기기가 없어 최근 대화 카드 폭/간격 실기기 확인은 Task 5.3 보류 사유와 함께 유지한다.
Task 6.8: creator·최근 대화 UI 표현 속성 source test 정합성 보완
Goal 실행 P6-R4: 확정 review 항목 REV-P6-004에 따라 creator·최근 대화의 크기·방향·말줄임 값을 XML 문자열로 고정하는 source assertion을 제거하고 허용된 구조·바인딩 검증만 유지한다.
- 시작 조건:
reviews/phase6-figma-follow-up-review.md의REV-P6-004확정과docs/agent-guides/code-style.md테스트 관례 확인. - 완료 증거: 금지된 XML 크기·orientation·style·maxLines·ellipsize assertion 제거 → production XML/adapter 무변경 → focused test·resource merge·Kotlin compile·ktlint PASS → 실기기 가능 시 Task 5.3에서 표현 속성 대조.
- 범위 밖: creator/chat production UI 값 변경, adapter 데이터 바인딩, 다른 기존 Feed 테스트 일괄 정리.
- TDD 예외 사유: 동작 결함 수정이 아닌 현행 테스트 정책 위반 assertion 제거이며 production은 변경하지 않는다.
- 대체 검증 방법: Figma와 production XML/adapter는 정적 대조하고, 자동 검증은 section 존재·adapter view type·필수 field 바인딩·click route와 순수 로직으로 한정한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
Verify:
app/src/main/res/layout/item_home_following_creator.xml -
Verify:
app/src/main/res/layout/item_home_following_chat.xml -
Verify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingChatAdapter.kt -
creator test에서
75dpwidth/height와 typography style source assertion을 제거하고 creator header 제거 구조 검증은 유지한다. -
최근 대화 test에서 XML orientation,
284dp/62dpwidth/height,maxLines/ellipsizesource assertion을 제거한다. -
Direct badge 노출 결정, 상대 시간 formatter, 필수 field 바인딩과 adapter click 계약 검증은 유지한다.
-
HomeFollowingFragmentSourceTest, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint,git diff --check를 실행하고 실기기 표현 확인 가능 여부를 누적한다.
검증 기록:
- 2026-07-31: creator source test명을
팔로잉 크리에이터 섹션은 header 없이 item layout을 사용한다로, 최근 대화 source test명을팔로잉 최근 대화 섹션은 RecyclerView와 adapter를 연결한다,팔로잉 최근 대화 item은 필수 field와 클릭 계약을 바인딩한다로 한글화했다. creator의75dp/typography, 최근 대화의 XML orientation,284dp/62dp,maxLines/ellipsizesource assertion은 제거하고 creator header 제거, 필수 field id, Direct badge, 상대 시간 formatter, click listener 계약은 유지했다.rg -n -- "75dp|284dp|62dp|android:orientation|android:maxLines|android:ellipsize|Typography.Body5" HomeFollowingFragmentSourceTest.kt결과 제거 대상 참조 0건을 확인했다.HomeFollowingFragmentSourceTest, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint PASS.adb devices에는 연결 기기가 없어 실기기 표현 확인은 Task 5.3 보류 상태를 유지한다.
Phase 7: 최근 소식 ranking 문장과 오디오 콘텐츠 feed 정합성 후속 수정
-
Task 7.1: Figma 기준과 현재 구현 불일치 RED 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedViewTest.kt
- 작업:
- 팔로잉 최근 소식 ranking item이
creatorNickname,rank, 문장형 message,FeedRankHighlight를 구성하는지 검증한다. view_feed_content.xml이 Figma1229:27212기준88dp이미지,14dp카드 gap,6dp프로필-타이틀 간격을 갖는지 검증한다.
- 팔로잉 최근 소식 ranking item이
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" - Expected: 구현 전 RED 실패.
- Result: RED 확인.
HomeFollowingFragmentSourceTest.following adapters bind figma required item fields,HomeFollowingFragmentSourceTest.following ranking news builds sentence message and highlights rank text,FeedViewTest.content layout matches figma compact upload notice dimensions3건이 현재 구현과 맞지 않아 실패했다.
- Run:
- 수정:
-
Task 7.2: 최근 소식 ranking message와 content feed layout 수정
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.ktapp/src/main/res/layout/view_feed_content.xmlapp/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedContentView.kt
- 작업:
- ranking feed message는
creatorNickname + rank + 문장으로 구성하고, 순위 구간만 highlight range로 전달한다. - content feed 이미지는
88dp정사각 기준으로 변경하고, 오른쪽 정보 컬럼은 Figma의 프로필/제목/메타 간격을 유지한다. FeedContentView의 기본 이미지 크기 계산 기준을88dp로 맞춘다.
- ranking feed message는
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" - Expected: PASS.
- Result: PASS. ranking news가 크리에이터명/순위를 포함한 문장형 message와 순위 highlight range를 구성하고, content feed가
88dp이미지 및 Figma compact feed 간격 기준을 갖도록 검증됐다.
- Run:
- 수정:
-
Task 7.3: 후속 변경 통합 검증
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 팔로잉 관련 local unit/source test가 모두 PASS.
- Run:
./gradlew :app:mergeDebugResources - Expected: layout/resource merge PASS.
- Run:
./gradlew :app:compileDebugKotlin - Expected: Kotlin compile PASS.
- Run:
./gradlew :app:ktlintCheck - Expected: ktlint PASS.
- Run:
git diff --check - Expected: whitespace error 없음.
- Run:
- 검증 기록:
- 2026-06-30 후속 변경 검증:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"PASS. - 2026-06-30 후속 변경 검증:
./gradlew :app:mergeDebugResources는 최초 병렬 실행 중 Gradle wrapper lock sandbox 권한 오류로 실패했고, 승인 실행 재시도에서 PASS. - 2026-06-30 후속 변경 검증:
./gradlew :app:compileDebugKotlinPASS. - 2026-06-30 후속 변경 검증:
git diff --checkPASS. - 2026-06-30 후속 변경 검증:
./gradlew :app:ktlintCheck는 FAIL. 실패 지점은 이번 변경 파일이 아닌app/src/main/java/kr/co/vividnext/sodalive/v2/widget/creatorranking/CreatorRankingTopCardView.kt:11의 기존 unused import이며, 저장소 규칙에 따라 unrelated 파일은 수정하지 않았다. - 2026-07-30 재검증: 현재 working tree 기준
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
- 2026-06-30 후속 변경 검증:
- 검증:
-
Task 7.4: content feed radius clipping 구현 위치 수정
- 수정:
app/src/main/res/layout/view_feed_content.xmlapp/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedContentView.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedViewTest.kt
- 작업:
view_feed_content.xml의android:clipToOutline속성을 제거한다.FeedContentViewroot view에서clipToOutline = true와ViewOutlineProvider.setRoundRect(...)를 설정한다.- 가이드
docs/agent-guides/code-style.md의 radius clipping 규칙을 source test로 고정한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" - Expected: RED 확인 후 PASS.
- Result: RED 확인 후 PASS.
view_feed_content.xml의android:clipToOutline제거와FeedContentViewroot의 KotlinclipToOutline/outlineProvider설정을 검증했다.
- Run:
- 검증 기록:
- 2026-06-30 clipping 위치 수정 후
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:compileDebugKotlin,git diff --checkPASS. - 2026-06-30 clipping 위치 수정 후
./gradlew :app:mergeDebugResources는 최초 병렬 실행 중 Gradle wrapper lock sandbox 권한 오류로 실패했고, 승인 실행 재시도에서 PASS.
- 2026-06-30 clipping 위치 수정 후
- 수정:
Task 7.5: ranking 순위 단위 locale 적용
Goal 실행 P7-R1: 확정 review 항목 REV-P7-001에 따라 ranking 문장의 순위 텍스트를 한국어·영어·일본어 locale에 맞게 표시하고 같은 구간을 highlight한다.
- 시작 조건:
reviews/phase7-ranking-content-feed-review.md의REV-P7-001확정. - 완료 증거: 영어·일본어에서도
"위"가 노출되는 RED → locale string format GREEN → 세 locale와 highlight range 회귀 PASS. - 범위 밖: ranking message 문장 자체 재기획, FeedRankView 스타일·색상 변경, API rank 계약 변경.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt -
Modify:
app/src/main/res/values/strings.xml -
Modify:
app/src/main/res/values-en/strings.xml -
Modify:
app/src/main/res/values-ja/strings.xml -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
Test:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingNewsAdapterTest.kt -
Modify:
docs/agent-guides/build-test-style.md -
RED: locale별 ranking message를 생성해 영어·일본어 결과에 한국어
"위"가 포함되는 현재 문제를 재현한다. -
GREEN: 순위 단위를 locale string resource로 분리해 한국어
위, 영어 locale 표기, 일본어位를 사용한다. -
highlight 검증: locale별 완성 문장에서 순위 문자열 index가 유효하고
FeedRankHighlight범위가 해당 문자열과 일치하는지 검증한다. -
회귀 검증: focused test, Feed view test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint,
git diff --check를 실행한다.
검증 기록:
- 2026-07-30 RED:
HomeFollowingNewsAdapterTest를 추가해 한국어/영어/일본어 locale별 ranking message와 highlight range를 검증했고, 구현 전buildHomeFollowingRankingFeedItem및 locale rank format 부재로 focused test가 실패했다. - 2026-07-30 GREEN:
screen_home_following_ranking_rank_format을 3개 locale에 추가하고 ranking feed item 생성 helper에서 locale rank 문자열을 만든 뒤 같은 문자열 범위를FeedRankHighlight로 전달하도록 변경했다. 한국어7위, 영어No. 7, 일본어7位focused test, Feed view test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint,git diff --checkPASS. - 2026-07-30 리뷰 게이트 후 보완: subject에 같은 rank 문자열이 먼저 포함될 때 highlight가 잘못 잡힐 수 있다는 Minor 지적을 받아
lastIndexOf(rankText)로 삽입된 순위 문자열을 강조하도록 보완했다. 중복 문자열 fixture RED 확인 후HomeFollowingNewsAdapterTest, focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint,git diff --checkPASS.
Task 7.6: 신규 ranking 테스트와 실행 가이드 정합성 보완
Goal 실행 P7-R2: 확정 review 항목 REV-P7-002에 따라 신규 ranking 단위 테스트가 저장소의 한글 테스트명과 단일 실행 가이드 규칙을 충족하도록 한다.
- 시작 조건:
reviews/phase7-ranking-content-feed-review.md의REV-P7-002확정과HomeFollowingNewsAdapterTest추가 상태. - 완료 증거: 신규 test name 한글화 →
build-test-style.md단일 실행 예시 추가 → focused test·ktlint·문서 diff PASS. - 범위 밖: ranking message·highlight production 로직, locale 문구, 기존 영어 테스트명의 일괄 변경.
- TDD 예외 사유: 동작 결함이 아니라 테스트/가이드 규칙 정합성 수정이므로 production RED를 만들지 않는다.
- 대체 검증 방법: 테스트 메서드명과 가이드 명령을
rg로 확인하고 focused test와 ktlint를 실행한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingNewsAdapterTest.kt -
Modify:
docs/agent-guides/build-test-style.md -
HomeFollowingNewsAdapterTest의 신규 backtick 테스트명 2개를 검증 의도가 드러나는 한글 문장으로 변경한다. -
docs/agent-guides/build-test-style.md에HomeFollowingNewsAdapterTest클래스 단위 실행 예시를 추가한다. -
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest"를 실행한다. -
./gradlew --no-daemon :app:ktlintCheck와git diff --check를 실행하고 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-30:
HomeFollowingNewsAdapterTest의 신규 ranking 테스트명 2개를 한글 문장으로 변경하고build-test-style.md에 클래스 단위 실행 예시를 추가했다.rg로 한글 테스트명과 가이드 예시를 확인했다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest",./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
Task 7.7: content feed UI 표현 속성 source test 정책 정합성 보완
Goal 실행 P7-R3: 확정 review 항목 REV-P7-003에 따라 가이드 제정 이후 추가된 content feed 크기·padding·margin source test를 제거하고 허용된 대체 검증으로 전환한다.
- 시작 조건:
reviews/phase7-ranking-content-feed-review.md의REV-P7-003확정. - 완료 증거:
content layout matches figma compact upload notice dimensions테스트 제거 → production layout/View 코드는 유지 → Feed/팔로잉 회귀·resource merge·Kotlin compile·ktlint PASS. - 범위 밖:
view_feed_content.xml의 88dp/간격 값 변경,FeedContentViewclipping 정책 변경, 다른 기존 Feed 테스트 일괄 정리. - TDD 예외 사유: 동작 결함 수정이 아니라 금지된 UI 표현 속성 테스트 제거이므로 RED/GREEN production 변경을 만들지 않는다.
- 대체 검증 방법: Figma 기준과
view_feed_content.xml/FeedContentView.kt를 정적 대조하고 resource merge·compile 및 Task 5.3 수동 화면 확인을 사용한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedViewTest.kt -
content layout matches figma compact upload notice dimensions테스트만 제거하고 production 파일을 변경하지 않는다. -
FeedViewTest의 로직·접근성·clipping 계약 테스트는 이번 범위에서 유지한다. -
Feed focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint를 실행한다.
-
Figma 크기/간격 대조 결과와 실기기 확인 가능 여부를 검증 기록에 남긴다.
검증 기록:
- 2026-07-30:
FeedViewTest에서 content feed 크기·padding·margin 문자열을 고정하던content layout matches figma compact upload notice dimensions테스트만 제거했다.view_feed_content.xml과FeedContentView.ktproduction 코드는 변경하지 않았고, content meta row·clipping·접근성 테스트는 유지했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint가 PASS했다. Figma 크기/간격은 기존 production XML/View 정적 대조로 유지하며,adb devices에 연결 기기가 없어 실기기 확인은 Task 5.3 보류 사유와 함께 유지한다.
Phase 8: 팔로잉 크리에이터 전체 버튼 후속 추가
-
Task 8.1: PRD 반영과 RED 테스트 추가
- 수정:
docs/20260625_메인_홈_팔로잉_탭/prd.mddocs/20260625_메인_홈_팔로잉_탭/plan-task.mdapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt
- 작업:
- 팔로잉 크리에이터 RecyclerView 마지막 item에
전체버튼을 항상 추가하는 후속 요구사항을 문서화한다. 전체버튼 layout이wrap_content, creator item과 동일한 높이,paddingHorizontal=16dp,@color/soda_400를 갖는지 source test로 고정한다.- adapter가 creator item과 all item view type을 분리하고 마지막 item count를 보장하는지 source test로 고정한다.
전체버튼 클릭이 기존FollowingCreatorActivity로 연결되는지 source test로 고정한다.
- 팔로잉 크리에이터 RecyclerView 마지막 item에
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: 구현 전 RED 실패.
- Result: RED 확인.
following creators list appends all button as last item가item_home_following_creator_all.xml누락으로 실패했다.
- Run:
- 수정:
-
Task 8.2: 팔로잉 크리에이터 전체 버튼 구현
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.ktapp/src/main/res/layout/item_home_following_creator_all.xml
- 작업:
HomeFollowingCreatorAdapter에 creator/all view type을 추가한다.submitItems()에 1개 이상 creator가 들어오면 adapter 마지막 item으로전체버튼을 표시한다.전체버튼은width=wrap_content, creator item과 동일한 높이,paddingHorizontal=16dp,textColor=@color/soda_400를 XML에 명시한다.전체버튼 클릭 시ensureMainV2NavigationAllowed안에서FollowingCreatorActivity를 시작한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: PASS.
- Result: PASS. adapter creator/all view type, 마지막
전체item,FollowingCreatorActivity이동 연결,전체layout token이 source test로 검증됐다.
- Run:
- 수정:
-
Task 8.3: 후속 변경 통합 검증
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 팔로잉 관련 local unit/source test가 모두 PASS.
- Run:
./gradlew :app:mergeDebugResources - Expected: layout/resource merge PASS.
- Run:
./gradlew :app:compileDebugKotlin - Expected: Kotlin compile PASS.
- Run:
./gradlew :app:ktlintCheck - Expected: ktlint PASS 또는 기존 unrelated failure만 발생.
- Run:
git diff --check - Expected: whitespace error 없음.
- Run:
- 검증 기록:
- 2026-06-30 팔로잉 크리에이터
전체버튼 후속 검증:./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"PASS. - 2026-06-30 팔로잉 크리에이터
전체버튼 후속 검증:./gradlew :app:mergeDebugResources는 최초 sandbox 실행에서 Gradle wrapper lock 권한 오류로 실패했고, 승인 실행 재시도에서 PASS. - 2026-06-30 팔로잉 크리에이터
전체버튼 후속 검증:./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-30 팔로잉 크리에이터
전체버튼 높이 보정 후 재검증: creator item 전체 높이에 맞추기 위해 invisible nickname spacer를 추가했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --checkPASS.mergeDebugResources는 최초 sandbox lock 권한 오류 후 승인 실행으로 PASS했고,ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
- 2026-06-30 팔로잉 크리에이터
- 검증:
Task 8.4: 팔로잉 크리에이터 전체 item 테스트 정책 정합성 보완
Goal 실행 P8-R1: 확정 review 항목 REV-P8-001에 따라 adapter의 마지막 전체 item과 이동 로직 검증은 유지하고, 금지된 width·height·padding·visibility source assertion만 제거한다.
- 시작 조건:
reviews/phase8-following-creators-all-review.md의REV-P8-001확정. - 완료 증거: UI 표현 속성 assertion 제거 및 남은 테스트명 한글화 → adapter view type/개수/route 검증 유지 → focused test·resource merge·Kotlin compile·ktlint PASS.
- 범위 밖:
item_home_following_creator_all.xml디자인 값 변경, adapter 동작 변경, 다른 기존 영문 테스트명 일괄 변경. - TDD 예외 사유: production 동작 결함이 아니라 테스트 정책 정합성 수정이므로 production RED를 만들지 않는다.
- 대체 검증 방법: XML 토큰은 review 시 정적 대조하고 실제 높이·padding·색상은 resource merge와 Task 5.3 수동 화면 확인으로 검증한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
following creators list appends all button as last item에서 layout width·height·padding·visibility·색상 문자열 assertion만 제거한다. -
adapter의 creator/all view type, item count, 마지막 item,
FollowingCreatorActivityroute assertion은 유지한다. -
수정하는 테스트명을 검증 의도가 드러나는 한글 문장으로 변경한다.
-
focused test, resource merge, Kotlin compile, ktlint를 실행하고 대체 검증 결과를 누적한다.
검증 기록:
- 2026-07-30:
following creators list appends all button as last item테스트명을팔로잉 크리에이터 목록은 전체 item을 마지막에 추가하고 이동을 연결한다로 한글화하고, width/height/padding/visibility/color source assertion만 제거했다. adapter view type, item count, 마지막 all item,FollowingCreatorActivityroute, all label string 검증은 유지했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint가 PASS했다.
Phase 9: 최근 소식 Response nested payload 계약 반영
-
Task 9.1: 최근 소식 새 응답 계약 RED 테스트 추가
- 수정:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingMapperTest.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt
- 작업:
FollowingNewsResponsefixture를 새 nested payload 구조로 교체한다.CREATOR_RANKING은creatorRanking.rank,creatorRanking.creatorId,creatorRanking.nickname,creatorRanking.profileImageUrl로 ranking UI item을 만드는지 검증한다.CONTENT_RANKING은contentRanking.rank,contentRanking.contentId,contentRanking.contentImageUrl,contentRanking.title로 ranking UI item을 만드는지 검증한다.AUDIO_CONTENT는audioContent,PHOTO_CONTENT는photoContentpayload로 content UI item을 만드는지 검증한다.COMMUNITY_POST는communityPost.postId,creatorProfileImage,creatorNickname,imageUrl,content,createdAt,likeCount,commentCount를 UI item에 반영하는지 검증한다.type에 대응하는 payload가 null인 최근 소식은recentNewssection에서 제외되는지 검증한다.visibleFromAtUtc는 기존처럼UtcRelativeTimeTextFormatter에 전달되는지 검증한다.- source test로
HomeFollowingModels.kt에 기존 평면 필드(creatorProfileImageUrl,creatorNickname,title,body,thumbnailImageUrl,targetId,occurredAtUtc,rank)가FollowingNewsResponse직접 필드로 남지 않는지 확인한다.
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: DTO/UI model/mapper 변경 전 RED 실패.
- Result: RED 확인.
FollowingCommunityPostNewsResponse,FollowingContentNewsResponse,FollowingContentRankingNewsResponse,FollowingCreatorRankingNewsResponse미정의와FollowingNewsResponsenested parameter 미지원, 신규 UI item 필드 부재로compileDebugUnitTestKotlin이 실패했다.
- Run:
- 수정:
-
Task 9.2: DTO와 UI model을 nested payload 기준으로 갱신
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeFollowingModels.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingUiModels.ktapp/src/main/res/values/strings.xmlapp/src/main/res/values-en/strings.xmlapp/src/main/res/values-ja/strings.xml
- 작업:
FollowingNewsResponse직접 필드는newsId,type,visibleFromAtUtc,creatorRanking,audioContent,photoContent,contentRanking,communityPost만 유지한다.FollowingCreatorRankingNewsResponse,FollowingContentNewsResponse,FollowingContentRankingNewsResponse,FollowingCommunityPostNewsResponseDTO를 추가하고 모두@Keep,@SerializedName을 적용한다.HomeFollowingNewsUiItem은 새 payload 차이를 표현할 수 있도록 ranking/content/community variant를 분리하거나 기존 variant를 최소 확장한다.- ranking UI item은
rank, target id, 표시 이미지 URL, 표시 제목/이름,visibleFromAtUtc,visibleFromText를 가진다. - content UI item은
contentId,contentImageUrl,title,creatorProfileImageUrl,creatorNickname, label resource id,visibleFromAtUtc,visibleFromText를 가진다. - community UI item은
postId,creatorProfileImageUrl,creatorNickname,imageUrl,content,createdAt,likeCount,commentCount,visibleFromAtUtc,visibleFromText를 가진다. CONTENT_RANKING문장형 message가 필요하면screen_home_following_content_ranking_news_message를 3개 locale string resource에 추가한다.
- 검증:
- Run:
./gradlew :app:mergeDebugResources - Expected: string resource가 중복 없이 merge된다.
- Run:
./gradlew :app:compileDebugKotlin - Expected: DTO/UI model 변경 후 컴파일 오류가 mapper/adapter 미반영 지점으로만 제한된다.
- Result: PASS.
FollowingNewsResponse직접 필드를 nested payload 계약으로 교체하고, ranking/content/community UI model variant 및 3개 locale content ranking message string을 추가한 뒤 최종mergeDebugResources,compileDebugKotlin이 통과했다.
- Run:
- 수정:
-
Task 9.3: mapper와 최근 소식 adapter 바인딩 갱신
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/model/HomeFollowingMappers.ktapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.ktapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt
- 작업:
- mapper는
type별 matching payload만 읽고, payload가 null이면null을 반환해 해당 item을 제외한다. CREATOR_RANKINGadapter binding은 기존screen_home_following_creator_ranking_news_message와FeedRankHighlight정책을 유지하되creatorRanking.nickname,creatorRanking.rank,creatorRanking.profileImageUrl을 사용한다.CONTENT_RANKINGadapter binding은 content title, rank, content image로FeedRankView를 구성하고 순위 텍스트만 highlight한다.AUDIO_CONTENT,PHOTO_CONTENTadapter binding은FollowingContentNewsResponsepayload의 content/creator 필드를FeedContentView에 전달한다.COMMUNITY_POSTadapter binding은FeedCommunityView에postId, creator profile/nickname, content, image,likeCount,commentCount를 전달한다.- 최근 소식 item click target id는
creatorId,contentId,postId중 payload에 맞는 값을 사용한다. visibleFromAtUtc기준 상대 시간 표시 정책은 유지한다.- 코드 리뷰에서 확인한
contentImageUrlnullable 계약을 DTO/UI model에 반영하고, Feed 위젯에는 빈 문자열 fallback으로 전달한다.
- mapper는
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected: PASS.
- Result: PASS. 최초 병렬 Gradle 실행 중 Kotlin incremental cache 충돌과 source-level test 기대 문자열 불일치 2건을 확인했다. Gradle을
--no-daemon순차 실행으로 전환하고 source test 기대 문자열을 새HomeFollowingNewsUiItem.Community분기 구조에 맞춘 뒤 focused test가 PASS했다. - 2026-06-30 코드 리뷰 후 보완 검증:
contentImageUrl = null인CONTENT_RANKING,AUDIO_CONTENT최근 소식이 유지되는 mapper test를 추가했다. RED: DTOcontentImageUrl이 non-nullString이라compileDebugUnitTestKotlintype mismatch 실패. GREEN: DTO/UI model을String?로 변경하고 adapter에서.orEmpty()fallback을 적용한 뒤./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest"PASS.
- Run:
- 수정:
-
Task 9.4: 최근 소식 Response 변경 통합 검증
- 검증:
- Run:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 팔로잉 관련 local unit/source test가 모두 PASS.
- Run:
./gradlew :app:mergeDebugResources - Expected: layout/resource merge PASS.
- Run:
./gradlew :app:compileDebugKotlin - Expected: Kotlin compile PASS.
- Run:
./gradlew :app:ktlintCheck - Expected: ktlint PASS 또는 기존 unrelated failure만 발생.
- Run:
git diff --check - Expected: whitespace error 없음.
- Run:
- 검증 기록:
- 2026-06-30 Phase 9 focused 검증:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest"PASS. - 2026-06-30 Phase 9 통합 검증:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --check모두 PASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-30 Phase 9 검증 참고: 최초 병렬 Gradle 검증은 Kotlin incremental cache
Storage ... is already registered충돌과 timeout으로 중단되어, 이후 모든 Gradle 검증은--no-daemon순차 실행으로 재검증했다. - 2026-06-30 Phase 9 코드 리뷰 후 재검증:
contentImageUrlnullable 계약을 보완한 뒤./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
- 2026-06-30 Phase 9 focused 검증:
- 검증:
Task 9.5: nullable 최근 소식 이미지의 이전 Coil 요청 해제
Goal 실행 P9-R1: 확정 review 항목 REV-P9-001에 따라 nullable/blank 최근 소식 이미지를 바인딩할 때 재사용된 ImageView의 이전 Coil 요청을 해제해 다른 news item 이미지가 노출되지 않도록 한다.
- 시작 조건:
reviews/phase9-news-nested-payload-review.md의REV-P9-001확정과contentImageUrl,imageUrlnullable 계약 확인. - 완료 증거: 최근 소식 ViewHolder 재사용 시 이전 요청이 남는 RED → 공통 blank image 분기 요청 해제 GREEN → adapter focused test와 Phase 9 회귀 PASS.
- 범위 밖: nullable image의 placeholder/숨김 디자인 변경, Feed 위젯 레이아웃 변경, DTO·mapper·routing 변경.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingNewsAdapterTest.kt -
RED: 완료된 Coil 요청이 연결된 최근 소식 image view를 nullable image item에 재사용한 뒤 요청이 남는 현재 동작을 Robolectric adapter binding test로 재현한다.
-
GREEN:
HomeFollowingNewsAdapter.bindImage()의 blank 분기에서coil.dispose()로 이전 요청을 해제한 뒤 drawable을 비우는 최소 수정만 적용한다. -
GREEN 확인:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest"를 실행한다. -
회귀 검증: mapper와 팔로잉 전체 회귀,
:app:mergeDebugResources,:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행하고 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-30 RED:
HomeFollowingNewsAdapterTest에 nullable content image ViewHolder 재사용 테스트를 추가했고, 구현 전assertTrue(disposable.isDisposed)실패로 이전 Coil 요청이 남는 동작을 확인했다. - 2026-07-30 GREEN:
HomeFollowingNewsAdapter.bindImage()blank 분기에서imageView.dispose()후 drawable을 비우도록 최소 수정했다. focused test, 팔로잉 전체 회귀와 신규 프로필 테스트,:app:mergeDebugResources,:app:compileDebugKotlin,:app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
Task 9.6: 최근 소식 Feed model의 미제공 creator ID 합성 제거
Goal 실행 P9-R2: 확정 review 항목 REV-P9-002에 따라 API payload에 없는 creatorId를 contentId 또는 postId로 대신 채우지 않고 미제공 값으로 유지한다.
- 시작 조건:
reviews/phase9-news-nested-payload-review.md의REV-P9-002확정과FollowingContentNewsResponse,FollowingCommunityPostNewsResponse에creatorId가 없음을 확인. - 완료 증거: 잘못된 ID 대입을 고정한 RED → 두
FeedItem의creatorId를 빈 값으로 전달하는 GREEN → 최근 소식 adapter focused test·팔로잉 전체 회귀·Kotlin compile·ktlint PASS. - 범위 밖: 서버 DTO에
creatorId추정 추가, API 스키마 변경, 최근 소식 클릭 routing·Feed 공통 model 구조 변경.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingNewsAdapter.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
RED:
Content와Communitybinding이 API에 없는creatorId를 각각contentId·postId로 합성하지 않도록 요구하는 한글명 회귀 테스트를 추가하고 현재 실패를 확인한다. -
GREEN: 두
FeedItem의creatorId에 빈 문자열을 전달하고 원본contentId·postId, creator 이름·이미지, 기존 click callback은 유지한다. -
GREEN 확인:
HomeFollowingFragmentSourceTest와HomeFollowingNewsAdapterTest를 실행한다. -
회귀 검증: 팔로잉 전체 회귀,
:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행하고 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-31 RED:
HomeFollowingFragmentSourceTest에팔로잉 최근 소식 feed model은 미제공 creator id를 합성하지 않는다를 추가했고, 구현 전creatorId = community.targetId.toString()/creatorId = content.targetId.toString()때문에 focused test가 17개 중 1개 실패했다. - 2026-07-31 GREEN:
HomeFollowingNewsAdapter의FeedItem.Community와FeedItem.Content에서creatorId = ""를 전달하도록 변경했다.postId = community.postId.toString(),contentId = content.contentId.toString(), creator 이름·이미지와 원본 item click callback은 유지했다.rg로 잘못된 targetId 대입 0건과 빈 creatorId 2건, content/post ID 보존을 확인했다. focused test, 팔로잉 전체 회귀,:app:compileDebugKotlin,:app:ktlintCheckPASS../gradlew --no-daemon :app:installDebug와 launcher monkey 실행도 PASS했으나, 화면 캡처가 검은 화면이라 실제 팔로잉 탭 터치 대조는 Task 5.3에 미완료로 유지한다.
Task 9.7: 미사용 FeedAdapter 제거와 현재 문서 정리
Goal 실행 P9-R3: 현재 production/test 호출자가 없는 FeedAdapter와 FeedImageViews를 제거하고, 팔로잉 문서의 재사용 후보 설명을 실제 사용 중인 Feed view/model 기준으로 정리한다.
- 시작 조건:
FeedAdapter/FeedImageViewsproduction/test 호출자 0건 확인. - 완료 증거:
FeedAdapter.kt삭제 → 현재 팔로잉 PRD/계획의FeedAdapter참조 제거 → Kotlin compile·Feed/팔로잉 회귀·diff 검증 PASS. - 범위 밖: 과거 완료 문서의 생성 이력 수정,
FeedRankView/FeedContentView/FeedCommunityView/FeedItem구조 변경, 신규 공용 adapter 재작성. - TDD 예외 사유: 실행 동작 추가가 아니라 호출자 0건인 미사용 Kotlin 파일 삭제와 문서 정리이므로 신규 RED 테스트를 만들지 않는다.
- 대체 검증 방법:
codegraph_callers와rg로 호출자/참조 0건을 확인하고 Kotlin compile, 관련 unit/source test,git diff --check를 실행한다.
Files:
-
Delete:
app/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedAdapter.kt -
Modify:
docs/20260625_메인_홈_팔로잉_탭/plan-task.md -
Modify:
docs/20260625_메인_홈_팔로잉_탭/prd.md -
codegraph_callers와rg -n "FeedAdapter|FeedImageViews" app/src/main/java app/src/test/java docs/20260625_메인_홈_팔로잉_탭 docs/agent-guides로 production/test 호출자 0건과 현재 문서 참조만 남았는지 확인한다. -
FeedAdapter.kt를 삭제한다. -
현재 팔로잉 PRD/계획 문서에서
FeedAdapter재사용 후보 문구를 제거하고 실제 재사용 중인FeedItem,FeedRankView,FeedContentView,FeedCommunityView기준으로 정리한다. -
./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:ktlintCheck,git diff --check를 실행하고 결과를 누적한다.
검증 기록:
- 2026-07-31:
codegraph_callers결과FeedAdapter호출자 0건을 확인했고,rg -n "FeedAdapter|FeedImageViews" app/src/main/java app/src/test/java docs/20260625_메인_홈_팔로잉_탭 docs/agent-guides결과 production/test 참조 없이 Task 9.7 문서 참조만 남는 것을 확인했다.app/src/main/java/kr/co/vividnext/sodalive/v2/widget/feed/FeedAdapter.kt를 삭제하고 현재 팔로잉 PRD/계획 문서의 재사용 후보를FeedItem,FeedRankView,FeedContentView,FeedCommunityView기준으로 정리했다../gradlew --no-daemon :app:compileDebugKotlin :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" :app:ktlintCheck,git diff --checkPASS.
Phase 10: On Air 라이브 item Figma 재구현
- Task 10.1: Figma 기준 레이아웃 재구현
- 수정:
app/src/main/res/layout/item_home_following_live.xml
- 생성:
app/src/main/res/drawable/bg_home_following_live_capsule.xml
- 작업:
- Figma
24:5696기준으로item_home_following_live.xml을 썸네일 카드가 아닌 캡슐형 On Air item으로 재구현한다. - 기존
HomeFollowingLiveAdapter가 사용하는 표시 id(iv_home_following_live_creator_profile,tv_home_following_live_title,tv_home_following_live_creator_nickname,tv_home_following_live_started_at)는 유지한다. - 카드 배경은
gray_900, stroke는color_3bb9f1, radius는90dp, 전체 크기는 Figma의263dp x 100dp기준으로 맞춘다. - LIVE badge, 시작 시간, 제목, 크리에이터명을 Figma 순서와 간격에 맞게 배치한다.
- Figma
- 검증:
- Run:
./gradlew --no-daemon :app:mergeDebugResources - Expected: layout/drawable resource merge PASS.
- Run:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 기존 팔로잉 source/unit test PASS.
- Run:
- 검증 기록:
- 2026-07-03 Figma
24:5696기준으로item_home_following_live.xml을 기존 썸네일 카드에서263dp x 100dp캡슐형 On Air item으로 재구현했다. 기존 adapter id 계약은 유지했고, profile image는 기존loadHomeCreatorProfileImage()의CircleCropTransformation경로를 그대로 사용한다. - 2026-07-03 검증:
./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",git diff --checkPASS. Gradle 실행 중 기존 deprecation warning만 출력됐다. - 2026-07-03 후속 정리: Figma 캡슐형 item에 필요 없는
iv_home_following_live_thumbnail숨김 View와HomeFollowingLiveAdapter의 obsolete thumbnail binding을 제거했다.
- 2026-07-03 Figma
- 수정:
Task 10.2: On Air 가로 item 간격 복구
Goal 실행 P10-R1: 확정 review 항목 REV-P10-001에 따라 연속된 On Air 캡슐 item 사이에 기존 홈 가로 리스트와 동일한 간격을 적용한다.
- 시작 조건:
reviews/phase10-on-air-live-item-review.md의REV-P10-001확정. - 완료 증거: item layout parameter에 end margin이 없는 RED → 기존
recyclerItemLayoutParams(parent)재사용 GREEN → resource/source/팔로잉 회귀 PASS. - 범위 밖: 캡슐 크기·색상·내부 spacing 변경, RecyclerView padding 변경, 신규 ItemDecoration 추상화.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingLiveAdapter.kt -
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
RED:
HomeFollowingLiveAdapter.onCreateViewHolder()가 item end margin을 적용하지 않는 현재 상태를 실패 테스트로 고정한다. -
GREEN: creator/chat adapter와 같은
recyclerItemLayoutParams(parent)를 재사용해 XML 크기를 유지하면서spacing_12end margin을 적용한다. -
GREEN 확인:
HomeFollowingFragmentSourceTest와 팔로잉 전체 회귀 테스트를 실행한다. -
회귀 검증: resource merge, Kotlin compile, ktlint,
git diff --check를 실행하고 결과를 누적한다.
검증 기록:
- 2026-07-30 RED:
HomeFollowingFragmentSourceTest.following live adapter keeps horizontal item spacing을 추가해 live adapter의recyclerItemLayoutParams(parent)재사용을 요구했고, 구현 전 helper 미사용으로 focused test가 실패했다. - 2026-07-30 GREEN:
HomeFollowingLiveAdapter.onCreateViewHolder()에서 inflate한 view에recyclerItemLayoutParams(parent)를 적용해 기존 XML 크기와spacing_12end margin을 유지했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint,git diff --checkPASS.
Task 10.3: On Air 간격 검증의 테스트 정책 정합성 보완
Goal 실행 P10-R2: 확정 review 항목 REV-P10-002에 따라 UI margin을 source 문자열로 고정한 신규 테스트를 제거하고 가이드가 허용하는 대체 검증 기록으로 전환한다.
- 시작 조건:
reviews/phase10-on-air-live-item-review.md의REV-P10-002확정과 Task 10.2 production 수정 완료. - 완료 증거: 금지된 UI 표현 속성 source test만 제거 → adapter helper 사용 정적 대조 → resource merge·Kotlin compile·팔로잉 회귀 PASS.
- 범위 밖:
HomeFollowingLiveAdapter의recyclerItemLayoutParams(parent)적용 제거, item 크기·간격 변경, 기존 source test 일괄 정리. - TDD 예외 사유:
docs/agent-guides/code-style.md가 View margin 같은 UI 표현 속성 테스트를 금지하므로 실행 명령과 정적 대조를 대체 검증으로 사용한다. - 대체 검증 방법: adapter의 기존 helper 재사용을
rg로 확인하고 resource merge, Kotlin compile, 기존 팔로잉 로직 회귀를 실행한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
신규
following live adapter keeps horizontal item spacingsource test만 제거하고 Task 10.2 production 코드는 유지한다. -
rg -n "recyclerItemLayoutParams\(parent\)" app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingLiveAdapter.kt로 기존 helper 재사용을 확인한다. -
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",:app:mergeDebugResources,:app:compileDebugKotlin을 실행한다. -
./gradlew --no-daemon :app:ktlintCheck와git diff --check를 실행하고 결과를 이 Task 아래에 누적한다.
검증 기록:
- 2026-07-30: UI margin을 source 문자열로 고정하던
following live adapter keeps horizontal item spacing테스트만 제거하고HomeFollowingLiveAdapter의recyclerItemLayoutParams(parent)적용은 유지했다.rg -n "recyclerItemLayoutParams\(parent\)" app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingLiveAdapter.kt로 helper 재사용을 확인했다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.
Task 10.4: On Air 고정 폭 LayoutParams 보존
Goal 실행 P10-R3: 확정 review 항목 REV-P10-003에 따라 On Air item의 XML 263dp 폭을 런타임에서도 유지하면서 spacing_12 end margin을 적용한다.
- 시작 조건:
reviews/phase10-on-air-live-item-review.md의REV-P10-003확정. - 완료 증거:
RecyclerView.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)교체 경로 제거 → inflate된 width/height를 유지한 채 end margin만 적용 → resource merge·Kotlin compile·팔로잉 회귀 PASS → 연결 기기 준비 시 Task 5.3 수동 확인. - 범위 밖: 263dp × 100dp 디자인 변경, 공통 helper 전체 리팩터링, On Air 내부 필드/라우팅 변경.
- TDD 예외 사유:
docs/agent-guides/code-style.md가 View width·margin 테스트 추가를 금지하므로 새 자동 UI 크기 테스트를 작성하지 않는다. - 대체 검증 방법: inflate 후 기존
layoutParams보존 여부를 코드로 대조하고 resource merge·compile·기존 팔로잉 회귀 및 가능한 경우 실기기 수동 확인을 수행한다.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingLiveAdapter.kt -
Verify:
app/src/main/res/layout/item_home_following_live.xml -
HomeFollowingLiveAdapter.onCreateViewHolder()가 inflate된 root의 기존 263dp × 100dp layout parameter를 보존하고 end margin만 추가하도록 최소 수정한다. -
HomeFollowingFragmentSourceTest에 width·margin source assertion을 다시 추가하지 않는다. -
팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint를 실행한다.
-
연결 기기가 있으면 연속 On Air item의 폭과 간격을 수동 확인하고, 없으면 Task 5.3과 함께 사유를 기록한다.
검증 기록:
- 2026-07-30:
HomeFollowingLiveAdapter.onCreateViewHolder()에서recyclerItemLayoutParams(parent)사용을 제거하고 inflate된RecyclerView.LayoutParams의 263dp × 100dp 계약을 유지한 채spacing_12end margin만 적용했다. width·margin source assertion은 다시 추가하지 않았다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint가 PASS했다.adb devices에 연결 기기가 없어 On Air 폭/간격 실기기 확인은 Task 5.3 보류 사유와 함께 유지한다.
Phase 11: 최근 소식 COMMUNITY_POST 상세 이동
-
Task 11.1: 문서와 RED 테스트로 커뮤니티 상세 이동 계약 고정
- 수정:
docs/20260625_메인_홈_팔로잉_탭/prd.mddocs/20260625_메인_홈_팔로잉_탭/plan-task.mdapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLoginGuardSourceTest.kt
- 작업:
- 최근 소식
COMMUNITY_POSTitem 터치 시CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId)를 사용한다는 계약을 문서화한다. HomeMainFragment.onFollowingNewsClick()이HomeFollowingNewsUiItem.Community만 처리하고,postId <= 0L은 가드보다 먼저 무시하는지 source test로 고정한다.- legacy
CreatorCommunityAllActivity또는Constants.EXTRA_COMMUNITY_POST_ID직접 extra 조립을 사용하지 않는지 검증한다.
- 최근 소식
- 검증:
- Run:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest" - Expected RED: 구현 전
onFollowingNewsClick()no-op 때문에 새 source test가 실패한다.
- Run:
- 수정:
-
Task 11.2: COMMUNITY_POST 상세 이동 구현
- 수정:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
- 작업:
onFollowingNewsClick()에서HomeFollowingNewsUiItem.Community가 아니면 즉시 return한다.community.postId가 0 이하이면 즉시 return한다.- 유효한
postId는ensureMainV2NavigationAllowed안에서CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId)로 시작한다.
- 검증:
- Run:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest" - Expected GREEN: source test PASS.
- Run:
- 수정:
-
Task 11.3: 최근 소식 이동 회귀 검증
- 검증:
- Run:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 팔로잉 관련 local unit/source test PASS.
- Run:
./gradlew --no-daemon :app:compileDebugKotlin - Expected: Kotlin compile PASS.
- Run:
git diff --check - Expected: whitespace error 없음.
- Run:
- 검증:
Phase 12: 전체 empty 문구 중앙 표시
-
Task 12.1: 문서와 source test로 empty 문구 계약 고정
- 수정:
docs/20260625_메인_홈_팔로잉_탭/prd.mddocs/20260625_메인_홈_팔로잉_탭/plan-task.mdapp/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt
- 작업:
- 기존
screen_home_following_emptystring resource를 재사용한다는 계약을 문서화한다. fragment_v2_main_home.xml에tv_home_following_empty가 있고@string/screen_home_following_empty를 사용하는지 source test로 고정한다.- empty
TextView가 팔로잉 탭 전체 영역에서 가운데 배치되고 텍스트도 가운데 정렬되는지 source test로 고정한다. HomeFollowingUiState.Empty는 empty 문구를 표시하고,Content,LoginRequired,Error는 숨김 경로를 갖는지 source test로 고정한다.
- 기존
- 검증:
- Run:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected RED: 구현 전
tv_home_following_empty와 empty visibility 분기 부재로 실패한다.
- Run:
- 검증 기록:
- 2026-07-13: 기존
screen_home_following_emptystring resource를 재사용해 전체 empty 문구를 표시하는 요구사항을 PRD와 계획 문서에 추가했다.HomeFollowingFragmentSourceTest에tv_home_following_emptyid, string 재사용, 중앙 정렬 속성,HomeFollowingUiState.Empty전용 표시 분기를 고정하는 source test를 추가했다.
- 2026-07-13: 기존
- 수정:
-
Task 12.2: 다국어 string과 empty UI 구현
- 수정:
app/src/main/res/values/strings.xmlapp/src/main/res/values-en/strings.xmlapp/src/main/res/values-ja/strings.xmlapp/src/main/res/layout/fragment_v2_main_home.xmlapp/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt
- 작업:
- 기존
screen_home_following_empty값을 한국어/영어/일본어 문구로 갱신한다. - 팔로잉 탭 content 영역에
tv_home_following_empty를 추가하고 중앙 배치/중앙 정렬한다. HomeFollowingUiState.Empty에서 empty 문구를 표시하고 섹션 adapter는 비운다.HomeFollowingUiState.Content,LoginRequired,Error에서는 empty 문구를 숨긴다.
- 기존
- 검증:
- Run:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" - Expected GREEN: source test PASS.
- Run:
- 검증 기록:
- 2026-07-13:
values,values-en,values-ja의 기존screen_home_following_empty값을 한국어/영어/일본어 2줄 문구로 갱신했다.fragment_v2_main_home.xml에tv_home_following_empty를 추가하고@string/screen_home_following_empty,match_parent,gravity=center,textAlignment=center, 기본gone을 적용했다.HomeMainFragment에서는HomeFollowingUiState.Empty만 empty 문구를 표시하고,Content,LoginRequired,Error는 숨기도록 분기했다.
- 2026-07-13:
- 수정:
-
Task 12.3: empty 문구 회귀 검증 기록
- 검증:
- Run:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" - Expected: 팔로잉 관련 local unit/source test PASS.
- Run:
./gradlew --no-daemon :app:mergeDebugResources - Expected: string/layout resource merge PASS.
- Run:
./gradlew --no-daemon :app:compileDebugKotlin - Expected: Kotlin compile PASS.
- Run:
git diff --check - Expected: whitespace error 없음.
- Run:
- 검증 기록:
- 2026-07-13:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,git diff --check모두 PASS. Gradle 실행 중 기존 deprecation warning만 출력됐다.
- 2026-07-13:
- 검증:
Task 12.4: empty 상태 UI 표현 속성 source test 정책 정합성 보완
Goal 실행 P12-R1: 확정 review 항목 REV-P12-001에 따라 empty 상태의 mapper/문구/분기 검증은 유지하고, 금지된 layout 크기·정렬·visibility 문자열 assertion을 제거한다.
- 시작 조건:
reviews/phase12-empty-state-review.md의REV-P12-001확정. - 완료 증거: UI 표현 속성 assertion 제거 및 남은 테스트명 한글화 → mapper Empty 조건과 locale 문구/상태 분기 검증 유지 → focused test·resource merge·Kotlin compile·ktlint PASS.
- 범위 밖: empty 문구/중앙 배치 production 변경, 로그인 유도 UI, 다른 기존 source test 일괄 정리.
- TDD 예외 사유: production 동작이 아니라 테스트 정책 정합성을 수정하므로 production RED를 만들지 않는다.
- 대체 검증 방법: 중앙 배치는
fragment_v2_main_home.xml정적 대조와 Task 5.3 실기기 확인으로 검증하고, Empty 판정은HomeFollowingMapperTest로 유지한다.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt -
empty 테스트에서 width·height·gravity·textAlignment·visibility와 직접
View.VISIBLE/GONE문자열 assertion을 제거한다. -
3개 locale 문구 계약,
HomeFollowingUiState.Empty분기, 기존 mapper Empty 테스트는 유지한다. -
수정하는 테스트명을 검증 의도가 드러나는 한글 문장으로 변경한다.
-
focused test, resource merge, Kotlin compile, ktlint를 실행하고 Task 5.3 수동 확인 가능 여부를 기록한다.
검증 기록:
- 2026-07-30: empty source test명을
팔로잉 empty 상태는 다국어 빈 문구와 상태 분기를 유지한다로 한글화하고, width/height/gravity/textAlignment/visibility 및 직접View.VISIBLE/GONE문자열 assertion을 제거했다. 3개 locale 문구, empty string 재사용,HomeFollowingUiState.Empty/Error 상태 분기 검증은 유지했다. focused test, 팔로잉 전체 회귀, resource merge, Kotlin compile, ktlint가 PASS했다.adb devices에 연결 기기가 없어 중앙 배치 실기기 확인은 Task 5.3 보류 사유와 함께 유지한다.
Phase 13: 최근 소식 CREATOR_RANKING·AUDIO_CONTENT 터치 이동
Phase 결과: 팔로잉 탭 최근 소식에서 크리에이터 순위 item은 해당 크리에이터 채널로, 오디오 콘텐츠 업로드 item은 해당 오디오 콘텐츠 상세로 이동한다.
선행조건: Phase 11의 기존 COMMUNITY_POST 상세 이동과 공통 Creator/Content Action 경로가 유지되어야 한다.
Phase 완료 조건: CREATOR_RANKING, AUDIO_CONTENT, 기존 COMMUNITY_POST 이동 source test와 팔로잉 회귀 테스트, Kotlin 컴파일이 통과한다.
Task 13.1 최근 소식 이동 RED 테스트 추가
Goal 실행 P13-T1: 현재 실행되지 않는 CREATOR_RANKING과 AUDIO_CONTENT 터치 이동을 실패 source test로 재현한다.
- 시작 조건: PRD의
2026-07-30 CREATOR_RANKING·AUDIO_CONTENT 상세 이동 Requirements확정. - 완료 증거: 구현 전 focused test가 새 이동 호출 부재로 실패한다.
- 범위 밖:
CONTENT_RANKING,PHOTO_CONTENT, On Air, 스케줄 터치 이동.
Files:
-
Modify:
app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragmentLoginGuardSourceTest.kt -
RED:
onFollowingNewsClick()이CREATOR_RANKING을CreatorActionCommand.Profile로,AUDIO_CONTENT를ContentActionCommand.AudioDetail로 전달하는지 검증하는 source test를 추가한다. -
RED 확인:
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest"를 실행해 두 공통 액션 호출 부재로 인한 assertion 실패를 확인한다. -
GREEN: Task 13.2의 최소 구현으로 RED를 통과시킨다.
-
GREEN 확인: 같은 focused test를 다시 실행해 성공을 확인한다.
-
REFACTOR: 새 abstraction 없이 기존 공통 액션을 재사용하고 focused test를 다시 실행한다.
검증 기록:
- 2026-07-30 RED: focused test를 실행해 11개 중
COMMUNITY_POST분기 구조,CREATOR_RANKING채널 이동,AUDIO_CONTENT상세 이동 3개가 assertion 실패하는 것을 확인했다. 현재 production이HomeFollowingNewsUiItem.Community이외의 item을 즉시 반환해 요청 동작이 없는 것이 실패 원인이다. - 2026-07-30 GREEN: 동일 focused test를 다시 실행해 11개 모두 PASS했다. 새 abstraction이나 직접
Intent조립 없이 기존 Creator/Content/Community Action 호출을 검증했다.
Task 13.2 CREATOR_RANKING·AUDIO_CONTENT 이동 구현
Goal 실행 P13-T2: 요청된 두 최근 소식 타입만 기존 공통 액션 경로로 이동시킨다.
- 시작 조건:
P13-T1RED 확인. - 완료 증거: focused test와 Kotlin 컴파일 통과.
- 범위 밖: API/DTO/mapper/UI 변경, 직접
Intent조립, 다른 최근 소식 타입의 신규 이동.
Files:
-
Modify:
app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt -
RED: Task 13.1의 실패 source test를 기준으로 한다.
-
RED 확인: Task 13.1 실행 결과를 확인한다.
-
GREEN:
onFollowingNewsClick()에서CREATOR_RANKING은CreatorActionCommand.Profile(item.targetId),AUDIO_CONTENT는ContentActionCommand.AudioDetail(item.contentId)를 호출하고 기존COMMUNITY_POST분기를 유지한다. -
GREEN 확인: focused test와
./gradlew --no-daemon :app:compileDebugKotlin을 실행해 성공을 확인한다. -
REFACTOR:
CONTENT_RANKING과PHOTO_CONTENT는 no-op으로 유지하고 이번 변경이 만든 중복만 점검한다.
검증 기록:
- 2026-07-30:
HomeMainFragment.onFollowingNewsClick()을 sealed UI item 분기로 변경했다.CREATOR_RANKING만CreatorActionCommand.Profile(item.targetId),AUDIO_CONTENT만ContentActionCommand.AudioDetail(item.contentId)로 전달하며 기존COMMUNITY_POST의postId검증과 상세 이동을 유지했다. focused test와:app:compileDebugKotlin이 PASS했다.
Task 13.3 최근 소식 터치 이동 회귀 검증
Goal 실행 P13-GATE: 요청된 이동과 기존 팔로잉 동작에 회귀가 없는지 판정한다.
-
시작 조건:
P13-T1,P13-T2완료. -
완료 증거: 아래 자동 검증 결과와 수동 검증 가능 여부를 기록한다.
-
범위 밖: 연결 기기 없는 환경에서 수동 검증을 성공으로 추정하는 행위.
-
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest"PASS. -
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*"PASS. -
./gradlew --no-daemon :app:compileDebugKotlinPASS. -
./gradlew --no-daemon :app:ktlintCheckPASS 또는 이번 변경과 무관한 기존 위반만 확인. -
git diff --checkPASS. -
연결 기기가 있으면
CREATOR_RANKING과AUDIO_CONTENTitem 터치 목적지를 수동 확인하고, 없으면 미실행 사유를 기록한다.
검증 기록:
- 2026-07-30: focused test, 팔로잉 전체 회귀 테스트, Kotlin 컴파일, ktlint,
git diff --check가 모두 PASS했다. ktlint에는 기존.editorconfig의disabled_rulesdeprecation 경고만 출력됐다.adb devices결과 연결된 기기가 없어 실제 item 터치 수동 검증은 실행하지 못했다.
Verification Log
- 2026-07-31 이번 Phase 1~13 리뷰 재검증: 현재 working tree의 PRD·계획·production/test 코드와 Phase별 리뷰 보고서 13개를 대조했다. 새 확정 발견 사항은 없고 기존 확정 항목은 모두 각 회귀 수정 Task에서 수정 완료 상태다. Phase 9 보고서 범위를 Task 9.7까지 확장해 production/test
FeedAdapter|FeedImageViews호출자 0건과 현재 Feed view/model 직접 재사용을 기록했다../gradlew --no-daemon :app:testDebugUnitTest ... :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS(BUILD SUCCESSFUL, 16 suites·120 tests, failures/errors/skipped 0, 46 actionable tasks),./gradlew --no-daemon tasks --all, staged/unstagedgit diff --checkPASS.adb devices에서 기기2cec640c34017ece연결은 확인했지만 테스트 계정·API 데이터 기반 팔로잉 화면 조작과 Figma 대조는 수행하지 않아REV-P5-001/ Task 5.3 보류를 유지한다. 이번 리뷰에서는 production/test/resource 코드를 수정하지 않았다. - 2026-07-31 Phase 1~13 최종 리뷰 검증: 현재 working tree의 PRD·계획·production/test 코드와 Phase별 리뷰 보고서 13개를 다시 대조했다. 신규 확정 항목은
REV-P4-004(공용 source test의 영문 문장형 테스트명 11개)와REV-P9-002(API가 제공하지 않는 creator ID 자리에 content/post ID를 합성)이며, 코드 수정 전에 Phase 4 Task 4.9 /P4-R4, Phase 9 Task 9.6 /P9-R2로 전환했다. 이번 리뷰에서는 production/test/resource 코드를 수정하지 않았다../gradlew --no-daemon :app:testDebugUnitTest ... :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS(BUILD SUCCESSFUL, 20 suites·306 tests, failures/errors/skipped 0, 46 actionable tasks),./gradlew --no-daemon tasks --all, staged/unstagedgit diff --check도 PASS했다.adb devices는 정상 실행됐으나 연결 기기가 없어REV-P5-001/ Task 5.3 실기기 수동 확인 보류를 유지한다. - 2026-07-31 리뷰 보완 Task 2.8, 6.8 완료 검증:
REV-P2-002에 따라 미사용HomeFollowingNewsUiItem.Content.labelResId와 전용FollowingNewsType.toLabelResId()를 제거하고, 실제 표시 경로인FeedContentCategory.Photolabel 회귀를HomeFollowingNewsAdapterTest에 유지했다.REV-P6-004에 따라 creator·최근 대화 source test의 UI 표현 속성 문자열 assertion만 제거하고 구조·필수 field·Direct badge·상대 시간 formatter·click 계약 검증은 유지했다. focused test 3개, 팔로잉 전체 회귀,./gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.adb devices에는 연결 기기가 없어 Task 5.3 실기기 수동 확인 보류를 유지한다. - 2026-07-31 Phase 1~13 리뷰 재점검: 현재 working tree의 PRD·계획·production/test 코드와 Phase별 리뷰 보고서 13개를 다시 대조했다. 신규 확정 항목은
REV-P2-002(최근 소식Content.labelResId와 전용 mapper가 production 표시에서 미사용)와REV-P6-004(creator·최근 대화 UI 표현 속성을 검증하는 source test가 현재 코드 스타일 정책과 불일치)이며, 구현 전에 Phase 2 Task 2.8 /P2-R2, Phase 6 Task 6.8 /P6-R4로 전환했다. 이번 리뷰에서는 production/test/resource 코드를 수정하지 않았다../gradlew --no-daemon :app:testDebugUnitTest --tests 'kr.co.vividnext.sodalive.v2.main.home.*Following*' --tests 'kr.co.vividnext.sodalive.v2.main.home.HomeCreatorProfileImageLoaderTest' --tests 'kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest' --tests 'kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest' --tests 'kr.co.vividnext.sodalive.v2.live.action.*' --tests 'kr.co.vividnext.sodalive.v2.content.action.*' --tests 'kr.co.vividnext.sodalive.v2.community.action.*' :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS(BUILD SUCCESSFUL, 15 suites·113 tests, failures/errors 0, 46 actionable tasks)../gradlew --no-daemon tasks --all, staged/unstagedgit diff --check도 PASS했다.adb devices에는 연결 기기가 없어 Phase 5 Task 5.3 실기기 수동 확인 보류를 유지한다. - 2026-07-31 리뷰 보완 Task 2.7 완료 검증:
REV-P2-001에 따라 미사용 팔로잉 string resourcescreen_home_following_creators_title,screen_home_following_on_air_title,screen_home_following_error를 3개 locale에서 제거했다. 선언 외 참조 0건을rg로 확인했고 사용 중인 팔로잉 문자열은 유지했다../gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlin,./gradlew --no-daemon --rerun-tasks :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingMapperTest",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS. 첫 팔로잉 전체 회귀는R.stringid 변경 증분 캐시로 mapper test 2건이 실패했으나--rerun-tasks재빌드 후 focused와 전체 회귀가 PASS했다.adb devices에 연결된 기기가 없어 Phase 5 Task 5.3 실기기 수동 확인은 계속 보류한다. - 2026-07-30 Phase 1~13 최종 리뷰 재점검: 현재 working tree의 PRD·계획·production/test 코드·Phase별 리뷰 보고서 13개를 다시 대조했다. 신규 확정 항목은
REV-P2-001(후속 UI·오류 처리 변경 후 3개 locale에 미사용 string resource 3개가 남음) 1건이며 Phase 2 Task 2.7 /P2-R1로 전환했다. 이번 리뷰에서 production/test/resource 코드는 수정하지 않았다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorProfileImageLoaderTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" --tests "kr.co.vividnext.sodalive.v2.live.action.*" --tests "kr.co.vividnext.sodalive.v2.content.action.*" --tests "kr.co.vividnext.sodalive.v2.creator.action.*" --tests "kr.co.vividnext.sodalive.v2.community.action.*" :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS(BUILD SUCCESSFUL, 119 tests, failures/errors 0, 46 actionable tasks),./gradlew --no-daemon tasks --all, staged/unstagedgit diff --checkPASS.adb devices는 정상 실행됐으나 연결 기기가 없어 Phase 5 Task 5.3 수동 검증 보류를 유지한다. - 2026-07-30 리뷰 보완 Task 4.8, 9.5 완료 검증: blank profile image와 nullable 최근 소식 image 바인딩 시 재사용된
ImageView의 이전 Coil 요청을dispose()로 해제하도록 보완했다. 각 focused test는 구현 전disposable.isDisposedassertion 실패로 RED를 확인했고, 최소 구현 후 GREEN으로 전환했다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeCreatorProfileImageLoaderTest",./gradlew --no-daemon :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-07-30 Phase 1~13 리뷰 최종 재검증: 현재 working tree의 PRD·계획·production/test 코드와 Phase별 리뷰 보고서 13개를 대조했다. 신규 확정 항목은
REV-P4-003(blank profile image binding의 이전 Coil 요청 해제 누락)과REV-P9-001(nullable 최근 소식 image binding의 이전 Coil 요청 해제 누락)이며, 구현 전에 Phase 4 Task 4.8 /P4-R3, Phase 9 Task 9.5 /P9-R1로 전환했다. 이미 완료된REV-P6-003/ Task 6.7은 Phase 6 보고서의 상태와 수정 검증 기록을 현재 코드에 맞게 정정했다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" --tests "kr.co.vividnext.sodalive.v2.live.action.*" --tests "kr.co.vividnext.sodalive.v2.content.action.*" --tests "kr.co.vividnext.sodalive.v2.community.action.*" :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS(BUILD SUCCESSFUL, 111 tests, failures/errors 0, 46 actionable tasks),./gradlew --no-daemon tasks --allPASS, staged/unstagedgit diff --checkPASS.adb devices는 정상 실행됐으나 연결 기기가 없어 Phase 5 Task 5.3 수동 검증 보류를 유지한다. 이번 리뷰에서는 production/test 코드를 수정하지 않았다. - 2026-07-30 리뷰 보완 Task 6.7, 7.7, 8.4, 10.4, 12.4 완료 검증: 최근 대화와 On Air adapter는 inflate된 root의 기존
RecyclerView.LayoutParamswidth/height를 보존하고spacing_12end margin만 적용하도록 수정했다. 금지된 UI 표현 속성 source assertion은 Feed content, 팔로잉 크리에이터 전체 item, empty 상태 테스트에서 제거하고, 동작/문구/route 계약 검증은 유지했다../gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest" :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다.adb devices에 연결 기기가 없어 Task 5.3 실기기 수동 확인 보류를 유지한다. - 2026-07-30 Phase 1~13 리뷰 최종 검증:
./gradlew --no-daemon :app:testDebugUnitTest --tests 'kr.co.vividnext.sodalive.v2.main.home.*Following*' --tests 'kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest' --tests 'kr.co.vividnext.sodalive.v2.main.home.FeedViewTest' --tests 'kr.co.vividnext.sodalive.v2.live.action.*' --tests 'kr.co.vividnext.sodalive.v2.content.action.*' --tests 'kr.co.vividnext.sodalive.v2.community.action.*' :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheckPASS(BUILD SUCCESSFUL, 46 actionable tasks),git diff --checkPASS.adb devices는 정상 실행됐으나 연결 기기가 없어 Phase 5 Task 5.3 수동 검증은 미실행 상태를 유지한다. 자동 검증 PASS는 신규 확정 항목REV-P6-003,REV-P7-003,REV-P8-001,REV-P10-003,REV-P12-001의 정적 리뷰 결과를 해소하지 않으며, 각 신규 Task에서 후속 조치한다. - 2026-07-30 Phase별 추가 재점검: 기존 Phase 1~13 리뷰 보고서, 현재 production/test 코드,
docs/agent-guides/code-style.md를 다시 대조했다. 신규 확정 항목은REV-P6-003(최근 대화284dp폭을 adapter가WRAP_CONTENT로 교체),REV-P7-003(content feed UI 크기·padding·margin source test 정책 위반),REV-P8-001(전체item UI 표현 속성 source assertion),REV-P10-003(On Air263dp폭을 간격 helper가WRAP_CONTENT로 교체),REV-P12-001(empty 크기·정렬·visibility source assertion)이다. 구현 전에 해당 Phase에 Task 6.7, 7.7, 8.4, 10.4, 12.4를 추가했으며, 이번 재점검에서는 production/test 코드를 수정하지 않았다. Phase 5 Task 5.3의 실기기 수동 확인은 기존 보류 상태를 유지한다. - 2026-07-30 리뷰 보완 Task 6.6, 7.6, 10.3 완료 검증: 상단 파일 구조의 obsolete 최근 소식 layout 항목을 Feed layout 재사용/삭제 이력 기준으로 정리하고,
HomeFollowingNewsAdapterTest신규 테스트명 2개를 한글화했으며,build-test-style.md에 클래스 단위 실행 예시를 추가하고, On Air 간격 source test 정책 위반 항목을 제거했다.rg대체 검증,./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest",./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. 리뷰어 재확인 결과 blocking finding 없음. - 2026-07-30 Phase별 리뷰 산출물 재점검: 기존 Phase 1~13 보고서와 현재 working tree를 다시 대조했다. 기존 통합 리뷰 기록의 “이번 리뷰에서는 production 코드를 수정하지 않았다”는 문구와 달리, 같은 리뷰 후속 Task 4.6·4.7·6.5·7.5·10.2에서 production 코드가 수정된 상태임을 정정한다. 이번 재점검 자체에서는 production 코드를 변경하지 않았으며,
REV-P6-002(삭제된 layout의 상단 파일 구조 잔존),REV-P7-002(신규 테스트명과 단일 실행 가이드 미준수),REV-P10-002(UI margin source test 정책 위반)를 추가 확정해 Task 6.6·7.6·10.3으로 전환했다.*Following*39개,HomeMainFragmentLoginGuardSourceTest13개, Feed·Live·Content·Community Action 회귀, resource merge, Kotlin compile, ktlint,./gradlew --no-daemon tasks --all, staged/unstaged diff whitespace 검증이 PASS했다.adb devices에는 연결 기기가 없어 Task 5.3 실기기 수동 확인 보류를 유지한다. - 2026-07-30 리뷰 보완 Task 3.4, 4.6, 4.7, 6.5, 7.3, 7.5, 10.2 완료 검증: RED 단계에서 focused source/unit test 실패를 확인한 뒤 최소 구현으로 GREEN 전환했다.
./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingViewModelTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest" --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingNewsAdapterTest", 팔로잉 전체 회귀 + FeedView +v2.live.action.*/v2.content.action.*/v2.community.action.*,./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS. 최종 리뷰 게이트에서 Critical/Important finding은 없었고, ranking highlight 중복 문자열 Minor를 추가 RED/GREEN으로 보완했다. 최초 병렬 Gradle 검증은mergeDebugResourcesincremental missing file로 실패했으나 순차 재실행에서 PASS했다.adb devices에 연결 기기가 없어 Task 5.3 실기기 수동 확인은 계속 blocked다. - 2026-07-30 Phase 1
13 통합 리뷰:3 focused test, Phase 4·6·7·8·9·11·12·13 source/feed focused test, 팔로잉 전체 회귀 36개,docs/sample/sample-review.md와 review guide에 따라 Phase별 리뷰 보고서 13개를reviews/아래의phase1-...-review.md부터phase13-...-review.md까지 작성했다. 확정 항목은REV-P3-001(Loading 상태 발행 순서 테스트 누락),REV-P4-001(On Air·스케줄 item 이동 no-op),REV-P4-002(LoginRequired pull refresh 종료 누락),REV-P6-001(Feed 전환 전 obsolete layout),REV-P7-001(영어·일본어 ranking 순위 단위의 한국어 고정),REV-P10-001(On Air item 간격 누락)이며, 코드 수정 전에 해당 Phase에 Task 3.4, 4.6, 4.7, 6.5, 7.5, 10.2를 추가했다. Phase 5 실기기 수동 확인은adb devices에 연결 기기가 없어 기존 Task 5.3 보류를 유지했다. 검증으로 Phase 2:app:mergeDebugResources,:app:compileDebugKotlin,:app:ktlintCheck,git diff --check를 실행했고 모두 PASS했다. Gradle deprecation과 Agora namespace는 기존 경고이며, 이번 리뷰에서는 production 코드를 수정하지 않았다. - 2026-07-30 Phase 13 최근 소식 터치 이동 검증:
onFollowingNewsClick()이CREATOR_RANKING을 기존CreatorActionCommand.Profile로 전달해 해당 크리에이터 채널로 이동하고,AUDIO_CONTENT를 기존ContentActionCommand.AudioDetail로 전달해 해당 오디오 콘텐츠 상세로 이동하도록 보완했다. 기존COMMUNITY_POST상세 이동은 유지하고CONTENT_RANKING,PHOTO_CONTENT는 no-op으로 유지했다. RED에서 focused test 11개 중 요청 동작 관련 3개 실패를 확인했고, GREEN에서 11개 모두 PASS했다. 팔로잉 전체 회귀 테스트,:app:compileDebugKotlin,:app:ktlintCheck,git diff --check가 PASS했다.adb devices에 연결된 기기가 없어 실제 터치 수동 검증은 미실행했다. - 2026-07-13 Phase 12 전체 empty 문구 중앙 표시 검증: 팔로잉 탭 전체 empty 상태에서 기존
screen_home_following_empty리소스를 재사용해아직 팔로잉 소식이 없어요.\n관심 있는 크리에이터를 팔로우해 보세요.문구를 중앙 표시하도록 구현했다. 영어는No following updates yet.\nFollow creators you are interested in., 일본어는フォロー中のお知らせはまだありません。\n気になるクリエイターをフォローしてみましょう。로 갱신했다.HomeFollowingUiState.Empty에서만 empty 문구가 보이고Content,LoginRequired,Error에서는 숨김 처리된다. 검증으로./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,git diff --check모두 PASS. Gradle 실행 중 기존 deprecation warning만 출력됐다. - 2026-07-12 Phase 11 검증: 최근 소식
COMMUNITY_POST상세 이동 계약을 source test로 추가하고HomeMainFragment.onFollowingNewsClick()에서HomeFollowingNewsUiItem.Community만CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId)로 이동하도록 구현했다. RED 시도: 구현 전 targeted test./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainFragmentLoginGuardSourceTest"는 120초/300초 timeout으로 assertion 결과까지 도달하지 못했지만, 당시 production은 no-op 상태였고 새 source test는ensureMainV2NavigationAllowed와 상세 이동 호출 문자열을 요구하도록 추가되어 실패 조건을 고정했다. GREEN: 동일 targeted test PASS. 회귀 검증./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:compileDebugKotlin,git diff --checkPASS../gradlew --no-daemon :app:ktlintCheck는 이번 변경과 무관한 기존 legacy/source 위반(explorer/profile/creator_communitypackage underscore,LiveRoomActivity.ktformatting,NicknameUpdateViewModel.ktindentation 등)으로 FAIL. 실기기 수동 QA는adb devices결과 연결된 device가 없어 blocked. - 2026-06-25 Phase 1-3 구현 검증:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS. - 2026-06-25 Phase 1-3 코드 리뷰 및 재검증: blocking finding 없음.
./gradlew :app:mergeDebugResources는 최초 sandbox lock 권한 오류 후 승인 실행으로 PASS했고, 나머지 검증 명령도 PASS. - 2026-06-25 Phase 4 코드 리뷰 및 검증: Figma
24:5682기준 UI 필드 바인딩 누락을 보완했고,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS. - 2026-06-25 Phase 4 재코드 리뷰 및 검증: blocking finding 없음. Figma
24:5682디자인 컨텍스트/스크린샷과 현재 Phase 4 변경을 정적 대조했고,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS.mergeDebugResources는 최초 sandbox lock 권한 오류 후 승인 실행으로 PASS했다. - 2026-06-25 Phase 5 진행 검증:
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS../gradlew :app:installDebug는 실행 중 Android 디바이스 연결 해제로 실패했고, 재확인 시 연결된 디바이스가 없어 실제 화면 수동 확인은 blocked 상태다. - 2026-06-26 Phase 6 후속 디자인 수정 검증: Figma
24:5682기준 팔로잉 크리에이터 header 제거, 최근 대화 horizontal box list, Direct badge/상대시간 표시를 RED 테스트로 고정한 뒤 GREEN 확인했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check,./gradlew :app:installDebug,adb shell monkey -p kr.co.vividnext.sodalive.debug -c android.intent.category.LAUNCHER 1모두 PASS. - 2026-06-26 Phase 6 리뷰 지적 후 재검증: 최근 대화 item 폭 override를 제거하고 source test를 보강했다.
./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest.following recent chat item matches figma box fields",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check,./gradlew :app:installDebug모두 PASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-26 최근 대화 한 줄 제한 후속 검증:
item_home_following_chat.xml의tv_home_following_chat_message를maxLines="1"로 변경하고 기존ellipsize="end"를 유지했다. RED/GREEN source test,./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,git diff --check모두 PASS. - 2026-06-26 최근 소식 Feed 위젯 재사용 후속 검증: 최근 소식 chevron 제거와
FeedCommunityView/FeedRankView/FeedContentView재사용을 source test로 고정했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --check모두 PASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-30 최근 소식 ranking/content 후속 검증: Figma
24:5717,1229:27212기준으로 ranking 문장형 message와 content feed88dp이미지/간격을 RED 테스트로 고정한 뒤 GREEN 확인했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest" --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,git diff --checkPASS../gradlew :app:ktlintCheck는 이번 변경과 무관한CreatorRankingTopCardView.kt:11기존 unused import로 FAIL. - 2026-06-30 content feed clipping 위치 수정 검증:
docs/agent-guides/code-style.md의 XMLandroid:clipToOutline금지 규칙에 맞춰view_feed_content.xml속성을 제거하고FeedContentViewKotlin 코드에서 rootclipToOutline/outlineProvider를 설정했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.feed.FeedViewTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,git diff --checkPASS. - 2026-06-30 팔로잉 크리에이터
전체버튼 후속 검증: 팔로잉 크리에이터 RecyclerView 마지막에전체item을 추가하고FollowingCreatorActivity이동을 연결했다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest"RED/GREEN,./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --checkPASS.mergeDebugResources는 최초 sandbox lock 권한 오류 후 승인 실행으로 PASS했고,ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-30 팔로잉 크리에이터
전체버튼 높이 보정 후 재검증:전체item root는wrap_content높이로 두고 invisible nickname spacer로 creator item 전체 높이를 맞췄다../gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeFollowingFragmentSourceTest",./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew :app:mergeDebugResources,./gradlew :app:compileDebugKotlin,./gradlew :app:ktlintCheck,git diff --checkPASS.mergeDebugResources는 최초 sandbox lock 권한 오류 후 승인 실행으로 PASS했고,ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-30 Phase 9 최근 소식 Response nested payload 계약 반영 검증:
FollowingNewsResponse를newsId,type,visibleFromAtUtc, type별 nested payload만 갖는 구조로 갱신하고 mapper/adapter를 matching payload 기준으로 변경했다. RED: 새 nested DTO/UI 필드 미구현으로compileDebugUnitTestKotlin실패. GREEN: focused test PASS. 통합 검증./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --check모두 PASS.ktlintCheck에서는 기존.editorconfig disabled_rulesdeprecation warning만 출력됐다. - 2026-06-30 Phase 9 코드 리뷰 후 nullable 계약 보완 검증: PRD의
contentImageUrl: String?계약과 구현의 non-null DTO/UI model 불일치를 수정했다. RED: null image fixture 추가 시compileDebugUnitTestKotlintype mismatch 실패. GREEN:contentImageUrlnullable DTO/UI model과 adapter.orEmpty()fallback 적용 후 focused mapper test PASS. 통합 재검증./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",./gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:compileDebugKotlin,./gradlew --no-daemon :app:ktlintCheck,git diff --checkPASS. - 2026-07-03 Phase 10 On Air 라이브 item Figma 재구현 검증: Figma
24:5696기준으로item_home_following_live.xml을 캡슐형 카드로 재구현하고bg_home_following_live_capsule.xml을 추가했다../gradlew --no-daemon :app:mergeDebugResources,./gradlew --no-daemon :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*Following*",git diff --checkPASS. Gradle 실행 중 기존 deprecation warning만 출력됐다. - 2026-07-03 Phase 10 후속 정리:
item_home_following_live.xml에서 불필요한iv_home_following_live_thumbnail을 제거하고,HomeFollowingLiveAdapter의 해당 id 조회와loadUrl호출을 삭제했다.