Files
voiceon-character-admin/docs/20260806_커뮤니티댓글답글/plan-task.md

16 KiB

커뮤니티 댓글 직접 답글 구현 계획

문서 항목 내용
상태 구현 완료
작성일 2026-08-06
요구사항 기준 prd.md
API 기준 api-contract.md
현재 Phase Phase 1 완료
현재 활성 Goal 없음

목표

활성 커뮤니티 게시글의 답글 0개 원댓글에서도 기존 답글 form을 열어 첫 답글과 여러 직접 답글을 작성할 수 있게 한다.

현재 상태

Phase 상태 완료 Task 활성/다음 Goal 차단 또는 남은 조건
1 완료 3/3 없음 완료
  • Community 답글 GET·POST, form, 여러 직접 답글 조회·작성·재조회 흐름은 이미 구현돼 있다.
  • 답글이 하나 이상인 Community root에는 답글 보기와 추가 작성 form이 제공된다.
  • replyCount === 0인 Community root에는 첫 답글 작성 진입만 없다.
  • P1-T1 구현과 test는 완료됐고, P1-R1에서 E2E fixture 검증 결함 후보를 실제 mock 실행 경로와 대조해 오탐으로 판정했다.

범위의 포함·제외

포함

  • 활성 Community root의 replyCount === 0일 때 답글 작성 버튼 표시
  • 기존 답글 영역, form, GET·POST와 mutation 상태 재사용
  • 같은 원댓글에 첫 답글과 여러 직접 답글 작성
  • Community 첫 답글과 Audio·비활성·reply row 경계 회귀 test
  • 기존 Comments Chromium mock E2E와 정적 검증

제외

  • 새 endpoint, DTO, component, state library 또는 dependency
  • form 상시 노출, reply-of-reply, payload 정책 변경
  • 기존 답글 수정·삭제·pagination 리팩터링
  • Audio 전용 languageCode의 Community payload 추가
  • optimistic update와 답글 전체 선조회

기술적 제약

  • React·TypeScript strict, Vitest·React Testing Library와 기존 Playwright 구성을 사용한다.
  • api-contract.md의 기존 GET·POST만 사용한다.
  • CommentThread, CommentItem, CommentForm의 현재 책임 경계를 유지한다.
  • CommentItem의 기존 replyActionLabel, CommentThread.toggleReplies()와 reply state를 재사용한다.
  • 공통 조건 한 곳에서 Audio와 Community의 첫 답글 진입을 일치시키며 target별 분기를 추가하지 않는다.
  • RED → GREEN → REFACTOR 순서와 최소 변경을 지킨다.

Phase 1. 커뮤니티 직접 답글 진입 구현·검증

Phase 결과: 관리자가 활성 Community의 답글 0개 원댓글에서 첫 답글을 작성하고 같은 원댓글에 여러 직접 답글을 추가하며, 기존 Audio·읽기 전용·2단계 경계가 유지된다.

선행조건: CCR-001~006과 기존 Community 댓글 GET·POST 계약 확정.

Phase 완료 조건: P1-T1, P1-GATE 완료와 Progress 기록.

Task 1.1 커뮤니티 첫 답글 진입

Goal 실행 P1-T1: Community의 답글 0개 원댓글에 기존 답글 영역을 여는 답글 작성 action을 추가하고 직접 답글 작성 흐름을 검증한다.

  • 시작 조건: prd.mdCCR-001~006, api-contract.md.
  • 완료 증거: TDD 체크박스, focused·회귀·E2E·정적 검증과 Progress 기록.
  • 범위 밖: API·mock·schema 변경, 새 UI 구조, 관련 없는 Comments 리팩터링.

Files:

  • Modify: src/features/comments/components/CommentThread.tsx
  • Modify: src/features/comments/tests/comment-thread.test.tsx
  • Modify: tests/e2e/comments.spec.ts
  • Test: src/features/comments/tests/comment-thread.test.tsx, tests/e2e/comments.spec.ts

Interfaces:

  • Consumes: CommentRecord.replyCount, canMutate, expandedRootIds, toggleReplies(), CommentForm, Community createComment() overload.
  • Produces: 활성 Audio·Community 원댓글에 공통 적용되는 첫 답글 action 노출 조건.

