Files
voiceon-character-admin/docs/20260725_AI캐릭터관리자웹/reviews/review-phase-3-20260729.md

9.6 KiB

Phase 3 코드 리뷰·QA — 2026-07-29

1. 리뷰 정보

항목 내용
리뷰 대상 Phase 3 / Character workspace
기준 commit 또는 working tree dd30e36323543e8f60e9983326503653e8001f12; 리뷰 시작 시 tracked diff 36개, 전체 변경 169개
리뷰 일자 2026-07-29
리뷰어 Codex
기준 문서 prd.md, api-contract.openapi.json, plan-task.md
리뷰 상태 판정 완료

2. 리뷰 목적과 범위

목적

  • CHAR-001~018, Character form/file 요구와 P3-T1~P3-GATE, P10-T1 결과를 대조한다.

포함 범위

  • 코드: src/features/characters, Character route와 workspace 조합
  • 테스트: Character unit/integration와 mock E2E
  • 문서: Character 요구사항, OpenAPI Character request/schema, Phase 3 체크
  • 수동 검증: form control inventory와 payload 정적 대조

제외 범위

  • 공통 crop 계산은 Phase 1, cross-domain inactive policy와 field-error 접근성은 Phase 9에서 판정

3. 판정 기준

심각도는 Blocker/High/Medium/Low, 상태는 확정/오탐/보류/수정 완료를 사용했다.

4. 검토한 근거

문서와 코드

  • 요구사항: CHAR-003, CHAR-013, CHAR-018, Character 생성·수정 폼, FILE-002, PRD 10.5
  • 계약: CharacterCreateRequest, CharacterUpdateRequest
  • 코드: CharacterCreatePage.tsx:37, CharacterCreatePage.tsx:52, CharacterCreatePage.tsx:75, CharacterCreatePage.tsx:88, CharacterEditPage.tsx:53, CharacterEditPage.tsx:68, CharacterEditPage.tsx:93, CharacterEditPage.tsx:106
  • 테스트: CharacterCreatePage.test.tsx, CharacterEditPage.test.tsx, character-api.test.ts

실행 환경

OS: macOS 26.0
Node: v24.12.0
npm: 11.7.0
API mode: unit injected client/MSW

실행한 검증

명령 결과 핵심 증거
npm run test:run -- src/features/characters 성공 6 files / 23 tests passed
OpenAPI property 출력 성공 optional scalar 10개와 반복 배열 8개 확인
form control/payload 정적 대조 실패 재현 생성·수정 UI는 기본 4개 text/file + 원작 선택만 제공

5. 발견 사항 요약

ID 심각도 상태 제목 소유 Task 후속 goal
REV-P3-001 High 수정 완료 Character form이 OpenAPI optional scalar·배열을 편집하지 못한다 P3-T3 P3-R1
REV-P3-002 Medium 수정 완료 create/update 실패 시 form이 영구 제출 중 상태가 된다 P3-T3 P3-R2
REV-P3-003 Medium 수정 완료 Character image가 확장자와 MIME 조합을 검증하지 않는다 P3-T3 P3-R2

6. 발견 사항 상세

REV-P3-001 — Character form의 확정 입력 범위가 누락됐다

  • 심각도: High
  • 상태: 수정 완료
  • 관련 요구사항: Character 생성·수정 폼, CHAR-003, CHAR-018
  • 관련 계약: CharacterCreateRequest, CharacterUpdateRequest
  • 소유 Task: 신규 P3-R1

관찰 내용

생성·수정 화면은 name, systemPrompt, description, originalWorkId, image와 수정의 읽기 전용 region만 제공한다. PRD가 명시한 age, gender, mbti, speechPattern, speechStyle, appearance, region, originalTitle, originalLink, characterType 및 8개 반복 배열 입력이 없다.

재현 또는 검증 절차

  1. Character 생성 또는 수정 route를 연다.
  2. OpenAPI request property와 visible label을 대조한다.
  3. 해당 18개 optional 입력을 찾거나 수정할 수 없다.
  4. API helper의 type/test는 이 필드를 수용하지만 UI test는 입력 경로를 검증하지 않는다.

영향

운영자가 계약에 포함된 캐릭터 프로필·관계·기억 데이터를 생성·수정할 수 없고 P3-T3 완료 판정과 불일치한다.

권장 조치

현재 request type을 재사용해 scalar와 반복 section을 최소 form component로 추가하고 create/update serializer·dirty state·validation E2E를 보강한다.

판정 기록

  • 2026-07-29 — PRD·OpenAPI property와 실제 form control을 대조해 확정.
  • 2026-07-30 — P3-R1에서 create/edit optional scalar·반복 배열 editor와 canonical payload test를 추가해 수정 완료로 판정.

REV-P3-002 — Character mutation 실패 후 재시도할 수 없다

  • 심각도: Medium
  • 상태: 수정 완료
  • 관련 요구사항: PRD 10.5 오류·저장 상태
  • 관련 계약: Character mutation 공통 오류 envelope
  • 소유 Task: 신규 P3-R2

관찰 내용

setIsSubmitting(true)await createCharacter/updateCharacter를 catch/finally 없이 실행한다. 요청이 reject되면 서버 오류가 표시되지 않고 제출 버튼이 계속 비활성화된다.

영향

