docs(chat): 채팅방 Adapter 검증을 기록한다

This commit is contained in:
2026-06-10 13:26:03 +09:00
parent 346671b3e2
commit 55fb032b22

View File

@@ -275,7 +275,7 @@
### Phase 5: 채팅방 list item UI와 Adapter 작성 ### Phase 5: 채팅방 list item UI와 Adapter 작성
- [ ] **Task 5.1: Direct badge와 item layout 추가** - [x] **Task 5.1: Direct badge와 item layout 추가**
- Create: `app/src/main/res/drawable/bg_chat_direct_badge.xml` - Create: `app/src/main/res/drawable/bg_chat_direct_badge.xml`
- Create: `app/src/main/res/layout/item_v2_chat_room.xml` - Create: `app/src/main/res/layout/item_v2_chat_room.xml`
- Modify: `app/src/main/res/values/strings.xml` - Modify: `app/src/main/res/values/strings.xml`
@@ -292,7 +292,7 @@
- 검증 명령: `./gradlew :app:mergeDebugResources` - 검증 명령: `./gradlew :app:mergeDebugResources`
- 기대 결과: 신규 layout/drawable/string resource merge 성공. - 기대 결과: 신규 layout/drawable/string resource merge 성공.
- [ ] **Task 5.2: Adapter RED 테스트 작성** - [x] **Task 5.2: Adapter RED 테스트 작성**
- Create: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/ChatRoomListAdapterTest.kt` - Create: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/ChatRoomListAdapterTest.kt`
- 테스트 케이스: - 테스트 케이스:
- DM item bind 시 Direct badge가 `VISIBLE` - DM item bind 시 Direct badge가 `VISIBLE`
@@ -303,7 +303,7 @@
- 검증 명령: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatRoomListAdapterTest"` - 검증 명령: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatRoomListAdapterTest"`
- 기대 결과: Adapter 미구현으로 RED 실패. - 기대 결과: Adapter 미구현으로 RED 실패.
- [ ] **Task 5.3: Adapter 구현** - [x] **Task 5.3: Adapter 구현**
- Create: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/ui/ChatRoomListAdapter.kt` - Create: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/ui/ChatRoomListAdapter.kt`
- 구현: - 구현:
- `RecyclerView.Adapter` - `RecyclerView.Adapter`
@@ -493,3 +493,5 @@
- 2026-06-10: Phase 4 검증 완료. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 10s`, `./gradlew :app:mergeDebugResources``BUILD SUCCESSFUL in 1s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 1s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 5s`로 통과했다. ktlint 실행 중 `.editorconfig``disabled_rules` deprecation warning과 Gradle deprecation warning은 기존 경고로 남아 있다. - 2026-06-10: Phase 4 검증 완료. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 10s`, `./gradlew :app:mergeDebugResources``BUILD SUCCESSFUL in 1s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 1s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 5s`로 통과했다. ktlint 실행 중 `.editorconfig``disabled_rules` deprecation warning과 Gradle deprecation warning은 기존 경고로 남아 있다.
- 2026-06-10: Phase 4 리뷰 게이트에서 filter 변경 중 늦게 도착한 first page/next page 응답이 현재 filter 상태를 덮거나 append할 수 있는 race 조건이 발견되어 보강했다. `filter 변경 전 첫 페이지 응답이 늦게 도착하면 현재 filter 목록을 덮어쓰지 않는다`, `filter 변경 전 다음 페이지 응답이 늦게 도착하면 현재 filter 목록에 append하지 않는다` 테스트를 추가했고, 기존 구현에서 각각 `AssertionError`로 RED 실패를 확인했다. 이후 `ChatMainViewModel``requestGeneration` guard를 추가하고 first page 시작 시 `_isAppending=false`로 reset해 stale first/append 응답을 무시하도록 수정했다. 수정 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatMainViewModelTest"``BUILD SUCCESSFUL in 18s`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 8s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 1s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 3s`, `./gradlew :app:mergeDebugResources``BUILD SUCCESSFUL in 1s`로 재통과했다. - 2026-06-10: Phase 4 리뷰 게이트에서 filter 변경 중 늦게 도착한 first page/next page 응답이 현재 filter 상태를 덮거나 append할 수 있는 race 조건이 발견되어 보강했다. `filter 변경 전 첫 페이지 응답이 늦게 도착하면 현재 filter 목록을 덮어쓰지 않는다`, `filter 변경 전 다음 페이지 응답이 늦게 도착하면 현재 filter 목록에 append하지 않는다` 테스트를 추가했고, 기존 구현에서 각각 `AssertionError`로 RED 실패를 확인했다. 이후 `ChatMainViewModel``requestGeneration` guard를 추가하고 first page 시작 시 `_isAppending=false`로 reset해 stale first/append 응답을 무시하도록 수정했다. 수정 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatMainViewModelTest"``BUILD SUCCESSFUL in 18s`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 8s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 1s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 3s`, `./gradlew :app:mergeDebugResources``BUILD SUCCESSFUL in 1s`로 재통과했다.
- 2026-06-10: `ChatMainViewModel`에서 `Context`를 필드로 보관해 `This field leaks a context object` 경고가 발생할 수 있는 구조를 점검했다. 시간 포맷은 리소스가 필요한 표시 계층 책임으로 두는 편이 적절하다고 판단해 `ChatRoomListUiItem``lastMessageTimeText` 대신 원본 `lastMessageAt`을 보관하도록 바꾸고, `ChatRoomMappers.toUiItem()/toUiItems()``ChatMainViewModel`에서 `Context` 의존을 제거했다. `AppDI` 등록도 `viewModel { ChatMainViewModel(get()) }`로 되돌렸으며, Phase 5 Adapter 구현 시 bind 직전에 `formatChatRoomLastMessageTime(context, item.lastMessageAt)`을 호출하도록 계획 문서의 계약을 갱신했다. 테스트 계약 변경 후 최초 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatRoomMapperTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatMainViewModelTest"`는 기존 production이 아직 `context` 파라미터와 `lastMessageTimeText`를 요구해 `No value passed for parameter 'context'`, `Unresolved reference 'lastMessageAt'`로 RED 실패했다. 구현 수정 후 같은 명령은 `BUILD SUCCESSFUL in 19s`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 9s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 1s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 4s`로 통과했다. ktlint의 `.editorconfig disabled_rules` deprecation warning과 Gradle deprecation warning은 기존 경고로 남아 있다. - 2026-06-10: `ChatMainViewModel`에서 `Context`를 필드로 보관해 `This field leaks a context object` 경고가 발생할 수 있는 구조를 점검했다. 시간 포맷은 리소스가 필요한 표시 계층 책임으로 두는 편이 적절하다고 판단해 `ChatRoomListUiItem``lastMessageTimeText` 대신 원본 `lastMessageAt`을 보관하도록 바꾸고, `ChatRoomMappers.toUiItem()/toUiItems()``ChatMainViewModel`에서 `Context` 의존을 제거했다. `AppDI` 등록도 `viewModel { ChatMainViewModel(get()) }`로 되돌렸으며, Phase 5 Adapter 구현 시 bind 직전에 `formatChatRoomLastMessageTime(context, item.lastMessageAt)`을 호출하도록 계획 문서의 계약을 갱신했다. 테스트 계약 변경 후 최초 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatRoomMapperTest" --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatMainViewModelTest"`는 기존 production이 아직 `context` 파라미터와 `lastMessageTimeText`를 요구해 `No value passed for parameter 'context'`, `Unresolved reference 'lastMessageAt'`로 RED 실패했다. 구현 수정 후 같은 명령은 `BUILD SUCCESSFUL in 19s`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 9s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 1s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 4s`로 통과했다. ktlint의 `.editorconfig disabled_rules` deprecation warning과 Gradle deprecation warning은 기존 경고로 남아 있다.
- 2026-06-10: Phase 5 완료. Task 5.1에서 `bg_chat_direct_badge.xml`, `item_v2_chat_room.xml`을 생성하고 `strings.xml`/`values-en`/`values-ja``screen_chat_direct_badge`, `screen_chat_filter_all/ai/dm` 문자열을 추가했다. `./gradlew :app:mergeDebugResources``BUILD SUCCESSFUL in 6s`로 통과했다. Task 5.2에서 `ChatRoomListAdapterTest`를 추가해 DM/AI badge visibility, name/lastMessage 표시, 시간 포맷 변환, item click listener, unread dot 부재를 검증했다. 최초 실행은 `ChatRoomListAdapter` 미구현으로 RED 실패를 확인했다. Task 5.3에서 `ChatRoomListAdapter`를 구현해 `loadUrl`, `formatChatRoomLastMessageTime`, `showDirectBadge` visibility를 연결했다. 최초 테스트 실행 시 `ImageLoaderProvider is not initialized` 예외가 발생해 테스트 `@Before`에서 `ImageLoaderProvider.init(context)`를 추가했다. 수정 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatRoomListAdapterTest"``BUILD SUCCESSFUL in 8s`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 7s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 1m 15s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 3s`로 통과했다.
- 2026-06-10: Phase 5 리뷰와 Figma `177:3469` 대조를 추가 수행했다. 기존 `dimens.xml`, `typography.xml`, `bg_character_chat_count_badge.xml`, `loadUrl`/Coil 원형 변환 패턴을 확인해 `item_v2_chat_room.xml`의 하드코딩 spacing/typography 일부를 기존 토큰으로 치환하고, `bg_chat_direct_badge.xml``4dp` radius를 `@dimen/radius_4`로 변경했다. Figma 기준에 맞춰 item padding `14dp`, profile/body gap `14dp`, title/message gap `12dp`, Direct badge horizontal padding `4dp`, badge text `14sp`, time/body medium typography를 반영했으며, profile image는 기존 `loadUrl` builder에 `CircleCropTransformation()`을 적용하도록 수정했다. `ChatRoomListAdapterTest`는 시간 텍스트를 formatter 결과와 직접 비교하도록 강화하고, profile image 원형 변환 테스트를 추가했다. RED 확인으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatRoomListAdapterTest"``Unresolved reference 'profileImageTransformations'`로 실패한 뒤 production 구현을 추가해 GREEN 전환했다. 리뷰 게이트에서는 AI row에서 Direct badge가 `GONE`일 때 title/time `24dp` gap이 사라질 수 있다는 차단 의견을 받아 `tv_name``app:layout_goneMarginEnd="@dimen/spacing_24"`를 추가했고, 재리뷰에서 무조건 승인을 받았다. 최종 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.ChatRoomListAdapterTest"``BUILD SUCCESSFUL in 23s`, `./gradlew :app:mergeDebugResources``BUILD SUCCESSFUL in 15s`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.*"``BUILD SUCCESSFUL in 30s`, `./gradlew :app:compileDebugKotlin``BUILD SUCCESSFUL in 7s`, `./gradlew :app:ktlintCheck``BUILD SUCCESSFUL in 17s`로 통과했다. Gradle deprecation warning은 기존 경고로 남아 있다.