TDD 절차:

  • RED: 실패 테스트 작성/실패 확인comment-thread.test.tsx에 Community replyCount=0 root의 답글 작성 노출, 클릭 후 form, parentId POST와 languageCode 미전송을 검증하고 npm run test:run -- src/features/comments/tests/comment-thread.test.tsx가 버튼 부재로 실패하는지 확인한다.
  • GREEN: 최소 구현/통과 확인CommentThread.tsx의 기존 optional action label 조건에서 Audio 전용 제한만 제거하고 같은 명령이 exit 0인지 확인한다.
  • REFACTOR: 정리/회귀 확인 — 추가 helper·component 없이 조건을 읽기 쉬운 최소 표현으로 유지하고 focused test와 npm run test:run -- src/features/comments가 모두 exit 0인지 확인한다.
  • 기존 Community mock E2E에 답글 0개 root의 첫 답글 작성과 같은 root에 추가 직접 답글 작성 journey를 검증한다.
  • 검증 결과를 Progress에 기록한다.

검증 기준:

  • 실행 명령: npm run test:run -- src/features/comments/tests/comment-thread.test.tsx; npm run test:run -- src/features/comments; npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium; npm run typecheck; npm run lint.
  • 기대 결과: 모든 명령 exit 0, Community 첫 답글 POST 1회 이상, parentId는 원댓글 ID, Community body의 languageCode 0건, reply row의 답글 action 0건, 기존 Audio·Comments 회귀 실패 0건.
  • 수동 확인: 활성 Community Sheet에서 답글 0개 root의 답글 작성 → form 노출 → 첫 답글 등록 → 같은 root 추가 답글 등록을 확인한다. 비활성 workspace와 reply row에는 작성 진입이 없어야 한다.

완료 조건

  • P1-T1의 모든 TDD·검증 체크박스가 완료됐다.
  • CCR-001~006이 구현 또는 검증 증거에 연결됐다.
  • API·mock·schema와 범위 밖 파일 변경이 없다.

Task 1.R1 Community E2E fixture 검증

Goal 실행 P1-R1: CCR-REV-P1-001의 E2E fixture 분류 오류 후보가 실제 mock E2E 실행 경로에 영향을 주는지 검증하고 판정한다.

  • 시작 조건: P1-T1 완료, CCR-REV-P1-001 확정.
  • 완료 증거: 실제 mock 요청 소유권 확인, 후보를 구분하는 E2E assertion, Chromium·Comments 회귀·정적 검증과 Progress 기록.
  • 범위 밖: 애플리케이션 mock handler·store, API·schema, production 댓글 동작 변경.

Files:

  • Modify: tests/e2e/comments.spec.ts
  • Test: tests/e2e/comments.spec.ts

TDD 예외 사유: 리뷰 후보를 구분하는 assertion이 기존 mock E2E에서도 통과해 production 또는 fixture 수정이 필요하지 않은 오탐으로 판정됐다. 실패하는 구현 변경이 없으므로 RED → GREEN 대신 실제 요청 소유권과 기존 동작을 대체 검증했다.

  • root 2102의 초기 reply region에 root 댓글이 없고, 첫·두 번째 답글이 region에 표시되며 중첩 action이 없는 assertion을 추가했다.
  • 기존 comments-test-support.ts를 유지한 상태에서 Chromium E2E 3/3 통과를 두 번 확인했다.
  • VITE_API_MODE=mock의 Browser MSW Service Worker가 mock 요청을 처리하며 page.route fixture 후보가 실제 실행 경로를 소유하지 않음을 확인했다.
  • fixture 변경을 폐기하고 Comments 회귀·typecheck·lint·git diff --check를 통과했다.
  • 검증 결과와 CCR-REV-P1-001 오탐 판정을 Progress에 기록했다.

검증 기준:

  • 실행 명령: npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium; npm run test:run -- src/features/comments; npm run typecheck; npm run lint; git diff --check.
  • 기대 결과: 기존 fixture를 변경하지 않고 모든 명령 exit 0, Chromium 3/3, 첫·추가 답글이 root 2102 region에만 표시된다.
  • 수동 확인: 기존 P1-GATE의 Community 첫·추가 답글 browser QA 결과와 mock E2E의 동일 동작을 대조한다.

검증 방법

Phase 1 Gate

Goal 실행 P1-GATE: 커뮤니티 첫·추가 직접 답글 journey와 Comments 공통 경계를 최종 판정한다.

  • 시작 조건: P1-T1 완료.
  • 완료 증거: 아래 명령·수동 확인 통과와 Progress 기록.
  • 범위 밖: test 완화, timeout 상향과 관련 없는 수정.