일시적 네트워크·server 오류 뒤 입력을 유지한 재시도가 불가능하다.

권장 조치

server/form 오류 상태와 finally 복구를 추가하고 create/update rejection focused test를 먼저 작성한다.

판정 기록

  • 2026-07-29 — 두 submit 경로의 예외 처리를 대조해 확정.
  • 2026-07-30 — P3-R2에서 create/update rejection retry test를 RED로 추가한 뒤 try/catch/finally와 form-level 오류를 적용해 수정 완료로 판정. 검증: npm run test:run -- src/features/characters/tests/CharacterCreatePage.test.tsx src/features/characters/tests/CharacterEditPage.test.tsx src/features/characters/tests/character-api.test.ts 3 files / 24 tests passed, npm run test:run -- src/features/characters 6 files / 32 tests passed, npm run e2e:mock -- tests/e2e/character-workspace.spec.ts 병렬 실행은 axe timeout 4건으로 실패, focused Chromium 1 passed, timeout 보정 후 npm run e2e:mock -- tests/e2e/character-workspace.spec.ts --workers=1 41 passed / 3 skipped, npm run typecheck, npm run lint, npm run build exit 0.

REV-P3-003 — Character image의 format pair 검증이 없다

  • 심각도: Medium
  • 상태: 수정 완료
  • 관련 요구사항: FILE-002
  • 관련 계약: JPEG/PNG image
  • 소유 Task: 신규 P3-R2

관찰 내용

validateImage는 MIME과 크기만 검사한다. 예를 들어 profile.gif 또는 profile.txt라는 이름에 image/png MIME을 부여하면 통과한다.

영향

허용 format과 다른 multipart가 client에서 전송되고 backend 거부가 불필요하게 늦게 발생한다.

권장 조치

Community에서 사용하는 extension↔MIME pair 방식의 Character 전용 policy를 추가하고 mismatch test를 작성한다.

판정 기록

  • 2026-07-29 — create/edit validator의 filename 사용 0건으로 확정.
  • 2026-07-30 — Character image policy가 .jpg/.jpeg ↔ image/jpeg, .png ↔ image/png 조합을 검증하고, create/edit mismatch test가 crop source 0회와 mutation request 0회를 확인해 수정 완료로 판정. 검증 명령과 결과는 REV-P3-002의 2026-07-30 기록과 동일하다.

7. 확정 항목의 plan·goal 전환

  • REV-P3-001P3-R1
  • REV-P3-002~003P3-R2

8. 리뷰 종료 판정

판정 항목 결과 근거
리뷰 범위 전체 확인 충족 Character code/test/contract 대조
후보 항목 판정 완료 충족 3건 확정
확정 항목 plan 반영 충족 P3-R1, P3-R2
보류 항목 담당·재개 조건 해당 없음 보류 없음
검증 명령과 결과 기록 충족 §4

최종 결론: 수정 goal 필요.

남은 항목: P3-R2, Phase 9의 inactive·접근성 회귀.

9. 수정 후 검증 기록

  • 2026-07-30 REV-P3-001 / P3-R1 수정 완료 확인
    • RED: npm run test:run -- src/features/characters/tests/CharacterCreatePage.test.tsx src/features/characters/tests/CharacterEditPage.test.tsx에서 신규 3개 test가 optional field label 누락으로 실패했다.
    • GREEN: npm run test:run -- src/features/characters/tests/CharacterCreatePage.test.tsx src/features/characters/tests/CharacterEditPage.test.tsx src/features/characters/tests/character-api.test.ts 결과 3 files / 18 tests passed.
    • 회귀: npm run test:run -- src/features/characters 결과 6 files / 26 tests passed.
    • E2E: npm run e2e:mock -- tests/e2e/character-workspace.spec.ts 결과 41 passed / 3 skipped. optional 입력 추가로 keyboard-only helper의 tab 한도만 80회로 조정했다.
    • 품질 게이트: npm run typecheck, npm run lint, npm run build 모두 exit 0.
  • 2026-07-30 REV-P3-001 / P3-R1 독립 리뷰 보완
    • 발견: 수정 상세 응답에 없는 originalTitle/originalLink가 일반 저장 시 null로 전송되어 기존 서버 값을 지울 수 있는 blocker를 확인했다.
    • RED: npm run test:run -- src/features/characters/tests/CharacterEditPage.test.tsx 결과 2 failed로 이름 수정과 원작 선택 해제 저장에서 originalTitle: null, originalLink: null 전송을 재현했다.
    • 수정: 두 필드에 touched flag를 추가해 edit 기본 저장은 omit하고, 사용자가 입력 후 삭제한 경우에만 null을 전송하게 했다.
    • 재검증: npm run test:run -- src/features/characters/tests/CharacterEditPage.test.tsx 결과 1 file / 7 tests passed. npm run test:run -- src/features/characters/tests/CharacterCreatePage.test.tsx src/features/characters/tests/CharacterEditPage.test.tsx src/features/characters/tests/character-api.test.ts 결과 3 files / 18 tests passed. npm run test:run -- src/features/characters 결과 6 files / 26 tests passed. npm run e2e:mock -- tests/e2e/character-workspace.spec.ts 결과 41 passed / 3 skipped. npm run typecheck, npm run lint, npm run build 모두 exit 0.