# 커뮤니티 게시물 상세 / 댓글 / 답글 구현 계획/TASK > **For agentic workers:** 각 단계는 체크박스(`- [ ]`)로 추적하고, 완료 즉시 `- [x]`로 갱신한다. 구현 범위 변경이 생기면 이 문서를 먼저 수정한 뒤 코드에 반영한다. **Goal:** 크리에이터 채널 `커뮤니티` 탭에서 게시글 item 터치 시 게시물 상세로 진입해 본문/좋아요/댓글을 조회·작성하고, 댓글의 답글 목록 화면(팬Talk 상세와 동일 UI)에서 답글을 조회·작성하며, 수정/삭제/좋아요는 기존 API를 재사용한다. **Architecture:** 조회(상세/댓글/답글)는 신규 v2 endpoint를 v2 API/Repository로 호출한다. 쓰기/수정/삭제/좋아요는 기존 `CreatorCommunityRepository`를 그대로 호출한다. 화면은 커뮤니티 전용으로 신규 구현하되, 답글 목록 화면의 layout XML과 댓글/답글 item view만 재사용 가능하게 설계한다. **Tech Stack:** Kotlin, Android XML Views, ViewBinding, RxJava3, Koin, JUnit4/Robolectric. --- ## 전제와 성공 기준 - PRD: `docs/20260708_커뮤니티_게시물_상세_댓글_답글/prd.md` - 기존 커뮤니티 탭 문서: - `docs/20260621_크리에이터_채널_커뮤니티_탭/prd.md` - `docs/20260621_크리에이터_채널_커뮤니티_탭/plan-task.md` - 재사용 vs 복사 결정: 커뮤니티 전용 신규 구현. layout XML + 댓글/답글 item view만 데이터/콜백 주입형으로 공용화(데이터 계층은 커뮤니티 전용). 근거는 PRD `11. Open Questions & Decisions` 참고. - 조회 API는 신규 v2 endpoint를 사용하고 기본값 `page=0`, `size=20`을 따른다. - 쓰기/수정/삭제/좋아요/팝업 메뉴는 기존 커뮤니티 코드를 재사용한다. - 구현 완료 판단 시 Gradle 검증뿐 아니라 Figma 4개 화면의 주요 layout, 하트/전송 버튼 상태, 댓글 불가 처리, 입력 영역 동작이 실제 구현 화면에 반영되었는지 확인한다. - Figma 대조 결과는 문서 최하단 `Verification Log`에 한국어로 누적 기록한다. - 구현 완료 후 최소 다음 명령을 실행한다. - `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"` - `./gradlew :app:mergeDebugResources` - `./gradlew :app:compileDebugKotlin` - `./gradlew :app:ktlintCheck` - `git diff --check` --- ## Figma 참조 - 게시글 상세(댓글 가능 + 댓글 있음): `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=290-9243&m=dev` - 게시글 상세(댓글 불가능): `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=290-9266&m=dev` - 댓글 답글 목록(답글 없음): `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40462&m=dev` - 댓글 답글 목록(답글 있음): `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40468&m=dev` --- ## API 계약 - 조회(신규 v2, `ApiResponse`): - 상세: `GET /api/v2/creator-channels/community-posts/{postId}` → `CreatorChannelCommunityPostDetailResponse` - 필드: `postId`, `creatorId`, `creatorNickname`, `creatorProfileUrl`, `createdAtUtc`, `content`, `imageUrl`, `audioUrl`, `price`, `isCommentAvailable`, `existOrdered`, `likeCount`, `commentCount`, `isPinned`, `isLiked`, `comments` - `comments`는 댓글 첫 페이지(`CreatorChannelCommunityCommentsResponse`)를 포함한다. - 댓글: `GET /api/v2/creator-channels/community-posts/{postId}/comments?page=0&size=20` → `CreatorChannelCommunityCommentsResponse` - 필드: `commentCount`, `comments`, `page`, `size`, `hasNext` - 댓글 필드: `commentId`, `writerId`, `writerProfileImageUrl`, `writerNickname`, `content`, `isSecret`, `createdAtUtc`, `latestReply` - 최신 답글 필드: `commentId`, `writerId`, `writerProfileImageUrl`, `writerNickname`, `content`, `createdAtUtc` - 답글: `GET /api/v2/creator-channels/community-comments/{commentId}/replies?page=0&size=20` → `CreatorChannelCommunityRepliesResponse` - 쓰기/수정/삭제/좋아요(기존 `CreatorCommunityRepository` 재사용): - 좋아요: `communityPostLike(postId, token)` - 댓글 쓰기: `registerComment(postId, comment, token = token)` - 답글 쓰기: `registerComment(postId, comment, parentId = commentId, token = token)` - 댓글/답글 수정: `modifyComment(ModifyCommentRequest(commentId, comment = ...), token)` - 댓글/답글 삭제: `modifyComment(ModifyCommentRequest(commentId, isActive = false), token)` - 팝업 메뉴: `R.menu.content_comment_option_menu`(내 댓글/답글: 수정/삭제), `R.menu.content_comment_option_menu2`(채널 크리에이터가 보는 타인 댓글/답글: 삭제). 일반 타인 댓글/답글은 커뮤니티 댓글 전용 신고 API가 없어 더보기 버튼을 노출하지 않는다. --- ## 파일 구조 (예정) - 생성(응답 모델): `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/detail/data/CreatorChannelCommunityDetailResponse.kt` - PRD의 `CreatorChannelCommunityPostDetailResponse`, `CreatorChannelCommunityCommentsResponse`, `CreatorChannelCommunityCommentResponse`, `CreatorChannelCommunityReplyResponse`, `CreatorChannelCommunityRepliesResponse`. - 수정: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelApi.kt` - 상세/댓글/답글 조회 endpoint 3개 추가. - 수정: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelRepository.kt` - 상세/댓글/답글 조회 method 추가. - 생성(진입점): 커뮤니티 탭 item 터치 → 상세 화면 이동. - 수정: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/CreatorChannelCommunityFragment.kt`(item click을 Host callback으로 위임). - 수정: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/ui/CreatorChannelCommunityListAdapter.kt`, `CreatorChannelCommunityGridAdapter.kt`(item click 콜백 추가). - 수정: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt`(상세 화면 실행). - 생성(상세 화면): `.../community/detail/CreatorChannelCommunityDetailActivity.kt`, `CreatorChannelCommunityDetailViewModel.kt` - 생성(답글 화면): `.../community/detail/reply/CreatorChannelCommunityReplyActivity.kt`, `CreatorChannelCommunityReplyViewModel.kt` - 생성(layout): `activity_creator_channel_community_detail.xml`, `activity_creator_channel_community_reply.xml`, 댓글/답글 item layout, 입력 영역 layout, 전송 버튼 배경 drawable(enabled/disabled). - 생성(어댑터/item view): 댓글 목록 adapter, 답글 목록 adapter(재사용 가능한 댓글/답글 item view). - 수정: `app/src/main/AndroidManifest.xml`(신규 Activity 등록), `app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt`(신규 ViewModel binding). - 수정: `values`, `values-en`, `values-ja` strings(placeholder 등 신규 문자열 또는 기존 재사용). - 테스트 생성: 상세/답글 ViewModel 테스트, layout/source 테스트. --- ### Phase 1: 조회 API/모델 계약 - [x] **Task 1.1: 응답 데이터 클래스 생성** - 생성: `.../community/detail/data/CreatorChannelCommunityDetailResponse.kt` - 작업: PRD 명시 5개 data class를 `@Keep`/`@SerializedName` 포함해 정의한다. - 검증: `./gradlew :app:compileDebugKotlin` - 검증 기록(2026-07-08): TDD RED로 `CreatorChannelCommunityDetailContractTest` 추가 후 DTO 패키지/클래스 미존재로 `:app:compileDebugUnitTestKotlin` 실패를 확인했다. 이후 `CreatorChannelCommunityPostDetailResponse`, `CreatorChannelCommunityCommentsResponse`, `CreatorChannelCommunityCommentResponse`, `CreatorChannelCommunityReplyResponse`, `CreatorChannelCommunityRepliesResponse`를 생성하고 `./gradlew :app:compileDebugKotlin` 성공을 확인했다. - [x] **Task 1.2: v2 API/Repository 조회 method 추가** - 수정: `CreatorChannelApi.kt`, `CreatorChannelRepository.kt` - 작업: 상세/댓글/답글 조회 3개 추가(기본 `page=0`, `size=20`, token 포함). - 검증: `./gradlew :app:compileDebugKotlin` - 검증 기록(2026-07-08): 구현 전 `CreatorChannelApi`/`CreatorChannelRepository`의 상세/댓글/답글 method 미존재로 RED 실패를 확인했다. 구현 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"` 및 `./gradlew :app:compileDebugKotlin` 성공을 확인했다. --- ### Phase 2: 상세 ViewModel/화면 - [x] **Task 2.1: 상세 ViewModel RED 테스트 작성** - 생성: `CreatorChannelCommunityDetailViewModelTest.kt` - 케이스: 상세 로드, 좋아요 토글(낙관적 업데이트+실패 롤백, 중복 방지), 댓글 pagination(hasNext), 댓글 쓰기 성공 후 새로고침, 댓글 불가 시 댓글 조회/입력 미노출. - 검증: 해당 테스트 실행(구현 전 실패). - 검증 기록(2026-07-08): `CreatorChannelCommunityDetailViewModelTest`를 먼저 추가하고 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityDetailViewModelTest"`를 실행해 `CreatorChannelCommunityDetailViewModel`/`CreatorChannelCommunityDetailUiState` 미존재 컴파일 오류로 RED 실패를 확인했다. - [x] **Task 2.2: 상세 ViewModel 구현** - 생성: `CreatorChannelCommunityDetailViewModel.kt` - 검증: `CreatorChannelCommunityDetailViewModelTest` PASS. - 검증 기록(2026-07-08): `CreatorChannelCommunityDetailViewModel`과 상세/댓글/답글 UI state model을 추가하고 동일한 테스트 명령을 재실행해 PASS를 확인했다. 상세 조회, 댓글 첫 페이지/페이지네이션, 좋아요 낙관적 토글/중복 방지/실패 롤백, 댓글 trim 작성/성공 이벤트/댓글 새로고침, 댓글 불가 시 댓글 API/작성 미호출을 검증했다. - [x] **Task 2.3: 상세 layout/Activity 구현** - 생성: `activity_creator_channel_community_detail.xml`, `CreatorChannelCommunityDetailActivity.kt`, 댓글 adapter/item, 입력 영역, 전송 버튼 drawable. - 작업: Figma `290:9243`(댓글 가능)/`290:9266`(댓글 불가) 기준. 하트 fill/empty, 전송 버튼 gray_900/soda_400 상태, 3줄 자동확장/4줄 스크롤, 댓글 불가 시 댓글/입력 영역 숨김, 최신 답글 1개 중첩 표시, 더보기 팝업 메뉴 재사용. - 수정: `AndroidManifest.xml`, `AppDI.kt`. - 검증: `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin` - 검증 기록(2026-07-08): `CreatorChannelCommunityDetailReplyUiContractTest`를 먼저 추가하고 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`를 실행해 상세/답글 layout·id·source 미존재 컴파일 오류로 RED 실패를 확인했다. 이후 `activity_creator_channel_community_detail.xml`, `CreatorChannelCommunityDetailActivity`, 댓글 adapter/item, 입력 bar 배경/전송 icon drawable, 문자열, manifest/AppDI 등록을 추가했다. 상세 화면은 `newIntent(context, postId)`로 진입하고 `postId <= 0`은 toast 후 종료하며, 하트 토글/댓글 입력 trim 활성화/댓글 불가 시 댓글 목록과 하단 입력 숨김/최신 답글 card 클릭 답글 화면 진입/팝업 메뉴 재사용 계약을 반영했다. --- ### Phase 3: 답글 화면 - [x] **Task 3.1: 답글 ViewModel RED 테스트/구현** - 생성: `CreatorChannelCommunityReplyViewModel(.kt/Test.kt)` - 케이스: 부모 댓글/답글 로드, 답글 pagination, 답글 쓰기(`parentId = commentId`) 후 새로고침, 수정/삭제 후 새로고침. - 검증: 테스트 PASS. - 검증 기록(2026-07-08): `CreatorChannelCommunityReplyViewModelTest`를 먼저 추가하고 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityReplyViewModelTest"`를 실행해 `CreatorChannelCommunityReplyViewModel`/`CreatorChannelCommunityReplyUiState` 미존재 컴파일 오류로 RED 실패를 확인했다. 이후 `CreatorChannelCommunityReplyViewModel`을 추가하고 동일 명령을 재실행해 PASS를 확인했다. 부모 댓글 보존/답글 첫 페이지 조회, `hasNext` 페이지네이션과 중복 `loadMore` 방지, 답글 trim 작성/blank 무시/중복 전송 방지/성공 후 입력·이벤트 정리 및 새로고침, 수정·삭제 후 새로고침, `commentId <= 0`일 때 답글 API 미호출을 검증했다. - [x] **Task 3.2: 답글 layout/Activity 구현** - 생성: `activity_creator_channel_community_reply.xml`, `CreatorChannelCommunityReplyActivity.kt`, 재사용 가능한 댓글/답글 item view/adapter. - 작업: Figma `669:40462`(답글 없음)/`669:40468`(답글 있음) 기준. 부모 댓글 상단 표시, 답글 들여쓰기, placeholder `답글을 입력하세요`, 더보기 팝업 메뉴 재사용. - 수정: `AndroidManifest.xml`, `AppDI.kt`. - 검증: `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin` - 검증 기록(2026-07-08): 상세 UI 계약 RED 테스트에 답글 layout/source 계약을 함께 추가해 실패를 확인한 뒤 `activity_creator_channel_community_reply.xml`, `CreatorChannelCommunityReplyActivity`, 답글 adapter/item을 생성했다. 답글 화면은 primitive extras로 부모 댓글을 재구성하고 상단 부모 댓글 표시, 들여쓰기 답글 card, `답글을 입력하세요` 입력 bar, trim 기반 전송 버튼 상태, `updateReplyInput`/`submitReply`, 팝업 메뉴의 `modifyReply`/`deleteReply` 연결을 반영했다. --- ### Phase 4: 진입점 연결 - [x] **Task 4.1: 커뮤니티 탭 item 터치 → 상세 진입** - 수정: `CreatorChannelCommunityListAdapter.kt`, `CreatorChannelCommunityGridAdapter.kt`, `CreatorChannelCommunityFragment.kt`(Host callback 추가), `CreatorChannelActivity.kt`. - 작업: item 터치 시 `postId`로 상세 화면 실행. 댓글에서 답글 화면(`commentId`) 진입 연결. 좋아요/댓글/답글 작성 후 목록 새로고침 정책 연결. - 검증: `./gradlew :app:compileDebugKotlin` - 검증 기록(2026-07-08): `CreatorChannelCommunityFragmentLayoutTest`와 `CreatorChannelActivitySourceTest`에 RED source 계약을 먼저 추가해 list/grid adapter root click callback, fragment Host 위임, Activity의 상세 화면 `newIntent` 진입 계약 실패를 확인했다. 이후 list/grid adapter에 `onPostClick`을 추가하고 play/owner more click은 기존 콜백으로 분리 유지했으며, fragment는 `postId`를 Host로 위임하고 Activity는 `postId <= 0L`을 무시한 뒤 `CreatorChannelCommunityDetailActivity.newIntent(this, postId)`로 상세 화면을 실행하도록 연결했다. --- ### Phase 5: 테스트/회귀 검증 - [x] **Task 5.1: source/layout 테스트 추가** - 작업: 조회 API page/size 기본값, 하트 icon 계약(`ic_feed_community_heart_fill`/`ic_feed_community_heart`), 전송 버튼 상태(`ic_new_arrow_up_gray`+gray_900 / `ic_new_arrow_up_white`+soda_400), 댓글 불가 시 댓글/입력 숨김, placeholder 문구를 검증. - 검증: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"` - 검증 기록(2026-07-08): review-work 차단 이슈 회귀를 막기 위해 상세 댓글 수정/삭제 ViewModel 테스트와 상세/답글 source 계약 테스트를 먼저 추가했다. 구현 전 동일 targeted 테스트를 실행해 `CreatorChannelCommunityDetailViewModel.modifyComment/deleteComment` 미구현 컴파일 오류로 RED 실패를 확인했다. 구현 후 동일 명령을 재실행해 PASS를 확인했고, 상세/답글 Activity의 하단 도달 pagination 호출, 내 댓글/답글에만 destructive popup 노출, 수정 입력 dialog, 삭제 확인 dialog, 상세 오디오 매니저 연결/lifecycle 정리, 상세 로드 Error finish 계약을 source 테스트로 검증했다. - [x] **Task 5.2: 전체 검증 실행** - 실행: 위 성공 기준의 Gradle 명령 전체. - Figma 수동 확인: `290:9243`, `290:9266`, `669:40462`, `669:40468` 대조. - 검증 기록: `Verification Log`에 누적. - 검증 기록(2026-07-08): review-work 차단 이슈 수정 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`이 PASS했다. 최초 `./gradlew :app:ktlintCheck`는 신규 테스트 source 문자열 길이 초과로 실패했으며, 테스트 문자열 분리 후 재실행해 PASS했다. `git diff --check`는 출력 없이 PASS했다. --- ### Phase 6: review 재반영 및 서버 계약 수정 - [x] **Task 6.1: 서버 댓글 응답 계약 반영** - 작업: 상세 응답 내부 `comments`와 댓글/최신 답글의 `writer*`/`content` 필드명을 DTO와 UI mapping에 반영한다. - 검증: `CreatorChannelCommunityDetailContractTest`, 상세/답글 ViewModel 테스트 PASS. - 검증 기록(2026-07-08): `CreatorChannelCommunityPostDetailResponse`에 `comments`를 추가하고, `CreatorChannelCommunityCommentsResponse.commentCount`, 댓글/답글의 `writerId`, `writerProfileImageUrl`, `writerNickname`, `content` 계약을 반영했다. 상세 최초 댓글 목록은 상세 응답의 embedded `comments`에서 사용하고, 답글 수정/삭제 ID는 응답의 `commentId`를 답글 자체 ID로 매핑했다. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"` PASS로 확인했다. - [x] **Task 6.2: 댓글/답글 refresh 중 stale pagination 응답 방지** - 작업: 상세 댓글과 답글 pagination 요청에 generation guard를 두고, 새로고침 시 이전 요청이 현재 state를 덮지 않게 한다. - 검증: stale 응답 회귀 테스트 PASS. - 검증 기록(2026-07-08): 상세 댓글과 답글 ViewModel에 request generation guard를 추가해 새 상세/답글 로드 후 이전 page 응답이 도착해도 현재 목록을 덮지 않도록 수정했다. stale 응답 회귀 테스트를 추가하고 community targeted test PASS를 확인했다. - [x] **Task 6.3: 수정 dialog blank 입력 안내 보강** - 작업: 댓글/답글/부모 댓글 수정에서 공백 입력 시 기존 커뮤니티 정책과 동일한 내용 입력 toast를 표시한다. - 검증: source 또는 Activity 계약 테스트 PASS. - 검증 기록(2026-07-08): 댓글/답글/부모 댓글 수정 요청이 공백이면 `screen_creator_community_write_content_hint` toast 이벤트를 노출하고 legacy modify API를 호출하지 않도록 보강했다. ViewModel 회귀 테스트 PASS를 확인했다. - [x] **Task 6.4: 레이아웃 속성 직접 검증 테스트 축소** - 작업: UI layout 크기/padding/source 문자열 검증을 제거하고, 로직/상태/리소스 존재 계약 중심으로 테스트를 줄인다. - 검증: targeted unit test PASS. - 검증 기록(2026-07-08): `CreatorChannelCommunityDetailReplyUiContractTest`에서 layout 높이/padding/drawable 문자열 및 Activity source 문자열 직접 검증을 제거하고, inflate 가능한 layout과 필수 view id/문자열/AppDI/manifest 등록 확인으로 축소했다. community targeted test PASS를 확인했다. ### Phase 7: review 결과 반영 - [x] **Task 7.1: embedded 댓글의 채널 크리에이터 권한 매핑 수정** - 작업: 상세 응답의 embedded `comments`를 최초 UI state로 매핑할 때 `Content` state가 아직 없어 `isCreatorOwner`가 false로 고정되는 문제를 수정한다. - 검증: 채널 크리에이터가 타인 댓글/최신 답글에 대해 삭제 메뉴 권한을 갖는 ViewModel 회귀 테스트 PASS. - 검증 기록(2026-07-08): `CreatorChannelCommunityDetailViewModelTest`에 채널 작성자가 상세 embedded 타인 댓글의 삭제 메뉴 권한을 갖는 회귀 테스트를 추가하고, 수정 전 `AssertionError` RED 실패를 확인했다. 이후 embedded 댓글은 상세 응답의 `creatorId`, 추가 페이지 댓글은 현재 post의 `creatorId` 기준으로 `isCreatorOwner`를 명시 전달하도록 수정해 동일 테스트 PASS를 확인했다. ### Phase 8: 리뷰 결과 추가 반영 - [x] **Task 8.1: 댓글 불가 화면/댓글·답글 item UI 정리** - 작업: 댓글 불가 화면에서는 댓글 목록/입력 영역만 숨기고 별도 안내 문구를 제거한다. 댓글/답글 item에서 Figma/PRD에 없는 reaction row를 제거한다. - 검증: layout/source 계약 테스트 및 community targeted test PASS. - 검증 기록(2026-07-08): `CreatorChannelCommunityDetailReplyUiContractTest`에 댓글 불가 안내 view 제거, 댓글/답글 reaction id 제거 계약을 추가했다. `item_creator_channel_community_comment.xml`과 `item_creator_channel_community_reply.xml`에서 Figma에 없는 reaction row를 제거하고 adapter binding 참조를 정리했다. 상세 댓글 불가 화면은 댓글 header/list/input bar만 숨기도록 유지했다. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"` PASS로 확인했다. - [x] **Task 8.2: 유료 미구매 paywall 표시 수정** - 작업: 유료 미구매 게시물은 raw media URL을 노출하지 않되 Figma 중앙 lock + 가격 paywall 영역은 표시한다. - 검증: 상세 ViewModel/Activity/layout 계약 테스트 PASS. - 검증 기록(2026-07-08): `CreatorChannelCommunityPostDetailUiModel.showPaywall`을 추가하고 유료 미구매 타인 게시물에서 `imageUrl`/`audioUrl`은 계속 제거하되 `showPaywall`을 true로 노출하도록 수정했다. 상세 layout에는 `layout_creator_channel_community_detail_paywall`과 `tv_creator_channel_community_detail_paywall_price`를 추가해 이미지 컨테이너 중앙에 lock+가격 pill을 표시한다. 상세 ViewModel/UI 계약 테스트 PASS로 확인했다. - [x] **Task 8.3: 댓글/답글 상대시간 보정** - 작업: v2 `createdAtUtc` 파싱을 ISO offset/초 단위 epoch까지 지원하고, 서버·단말 시계 차이로 작성 직후 과거 시간이 표시되지 않도록 최근 시간 보정 규칙을 추가한다. 답글 화면 부모 댓글도 원본 `createdAtUtc`를 전달해 답글 목록과 같은 포맷터 기준으로 표시한다. - 검증: 상대시간 포맷터 회귀 테스트 및 상세/답글 ViewModel 테스트 PASS. - 검증 기록(2026-07-08): 기존 공통 함수 `formatUtcRelativeTimeText`를 보강해 epoch millis 기존 동작을 유지하면서 epoch seconds, ISO offset, 6자리 fraction을 파싱하도록 수정했다. ISO 문자열은 서버/단말 시계 오차를 고려해 10분 이내를 `방금전`으로 보정한다. 댓글/답글 UI model에 원본 `createdAtUtc`를 보존하고 답글 화면 `Intent`에 전달해 부모 댓글도 동일한 `UtcRelativeTimeTextFormatter`로 재포맷하도록 수정했다. `RelativeTimeFormatterTest`, 상세/답글 ViewModel 테스트 PASS로 확인했다. ### Phase 9: 댓글/답글 수정 UX 후속 반영 - [x] **Task 9.1: 타이틀/메뉴/모달 계약 정리** - 수정: `activity_creator_channel_community_detail.xml`, `activity_creator_channel_community_reply.xml`, `content_comment_option_menu.xml`, `content_comment_option_menu2.xml`, 상세/답글 Activity. - 작업: 상세/답글 titlebar의 `커뮤니티`, `답글` 문구를 제거하고, 댓글/답글 더보기 메뉴 문구를 `수정하기`, `삭제하기`로 바꾼다. v2 패키지 내부 삭제 확인은 `V2ModalDialog`를 사용한다. - 검증: layout/source 계약 테스트, `./gradlew :app:compileDebugKotlin` - 검증 기록(2026-07-09): 상세/답글 layout에서 title `TextView`를 제거하고, 댓글 메뉴 리소스는 `creator_channel_fantalk_edit`/`creator_channel_fantalk_delete`를 사용하도록 수정했다. 상세/답글 Activity의 삭제 확인은 `V2ModalDialog`로 교체하고 `AlertDialog` 사용을 제거했다. `CreatorChannelCommunityDetailReplyUiContractTest`에 title id 제거, 메뉴 문구, `V2ModalDialog` source 계약을 추가했으며 targeted community test와 `./gradlew :app:compileDebugKotlin` PASS로 확인했다. - [x] **Task 9.2: 하단 입력창 기반 수정 모드 구현** - 수정: `CreatorChannelCommunityDetailViewModel.kt`, `CreatorChannelCommunityReplyViewModel.kt`, 상세/답글 Activity/layout, 관련 테스트. - 작업: 수정 선택 시 별도 입력 Dialog 없이 하단 입력창에 기존 내용을 채우고 X 취소 버튼을 표시한다. 수정 모드의 send는 쓰기가 아니라 수정 API를 호출하며, 성공/취소 시 일반 입력 모드로 복귀한다. - 검증: 상세/답글 ViewModel 회귀 테스트, layout/source 계약 테스트, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"` - 검증 기록(2026-07-09): 상세 댓글은 `editingCommentId`/`editingOriginalComment`, 답글 화면은 `CreatorChannelCommunityReplyEditTarget`으로 수정 모드를 상태화했다. 수정 선택 시 하단 입력창에 기존 내용을 세팅하고 X 버튼을 표시하며, 수정 모드의 send는 댓글/답글/부모 댓글 수정 API를 호출한다. 성공 또는 X 취소 시 입력과 수정 target을 초기화한다. 변경 없음과 공백 입력은 기존 toast 정책을 유지했다. ViewModel 회귀 테스트와 layout/source 계약 테스트를 추가했고 targeted community test PASS로 확인했다. - [x] **Task 9.3: 후속 검증** - 실행: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`. - 검증 기록: `Verification Log`에 누적한다. - 검증 기록(2026-07-09): `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check` 실행 결과 모두 통과했다. `ktlintCheck`의 `.editorconfig disabled_rules` deprecation 경고는 기존 설정 경고로 남아 있다. ### Phase 10: 댓글/답글 더보기 메뉴 폰트 후속 반영 - [x] **Task 10.1: 더보기 메뉴 regular font 적용** - 수정/생성: `CreatorChannelCommunityMorePopup.kt`, `view_creator_channel_community_more_popup.xml`, 댓글/답글 adapter, UI 계약 테스트. - 작업: 기본 `PopupMenu` 대신 `PopupWindow` 기반 커스텀 메뉴를 사용하고, 메뉴 TextView에 `android:fontFamily="@font/regular"`를 명시한다. - 검증: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`. - 검증 기록(2026-07-09): 댓글/답글 더보기 메뉴를 `PopupMenu`에서 `CreatorChannelCommunityMorePopup`으로 교체했다. 새 `view_creator_channel_community_more_popup.xml`의 `수정하기`, `삭제하기` TextView에 `@font/regular`를 명시했고, 내 댓글/답글은 수정+삭제, 채널 작성자가 보는 타인 댓글/답글은 삭제만 노출하는 기존 권한 규칙을 유지했다. UI 계약 테스트에 popup layout font와 adapter source 계약을 추가했다. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 통과했다. ### Phase 11: 댓글/답글 입력창 키보드 후속 반영 - [x] **Task 11.1: 수정 진입/성공 시 키보드 제어** - 수정: `CreatorChannelCommunityDetailActivity.kt`, `CreatorChannelCommunityReplyActivity.kt`, UI 계약 테스트. - 작업: `수정하기` 터치 후 하단 입력창 수정 모드로 전환될 때 입력창에 focus를 주고 키보드를 즉시 올린다. 댓글/답글 작성 또는 수정 API 성공 이벤트 수신 시 키보드를 내리고 focus를 해제한다. - 검증: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`. - 검증 기록(2026-07-09): 상세/답글 Activity에 `showSoftInput`/`hideSoftInputFromWindow` 기반 키보드 제어를 추가했다. 수정 target이 새로 설정되면 입력창 focus 후 키보드를 올리고, 댓글 작성/수정 및 답글 작성/수정/부모 댓글 수정 성공 이벤트에서 키보드를 내리도록 연결했다. UI 계약 테스트에 IME 제어 source 계약을 추가했다. `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 통과했다. ### Phase 12: 커뮤니티 상세 UI border 후속 반영 - [x] **Task 12.1: 상세 상단 게시글 배경과 댓글 경계선 수정** - 수정: `app/src/main/res/layout/activity_creator_channel_community_detail.xml`, `app/src/main/res/layout/item_creator_channel_community_comment.xml`, `CreatorChannelCommunityCommentAdapter.kt` - 작업: 상세 게시글 컨테이너의 `bg_feed_card` rounded 배경을 제거하고, 게시글과 댓글 헤더 사이 1dp border를 추가한다. 댓글 item 사이에는 1dp border를 표시하되 마지막 댓글 하단 border는 숨긴다. - 검증: `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityDetailReplyUiContractTest"`, `./gradlew :app:ktlintCheck`, `git diff --check` - 검증 기록(2026-07-12): 상세 게시글 컨테이너의 `bg_feed_card` 배경을 제거해 목록형 rounded card 배경이 상세 상단 본문에는 적용되지 않도록 했다. 게시글과 댓글 헤더 사이에는 `gray_800` 1dp divider를 추가하고 댓글 가능 상태에서만 노출되도록 Activity binding을 연결했다. 댓글 item 하단 divider에는 id를 부여하고 adapter에서 마지막 댓글의 divider를 숨겨 댓글 사이 border로만 보이게 했다. `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityDetailReplyUiContractTest"`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 통과했다. `ktlintCheck`의 `.editorconfig disabled_rules` deprecation 경고는 기존 설정 경고로 남아 있다. ### Phase 13: 커뮤니티 상세 오디오/구매 후속 반영 - [x] **Task 13.1: 상세 오디오 중앙 버튼과 구매 회귀 테스트 추가** - 수정: `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/community/CreatorChannelCommunityDetailViewModelTest.kt`, `CreatorChannelCommunityDetailReplyUiContractTest.kt` - 작업: 상세 layout에 이미지 중앙 play/pause 버튼이 있고, Activity가 `PurchaseCommunityPostDialog`와 `purchaseCommunityPost`를 연결하며, ViewModel이 구매 성공 후 상세를 재조회하는 계약을 RED로 고정한다. - 검증: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityDetailViewModelTest"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityDetailReplyUiContractTest"` - 검증 기록(2026-07-12): 상세 layout의 중앙 오디오 버튼 id, legacy 구매 dialog 연결, ViewModel 구매 성공 후 상세 재조회 계약을 테스트에 추가했다. 최초 병렬 Gradle 실행은 120초/300초 timeout 및 병렬 resource packaging 충돌성 `NoSuchFileException`으로 완료 결과를 얻지 못했으나, 구현 후 순차 재실행에서 동일 테스트들이 PASS했다. - [x] **Task 13.2: 상세 오디오 중앙 버튼과 구매 흐름 구현** - 수정: `app/src/main/res/layout/activity_creator_channel_community_detail.xml`, `CreatorChannelCommunityDetailActivity.kt`, `CreatorChannelCommunityDetailViewModel.kt` - 작업: `item_creator_community_all.xml`의 `iv_play_or_pause`처럼 상세 이미지 중앙 버튼을 추가하고, 재생 상태에 따라 play/pause drawable을 갱신한다. 상세 paywall 가격 클릭 시 기존 구매 dialog를 띄우고 구매 성공 후 상세를 다시 로드한다. - 검증: targeted test PASS, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin` - 검증 기록(2026-07-12): `activity_creator_channel_community_detail.xml`의 이미지 컨테이너 중앙에 `iv_creator_channel_community_detail_play_or_pause`를 추가하고 `btn_audio_content_play`/`btn_audio_content_pause`를 사용하도록 연결했다. `CreatorChannelCommunityDetailActivity`는 이미지+오디오 게시물에서 중앙 버튼을 표시하고, 이미지 없는 오디오 게시물은 기존 텍스트 오디오 버튼을 유지한다. paywall 영역 클릭 시 기존 `PurchaseCommunityPostDialog`를 띄우고 확인 시 `CreatorChannelCommunityDetailViewModel.purchaseCommunityPost()`를 호출한다. ViewModel은 기존 `CreatorCommunityRepository.purchaseCommunityPost`를 호출한 뒤 성공 시 상세를 다시 로드한다. `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin` PASS로 확인했다. - [x] **Task 13.3: 후속 검증** - 실행: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check` - 검증 기록: `Verification Log`에 누적한다. - 검증 기록(2026-07-12): `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityDetailViewModelTest"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.CreatorChannelCommunityDetailReplyUiContractTest"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 통과했다. `ktlintCheck`의 `.editorconfig disabled_rules` deprecation 경고와 Gradle deprecated feature 경고는 기존 설정 경고로 남아 있다. --- ### Phase 14: 유료 미구매 상세 반응/댓글 숨김 후속 - [x] **Task 14.1: 상세 유료 미구매 게시글 reaction/comment 숨김** - 대상 파일: - `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/detail/CreatorChannelCommunityDetailViewModel.kt` - `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/detail/CreatorChannelCommunityDetailActivity.kt` - `app/src/main/res/layout/activity_creator_channel_community_detail.xml` - `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/community/CreatorChannelCommunityDetailViewModelTest.kt` - 작업: `price > 0 && !existOrdered && creatorId != SharedPreferenceManager.userId` 잠금 게시글에서는 상세의 reaction 현황, 댓글 목록, 댓글 헤더, 댓글 입력을 숨긴다. - 검증 기록: - 2026-07-12: RED로 `CreatorChannelCommunityDetailViewModelTest.유료 미구매 게시물은 작성자가 아니면 reaction 현황과 댓글을 숨긴다`를 추가했고, production 변경 전 `showReaction` 미구현 컴파일 실패를 확인했다. 이후 상세 UI 모델/상태와 Activity binding에 잠금 조건을 반영해 focused 테스트 GREEN을 확인했다. ## Verification Log - 2026-07-12: Phase 14 유료 미구매 상세 게시글 reaction/comment 숨김 변경을 완료했다. RED는 `CreatorChannelCommunityDetailViewModelTest.유료 미구매 게시물은 작성자가 아니면 reaction 현황과 댓글을 숨긴다`의 `showReaction` 미구현 컴파일 실패로 확인했고, 구현 후 focused 테스트, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:mergeDebugResources :app:compileDebugKotlin :app:ktlintCheck`가 모두 `BUILD SUCCESSFUL`로 PASS했다. 실제 화면 직접 조작은 Activity가 내부 진입 경로와 데이터 계정에 의존해 이번 검증에서는 단위/리소스/컴파일/스타일 검증으로 대체했다. - 구현 전 문서 작성 단계에서는 Gradle 검증을 실행하지 않았다. - 2026-07-12: 커뮤니티 상세 오디오 중앙 버튼 및 유료 게시글 구매 후속 변경을 반영했다. 상세 ViewModel 구매 회귀 테스트, 상세 UI 계약 테스트, 커뮤니티 targeted 테스트, 리소스 병합, Kotlin 컴파일, ktlint, diff whitespace 검증이 모두 통과했다. 최초 병렬 Gradle 실행 중 resource packaging incremental output 충돌성 오류가 한 번 발생했으나 순차 재실행에서 재현되지 않았다. - 2026-07-08: 추가 review findings 반영 범위를 확정했다. 상세/답글 변경 결과를 상위 커뮤니티 목록과 상세 댓글/답글 카운트에 반영하고, 좋아요 API의 `success=false` 응답에서 낙관적 상태를 롤백하며, 댓글/답글 입력창을 3줄까지 자동 확장되도록 고정 높이를 제거하고, 수정 내용이 없을 때 기존 `audio_content_comment_no_change` toast를 표시하도록 보강한다. - 2026-07-08: Phase 2.3/3.2 UI 구현 전 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`를 실행해 신규 activity/layout/item/source가 없어 `compileDebugUnitTestKotlin` RED 실패를 확인했다. - 2026-07-08: Phase 2.3/3.2 UI 구현 후 동일 targeted 테스트를 재실행해 48개 테스트 PASS를 확인했다. Robolectric inflate로 상세/답글 layout의 title back/content/input bar 및 item layout 계약을 확인했고, source 검사로 AppDI/manifest/ViewModel binding/popup menu/comment hidden/newIntent 계약을 확인했다. - 2026-07-08: review-work 차단 이슈 대응으로 Phase 5 테스트를 보강했다. RED는 `CreatorChannelCommunityDetailViewModel.modifyComment/deleteComment` 미구현 컴파일 오류로 확인했고, GREEN은 community targeted 테스트와 CreatorChannelActivity source 테스트, resources merge, Kotlin compile, ktlint, diff whitespace 검증 PASS로 확인했다. - 2026-07-08: 최종 확인으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`를 재실행해 모두 `BUILD SUCCESSFUL`을 확인했다. `git diff --check`는 출력 없이 통과했다. - 2026-07-08: review-work 재검증에서 발견된 추가 차단 이슈를 반영했다. 상세 댓글 추가 로딩은 실제 스크롤 컨테이너인 `NestedScrollView` 기준으로 감지하도록 수정하고, 유료 미구매 잠금 게시글은 작성자가 아닌 경우 이미지/오디오 URL을 UI model에서 제거해 raw media URL 노출을 막았다. 댓글/답글 더보기는 레거시와 동일하게 작성자 또는 채널 크리에이터에게만 노출하며, 답글 화면 부모 댓글에도 수정/삭제 메뉴를 연결했다. PRD의 상세 응답 `comments` 표현은 별도 댓글 endpoint 첫 페이지 조회 계약으로 정리했다. - 2026-07-08: 추가 차단 이슈 수정 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`를 재실행해 모두 `BUILD SUCCESSFUL`을 확인했다. `git diff --check`는 출력 없이 통과했다. - 2026-07-08: 부모 댓글 수정/삭제 후 답글 화면의 부모 댓글 영역과 상세 댓글 목록이 stale 상태로 남을 수 있다는 review-work 지적을 반영했다. 부모 댓글 수정 성공 시 답글 ViewModel의 `parentComment` 상태를 즉시 갱신하고, 부모 댓글 변경/삭제 이벤트를 Activity result로 상세 화면에 전달해 상세를 재조회하도록 수정했다. 삭제 성공 시 답글 화면은 `RESULT_OK` 반환 후 종료한다. 회귀 테스트로 부모 댓글 수정 상태 갱신, 삭제 이벤트, ActivityResult source 계약을 추가하고 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"` PASS를 확인했다. - 2026-07-08: 추가 review findings 4건을 반영했다. 상세 진입은 `ActivityResultLauncher`로 변경해 상세의 댓글/좋아요/수정/삭제 및 답글 화면 변경 결과가 상위 커뮤니티 목록 refresh로 전파되도록 했고, 좋아요 API의 `success=false` 응답은 낙관적 상태를 이전 좋아요 상태/개수로 롤백하도록 수정했다. 댓글/답글 작성·수정·삭제 후에는 상세/답글을 서버 재조회해 댓글·답글 count를 동기화하고, 댓글/답글 입력창은 고정 높이를 제거해 3줄까지 자동 확장되도록 `wrap_content`/`minHeight=40dp`/`maxLines=3`/vertical scrollbar 계약을 맞췄다. 수정 내용이 원문과 같으면 `audio_content_comment_no_change` toast 후 API 호출을 막도록 상세/답글 수정 dialog를 보강했다. 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`가 모두 `BUILD SUCCESSFUL`임을 확인했고, `git diff --check`는 출력 없이 통과했다. 최초 병렬 Gradle 실행 중 KSP 증분 캐시 손상/동시 접근 오류가 발생했으나 `app/build/kspCaches/debug` 생성 캐시 제거 후 순차 재실행으로 통과했다. - 2026-07-08: review-work 재검증에서 답글 화면 변경 결과가 상세 화면 재조회까지만 반영되고 상위 `CreatorChannelActivity` 목록 refresh로 재전파되지 않는 차단 이슈가 확인되어 수정했다. `CreatorChannelCommunityDetailActivity`의 `replyLauncher`에서 답글 화면 `RESULT_OK` 수신 시 `setResult(Activity.RESULT_OK)`를 먼저 호출한 뒤 `loadDetail(postId)`를 수행하도록 변경했고, source contract test가 이 순서를 검증하도록 보강했다. 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`가 모두 `BUILD SUCCESSFUL`임을 확인했고, `git diff --check`는 출력 없이 통과했다. - 2026-07-08: 추가 review findings 3건을 반영했다. 커뮤니티 게시물 상세 진입 전 `SharedPreferenceManager.token.isBlank()`이면 기존 `showLoginActivity()`로 이동하고 상세 Activity launch를 중단하도록 보강했다. 댓글/답글 작성·수정·삭제 실패 시 v2 `CreatorChannelEvent` 기반 toast 이벤트를 노출해 API 메시지 또는 `common_error_unknown`을 표시하도록 상세/답글 ViewModel과 Activity를 수정했다. 상세 댓글 목록 상단에는 `댓글 {commentCount}` 헤더를 추가하고, 답글 화면 부모 댓글에서는 reply/heart count reaction row와 latest reply block을 숨겨 Figma/PRD 정적 UI와 맞췄다. 회귀 테스트로 로그인 gate source 계약, 실패 toast 이벤트 consume 계약, 댓글 헤더/부모 reaction row source·layout 계약을 추가했으며 targeted unit test는 `BUILD SUCCESSFUL`을 확인했다. - 2026-07-08: 리뷰 결과 3건과 서버 응답 계약 불일치를 반영했다. 상세 응답 내부 `comments`를 최초 댓글 목록으로 사용하도록 바꾸고, 댓글/최신 답글/답글 응답 DTO를 서버 계약의 `writer*`, `content`, `commentId` 필드명에 맞췄다. 상세 댓글/답글 pagination에는 generation guard를 추가해 새로고침 후 stale page 응답이 현재 목록을 덮지 않게 했고, 댓글/답글/부모 댓글 수정 blank 입력은 `screen_creator_community_write_content_hint` toast 후 API를 호출하지 않도록 했다. UI 계약 테스트는 layout 속성/source 문자열 직접 검증을 제거해 필수 view/resource 등록 중심으로 축소했다. 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`가 모두 `BUILD SUCCESSFUL`임을 확인했다. `git diff --check`, `git diff HEAD --check`는 출력 없이 통과했다. `:app:mergeDebugResources`는 최초 sandbox에서 `~/.gradle` lock 파일 권한 문제로 실패했으나, 동일 명령을 권한 상승 재실행해 통과했다. - 2026-07-08: 코드 리뷰에서 발견된 채널 크리에이터 권한 매핑 문제를 반영했다. 상세 응답 embedded `comments`를 최초 UI state로 매핑할 때 아직 `Content` state가 없어 `isCreatorOwner`가 false로 고정되던 문제를, 상세 응답의 `creatorId` 또는 현재 post의 `creatorId`를 기준으로 명시 전달하도록 수정했다. 회귀 테스트는 수정 전 RED 실패 후 수정 후 PASS를 확인했다. 최종 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`가 모두 `BUILD SUCCESSFUL`임을 확인했다. `git diff --check`, `git diff HEAD --check`는 출력 없이 통과했다. `:app:mergeDebugResources`는 최초 sandbox에서 `~/.gradle` lock 파일 권한 문제로 실패했으나, 동일 명령을 권한 상승 재실행해 통과했다. - 2026-07-08: 리뷰 결과 추가 반영을 완료했다. 댓글 불가 화면은 댓글 목록/header/input bar만 숨기고 별도 안내 문구 view를 제거했다. 댓글/답글 item에서 Figma에 없는 reaction row를 제거했다. 유료 미구매 상세는 raw image/audio URL을 UI model에서 계속 제거하면서 `showPaywall`로 중앙 lock+가격 paywall을 표시하도록 수정했다. 상대시간은 기존 공통 `formatUtcRelativeTimeText`를 보강해 epoch seconds, ISO offset, 6자리 fraction, 작성 직후 서버/단말 시계 차이를 처리하고, 답글 화면 부모 댓글에는 원본 `createdAtUtc`를 전달해 동일 포맷터 기준으로 표시되게 했다. 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.common.RelativeTimeFormatterTest"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelActivitySourceTest"`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`가 모두 `BUILD SUCCESSFUL`임을 확인했다. `git diff --check`, `git diff HEAD --check`는 출력 없이 통과했다. `:app:mergeDebugResources`는 최초 sandbox에서 `~/.gradle` lock 파일 권한 문제로 실패했으나, 동일 명령을 권한 상승 재실행해 통과했다. - 2026-07-09: 사용자 후속 요청 4건을 반영했다. 상세/답글 titlebar의 `커뮤니티`, `답글` 문구를 제거했고, 댓글/답글 더보기 메뉴 문구를 `수정하기`, `삭제하기`로 변경했다. v2 패키지 내부 삭제 확인은 `V2ModalDialog`로 교체했으며, 수정은 Dialog 없이 하단 입력창 수정 모드로 전환되도록 구현했다. 수정 모드에서는 send 버튼으로 수정 API를 호출하고, send 버튼 오른쪽 X 버튼으로 수정 취소가 가능하다. 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.community.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check`가 모두 통과했다. `ktlintCheck`의 `.editorconfig disabled_rules` deprecation 경고는 기존 설정 경고로 남아 있다. - 2026-07-09: 댓글/답글 더보기 메뉴 font 후속 요청을 반영했다. `PopupMenu`는 메뉴 item font를 직접 지정하기 어려워, 댓글/답글 더보기만 `PopupWindow` 기반 `CreatorChannelCommunityMorePopup`으로 교체하고 메뉴 TextView에 `android:fontFamily="@font/regular"`를 명시했다. 검증 명령은 Phase 10.1 기록에 누적한다. - 2026-07-09: 수정하기 터치 시 키보드가 바로 올라오고, 입력/수정 API success 후 키보드가 내려가야 한다는 후속 요청을 반영했다. 상세/답글 Activity에서 수정 모드 진입 시 입력창 focus와 IME show를 수행하고, 작성/수정 성공 이벤트에서 IME hide와 focus clear를 수행한다. 검증 명령은 Phase 11.1 기록에 누적한다. - 2026-07-12: 커뮤니티 상세 상단 게시글 영역의 rounded card 배경 제거와 게시글-댓글/댓글 사이 1dp border 후속 요청을 반영했다. 검증 명령은 Phase 12.1 기록에 누적한다.