실행 명령:

npm run test:run -- src/features/comments
npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium
npm run typecheck
npm run lint
git diff --check

기대 결과: 모든 명령 exit 0, CCR-001~006 위반 0건.

수동 확인: 활성·비활성 Community와 활성 Audio에서 action 노출 경계를 대조한다. Community Sheet를 1280px·320px와 200% zoom에서 열어 수평 overflow 없이 첫·추가 답글을 작성하고 keyboard-only로 form에 진입한다.

실행 순서와 의존성

  1. P1-T1 RED
  2. P1-T1 GREEN
  3. P1-T1 REFACTOR·회귀
  4. P1-GATE
  • 동시에 하나의 미완료 goal만 운용한다.
  • 사용자가 goal 실행을 요청하기 전에는 goal을 생성하지 않는다.

변경 금지 항목

  • 기존 OpenAPI, API client, request schema, mock handler·store 변경
  • 새 dependency, state library, component 또는 speculative abstraction
  • 답글의 답글, optimistic update와 form 상시 노출
  • Audio payload와 기존 수정·삭제·pagination 동작 변경
  • 실패 test 삭제·skip, timeout 상향으로 Gate 통과
  • 기존 Progress와 결정 기록 삭제·덮어쓰기

의사결정 및 중단 규칙

  • replyCount === 0, canMutate === true인 Audio·Community 원댓글에만 답글 작성을 표시한다.
  • replyCount > 0 또는 펼친 원댓글은 기존 답글 보기 label을 유지한다.
  • reply row에는 onShowReplies를 전달하지 않으며 3단계 작성 경로를 만들지 않는다.
  • API 응답이나 오류가 api-contract.md와 다르면 추정 수정하지 않고 외부 의존으로 기록한다.
  • 범위가 바뀌면 코드보다 PRD Decision Log와 이 계획을 먼저 갱신한다.

Progress

2026-08-06 요구사항·설계

  • 무엇을: 활성 Community 원댓글의 첫 답글 진입, 여러 직접 답글과 2단계 제한을 요구사항·API 재사용 계약·단일 구현 Task로 정리했다.
  • 왜: Community 답글 조회·작성 흐름은 이미 있으나 replyCount === 0이면 진입 action이 없어 첫 답글만 작성할 수 없다.
  • 어떻게: 선행 Audio 답글 문서, 프로젝트 OpenAPI, CommentThread, request schema, mock handler·store, unit·E2E를 대조했다. 기존 공통 흐름을 재사용할 수 있어 새 API·컴포넌트·mock을 계획에서 제외했다. 애플리케이션 코드와 test는 변경하지 않았다.

2026-08-06 P1-T1 커뮤니티 첫 답글 진입

  • 무엇을: 활성 Community의 replyCount=0 원댓글에도 기존 답글 작성 action을 노출하고, 같은 원댓글에 첫 번째와 두 번째 직접 답글을 작성하는 단위·Chromium E2E를 추가했다. reply row의 중첩 답글 action 부재와 Community payload의 languageCode 미전송도 검증했다.
  • 왜: 기존 공통 GET·POST·form·재조회 흐름은 완성돼 있었지만 action label 조건이 Audio target만 허용해 Community 첫 답글 진입이 막혀 있었다.
  • 어떻게: RED에서 npm run test:run -- src/features/comments/tests/comment-thread.test.tsx를 실행해 AI 루트 댓글 답글 작성 버튼 부재로 1 failed, 7 passed를 확인했다. GREEN에서 CommentThread.tsx의 Audio 전용 조건만 제거한 뒤 focused test 8/8을 통과했다. REFACTOR·회귀로 npm run test:run -- src/features/comments15/15, npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium3/3, npm run typechecknpm run lint는 exit 0이었다. API·schema·mock·dependency는 변경하지 않았다.

