From 4012b92357c928424a93dba9a2f1c1103296b610 Mon Sep 17 00:00:00 2001 From: klaus Date: Mon, 22 Jun 2026 16:38:15 +0900 Subject: [PATCH] =?UTF-8?q?docs(creator):=20FanTalk=20=ED=83=AD=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EA=B2=80=EC=A6=9D=EC=9D=84=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/20260622_FanTalk_탭/plan-task.md | 36 ++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/docs/20260622_FanTalk_탭/plan-task.md b/docs/20260622_FanTalk_탭/plan-task.md index 2eab0e19..3b592c8a 100644 --- a/docs/20260622_FanTalk_탭/plan-task.md +++ b/docs/20260622_FanTalk_탭/plan-task.md @@ -221,7 +221,7 @@ ### Phase 2: API/DTO/Repository/ViewModel 계약 추가 -- [ ] **Task 2.1: FanTalk 탭 DTO 추가** +- [x] **Task 2.1: FanTalk 탭 DTO 추가** - 생성: - `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/data/CreatorChannelFanTalkTabResponse.kt` - 작업: @@ -233,8 +233,11 @@ - 기대 결과: - 신규 DTO 추가 후 컴파일이 PASS한다. - 검증 기록: + - 2026-06-22: `CreatorChannelFanTalkTabResponse.kt`에 `@Keep`/`@SerializedName` 기반 `CreatorChannelFanTalkTabResponse`, `CreatorChannelFanTalkResponse`, `CreatorChannelFanTalkReplyResponse`를 추가했다. + - `fanTalkCount`, `fanTalks`, `page`, `size`, `hasNext`, `fanTalkId`, `writerId`, `writerNickname`, `writerProfileImageUrl`, `content`, `createdAtUtc`, `creatorReplies` 필드가 PRD/계획 문서의 서버 필드명과 일치함을 확인했다. + - `./gradlew :app:compileDebugKotlin` 실행 결과 PASS. -- [ ] **Task 2.2: FanTalk 탭 endpoint와 Repository method 추가** +- [x] **Task 2.2: FanTalk 탭 endpoint와 Repository method 추가** - 수정: - `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelApi.kt` - `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelRepository.kt` @@ -249,8 +252,11 @@ - 기대 결과: - API/Repository 추가 후 기존 Koin graph와 충돌 없이 컴파일된다. - 검증 기록: + - 2026-06-22: `CreatorChannelApi.getFanTalks()`에 `@GET("/api/v2/creator-channels/{creatorId}/fan-talks")` endpoint를 추가하고 query parameter가 `page`, `size`만 전달되도록 구현했다. + - `CreatorChannelRepository.getFanTalks(creatorId, page, size, token)`, `reportFanTalk(fanTalkId, reason, token)`, `deleteFanTalk(fanTalkId, token)`를 추가했다. 신고는 `ReportRequest(ReportType.CHEERS, reason, cheersId = fanTalkId)`, 삭제는 `PutModifyCheersRequest(cheersId = fanTalkId, isActive = false)`로 기존 repository에 위임함을 확인했다. + - `./gradlew :app:compileDebugKotlin` 실행 결과 PASS. -- [ ] **Task 2.3: ViewModel RED 테스트 작성** +- [x] **Task 2.3: ViewModel RED 테스트 작성** - 생성: - `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkViewModelTest.kt` - `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkPaginationTest.kt` @@ -277,8 +283,11 @@ - 기대 결과: - production 구현 전 `CreatorChannelFanTalkViewModel` 미구현으로 RED 실패한다. - 검증 기록: + - 2026-06-22: `CreatorChannelFanTalkViewModelTest.kt`, `CreatorChannelFanTalkPaginationTest.kt`, `CreatorChannelFanTalkActionTest.kt`를 추가했다. + - production 구현 전 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkMapperTest"`를 실행했을 때 unit test compile 단계에서 `CreatorChannelFanTalkViewModel`, `CreatorChannelFanTalkTabResponse`, `getFanTalks`, `reportFanTalk`, `deleteFanTalk` 등 미구현 참조로 실패해 RED 상태를 확인했다. + - 구현 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.*"` 실행 결과 PASS. -- [ ] **Task 2.4: `CreatorChannelFanTalkViewModel` 구현** +- [x] **Task 2.4: `CreatorChannelFanTalkViewModel` 구현** - 생성: - `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkViewModel.kt` - 수정: @@ -298,12 +307,18 @@ - 기대 결과: - ViewModel 관련 테스트가 GREEN이다. - 검증 기록: + - 2026-06-22: `CreatorChannelFanTalkViewModel.kt`를 추가하고 `AppDI.kt`에 `viewModel { CreatorChannelFanTalkViewModel(get(), get()) }` binding을 추가했다. + - `DEFAULT_PAGE_SIZE = 20`, `FIRST_PAGE = 0`, 동일 조건 최초 조회 중복 방지, `requestGeneration`, load-more guard, pagination error 유지/consume, 신고/삭제 action message, 삭제 성공 후 refresh 동작을 테스트로 확인했다. + - `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.*"` 실행 결과 PASS. + - 2026-06-22 리뷰 수정: 신고 성공 응답의 `message`가 null이면 `character_comment_report_submitted` fallback toast message를 사용하도록 수정했다. + - RED: `CreatorChannelFanTalkActionTest`에 `ApiResponse(true, Any(), null)` 케이스를 추가한 뒤 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkActionTest"` 실행 시 `expected: but was:`로 실패함을 확인했다. + - GREEN: `SodaLiveApplicationHolder` 초기화가 포함된 action 테스트와 ViewModel fallback 수정 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.CreatorChannelFanTalkActionTest"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.*"`, `./gradlew :app:compileDebugKotlin`, `git diff --check` 실행 결과 PASS. --- ### Phase 3: Mapper와 권한별 UI model 추가 -- [ ] **Task 3.1: FanTalk UI model 추가** +- [x] **Task 3.1: FanTalk UI model 추가** - 생성: - `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/model/CreatorChannelFanTalkUiModels.kt` - 작업: @@ -318,8 +333,11 @@ - 기대 결과: - UI model 추가 후 컴파일이 PASS한다. - 검증 기록: + - 2026-06-22: `CreatorChannelFanTalkUiModels.kt`에 원글/답글 UI model과 `CreatorChannelFanTalkRightAction.Report`, `OwnerMore(showEdit, showDelete)`를 추가했다. + - mapper/action 테스트에서 내가 쓴 글은 `OwnerMore(showEdit = true, showDelete = true)`, 내 채널의 타인 글은 `OwnerMore(showEdit = false, showDelete = true)`, 타인 채널의 타인 글은 `Report`로 매핑됨을 확인했다. + - `./gradlew :app:compileDebugKotlin` 실행 결과 PASS. -- [ ] **Task 3.2: Mapper RED/GREEN 테스트 작성** +- [x] **Task 3.2: Mapper RED/GREEN 테스트 작성** - 생성: - `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/fantalk/CreatorChannelFanTalkMapperTest.kt` - 테스트 케이스: @@ -338,6 +356,10 @@ - 기대 결과: - Mapper 테스트가 GREEN이다. - 검증 기록: + - 2026-06-22: `CreatorChannelFanTalkMapperTest.kt`를 추가하고 production 구현 전 미구현 참조로 RED 실패함을 확인했다. + - `CreatorChannelFanTalkMappers.kt`에 `List.toFanTalkUiModels(relativeTimeTextFormatter, isOwner, currentUserId)`를 추가했다. + - `createdAtUtc`의 `UtcRelativeTimeTextFormatter.format()` 매핑, `creatorReplies.firstOrNull()` 1개 reply 매핑, 권한별 right action, 빈 content 유지 케이스를 테스트로 확인했다. + - `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.*"` 및 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*FanTalk*"` 실행 결과 PASS. --- @@ -542,3 +564,5 @@ ## Verification Log - 문서 작성 시점에는 구현을 수행하지 않았으므로 빌드/테스트 검증 기록이 없다. +- 2026-06-22: Phase 2, 3 코드 리뷰를 수행했다. API/DTO/Repository/ViewModel/mapper/action model/test 변경이 PRD와 계획 문서의 계약 범위 안에 있으며, 레거시 파일 직접 수정 없이 기존 repository/dialog 계약을 호출하는 구조임을 확인했다. blocking finding은 발견하지 못했다. +- 2026-06-22: Phase 2, 3 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.fantalk.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*FanTalk*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`, `git diff --cached --check`를 실행했고 모두 PASS했다.