2026-08-06 P1-R1 E2E fixture 후보 판정

  • 무엇을: CCR-REV-P1-001이 지적한 단일 replyRootId fixture가 mock E2E의 root 2102 답글을 오분류하는지 검증했다.
  • 왜: 코드만 보면 comments-test-support.ts가 root 2101만 replies로 처리하지만, 실제 mock E2E가 이 fixture를 사용하는지 확인하지 않으면 오탐 수정으로 범위를 확장할 수 있다.
  • 어떻게: 기존 fixture를 유지한 상태에서 2102 초기 reply region에 root 댓글 0건, 첫·두 번째 답글 표시, dialog 내 각 1건, 중첩 action 0건을 추가하고 Chromium E2E 3/3 통과를 두 번 확인했다. playwright.config.tsVITE_API_MODE=mocksrc/shared/mocks/browser.tssetupWorker(...)를 대조해 Browser MSW가 Service Worker에서 요청을 처리하며 page.route가 해당 요청을 소유하지 않음을 확인했다. fixture 변경은 폐기했고 CCR-REV-P1-001을 오탐으로 판정했다.

2026-08-06 P1-GATE Phase 1 최종 검증

  • 무엇을: Community 첫·추가 직접 답글, 2단계·권한 경계, Comments 회귀와 반응형·keyboard·CJK 품질을 최종 판정했다.
  • 왜: 코드와 자동 test 통과만으로는 실제 Sheet의 keyboard 진입, 320px·200% zoom, 한국어 줄바꿈과 reviewer 차단 해소를 증명할 수 없다.
  • 어떻게: npm run test:run -- src/features/comments15/15, npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium3/3, npm run typecheck, npm run lint, npm run build:dev, git diff --check는 exit 0이었다. 실제 Chromium에서 첫·두 번째 답글, input 초기화, 중첩 action 0건, keyboard-only 진입과 1280px·320px·200% zoom의 수평 overflow 0건을 확인했다. 독립 goal·코드 품질·보안·컨텍스트·기능·visual/CJK 리뷰는 최종 PASS였고 Phase 1 리뷰에 근거를 기록했다.

Decision Log

날짜 결정 근거 영향
2026-08-06 Audio와 동일한 답글 작성 진입을 활성 Community 원댓글에도 적용한다. 사용자 요청 CCR-001~003, P1-T1
2026-08-06 한 원댓글에 여러 직접 답글을 허용하고 reply-of-reply는 제외한다. 사용자 요청 CCR-004~005, P1-T1, P1-GATE
2026-08-06 기존 공통 UI와 Community GET·POST를 재사용하고 API·mock·schema는 변경하지 않는다. OpenAPI와 코드 확인 CCR-002~006, P1-T1
2026-08-06 구현은 공통 action 조건의 Audio 전용 제한 제거와 기존 test 보강으로 제한한다. CommentThread 흐름 확인과 최소 변경 원칙 P1-T1 Files·Interfaces
2026-08-06 E2E 전용 route fixture가 특정 root만 replies로 처리하는 결함을 P1-R1에서 수정한다. 최종 코드 품질·컨텍스트 리뷰에서 2102 답글이 roots에 저장돼 E2E가 오탐 통과함을 확인 CCR-REV-P1-001, P1-R1, P1-GATE
2026-08-06 정정: CCR-REV-P1-001은 mock mode에서 Browser MSW가 요청을 소유해 E2E route fixture 분기가 실행되지 않으므로 오탐이다. fixture를 변경하지 않는다. 기존 fixture 상태에서 2102 빈 reply·첫·추가 답글 assertion과 Chromium 3/3 통과, VITE_API_MODE=mock·setupWorker(...) 확인 CCR-REV-P1-001, P1-R1, P1-GATE

발견된 문제

  • 수정 완료: 답글 0개 Community root의 첫 답글 작성 진입을 P1-T1에서 구현하고 P1-GATE에서 검증했다.
  • 확정: E2E 전용 fixture가 replyRootId 하나만 replies로 분류해 다른 root의 직접 답글을 roots에 저장한다. (CCR-REV-P1-001, P1-R1에서 수정 예정)
  • 오탐: CCR-REV-P1-001 — mock mode에서는 Browser MSW가 요청을 처리해 해당 E2E route fixture 분기가 실행되지 않으며, 기존 fixture 상태에서 root 2102의 빈 reply·첫·추가 답글 journey가 통과한다.
  • 외부 차단: 없음.

최종 보고 형식

  • 완료 Goal ID
  • 변경한 파일과 최소 구현 내용
  • RED·GREEN·REFACTOR 및 Gate 명령과 실제 결과
  • 실행하지 못한 수동·server 검증과 이유
  • 남은 위험 또는 열린 질문