15 KiB
Phase 0 프로젝트 기반 코드 리뷰·QA
1. 리뷰 정보
| 항목 | 내용 |
|---|---|
| 리뷰 대상 | Phase 0 / 프로젝트 기반, 환경 설정, 기본 Gate |
| 기준 commit 또는 working tree | dd30e36323543e8f60e9983326503653e8001f12, 2026-07-31 종합 재점검 당시 사용자 변경을 포함한 current working tree |
| 리뷰 일자 | 2026-07-31 |
| 리뷰어 | Codex |
| 기준 문서 | prd.md, api-contract.openapi.json 2.3.0, plan-task.md |
| 리뷰 상태 | 판정 완료, 회귀 수정 완료 |
2. 리뷰 목적과 범위
목적
- Phase 0의 환경별 API origin, 실행 명령, 기본 품질 Gate가 현재 구현과 일치하는지 확인한다.
- 완료 기록과 현재 working tree의 코드·테스트·문서가 같은 기준을 사용하는지 검증한다.
포함 범위
- 코드·설정:
.env*,src/shared/config, Vite·Vitest·Playwright 설정 - 테스트: 전체 unit, mock/server Playwright Gate, typecheck, lint, build
- 문서: PRD 공통 API 원칙,
P0-*, README와 환경 가이드 - 수동 검증: 환경 파일과 실제 요청 intercept origin 정적 대조
제외 범위
- 외부 개발 API에 대한 실제 ADMIN 계정 로그인과 운영 데이터 검증
- 발견 사항의 코드·테스트 수정
3. 판정 기준
| 심각도 | 기준 |
|---|---|
| Blocker | 보안·데이터 손실 위험, 핵심 흐름 불능, 완료 판정을 무효화하는 문제 |
| High | 확정 요구사항·API Contract 위반 또는 주요 회귀 |
| Medium | 제한된 조건의 기능·접근성·복구 문제 |
| Low | 비핵심 UX 또는 문서 정합성 문제 |
상태는 후보, 확정, 오탐, 보류, 수정 완료를 사용한다.
4. 검토한 근거
문서와 코드
- 요구사항: PRD §4, §6, §13, §14
- 계획:
P0-T1~P0-GATE - 설정:
.env.development:1,.env.production:1 - 문서:
README.md:21-22,docs/agent-guide/environment.md:3-4 - 테스트:
tests/e2e/auth.spec.ts:3,accessibility-shell.spec.ts:4,server-mode-boundary.spec.ts:4,error-mapping.spec.ts:12,comments-test-support.ts:3
실행 환경
OS: macOS 26.0 (Build 25A354)
Node: v24.12.0
npm: 11.7.0
Browser: Playwright Chromium, Mobile Chrome
환경 변수: VITE_API_MODE=mock/server, VITE_API_BASE_URL(값은 저장소 공개 설정만 대조)
실행한 검증
| 명령 또는 수동 검증 | 결과 | 핵심 증거 |
|---|---|---|
npm run typecheck |
성공 | exit 0 |
npm run lint |
성공 | exit 0 |
npm run test:run |
성공 | 72 files, 354 tests passed |
npm run build |
성공 | exit 0, 253 modules transformed |
npm run e2e:mock |
실패 | 201 passed, 22 skipped, 5 failed; 4개 프로젝트의 error-mapping이 과거 origin으로 요청해 500 수신 |
npm run e2e:mock -- tests/e2e/series.spec.ts --project=webkit --grep "desktop and tablet Series management flow remains available at 768px" |
성공 | 1 passed; 전체 실행의 단일 timeout은 재현되지 않음 |
npm run e2e |
실패 | 12 passed, 24 failed; auth·shell·server boundary가 현재 앱 origin을 intercept하지 못함 |
jq operation/status 집계 및 component schema $ref 차집합 검증 |
성공 | 두 명령 모두 exit 0; 25 paths, 37 operations, status 전부 implemented, 누락 schema ref 없음 |
OpenAPI 검증은 다음 명령으로 실행했다.
jq '[.paths[] | to_entries[] | select(.key | IN("get", "put", "post", "delete", "patch", "head", "options", "trace")) | .value] as $operations | {openapi, version: .info.version, paths: (.paths | length), operations: ($operations | length), statuses: ([$operations[]."x-implementation-status"] | unique)}' docs/20260725_AI캐릭터관리자웹/api-contract.openapi.json
jq -e '((([.. | objects | .["$ref"]? // empty | select(startswith("#/components/schemas/")) | split("/")[-1]] | unique) - (.components.schemas | keys)) | length) == 0' docs/20260725_AI캐릭터관리자웹/api-contract.openapi.json
5. 발견 사항 요약
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|---|---|---|---|---|---|
REV-P0-004 |
High | 수정 완료 | API origin 변경이 문서와 Playwright route에 반영되지 않아 브라우저 Gate가 실패한다 | P0-R2 |
P0-R2 |
6. 발견 사항 상세
REV-P0-004 — API origin 변경이 문서와 Playwright route에 반영되지 않아 브라우저 Gate가 실패한다
- 심각도: High
- 상태: 수정 완료
- 관련 요구사항: PRD §4, §6.2, §13, §14
- 관련 계약: 모든 OpenAPI operation의 server-mode 요청 경계
- 소유 Task: 신규
P0-R2
관찰 내용
현재 개발·운영 환경 파일은 각각 https://test-api.sodalive.net, https://api.sodalive.net을 사용한다. README, 환경 가이드와 다섯 Playwright 지원 파일은 과거 test-character-admin/character-admin origin을 사용한다. 앱 요청과 테스트 route가 서로 다른 origin을 바라보므로 mock 오류 매핑과 server auth·shell·retry 검증이 실제 요청을 가로채지 못한다.
근거
- 코드:
.env.development:1,.env.production:1 - 테스트:
tests/e2e/auth.spec.ts:3,accessibility-shell.spec.ts:4,server-mode-boundary.spec.ts:4,error-mapping.spec.ts:12,comments-test-support.ts:3 - 문서:
README.md:21-22,docs/agent-guide/environment.md:3-4 - 자동화: mock Gate 4개 동일 error-mapping 실패, server Gate 24개 실패
재현 또는 검증 절차
- 현재
.env.development를 유지한다. npm run e2e:mock을 실행한다.- 과거 origin 요청이 MSW handler와 일치하지 않아 기대한 401 대신 500이 반환되는 것을 확인한다.
npm run e2e를 실행해 로그인·shell·server retry route가 현재 요청을 intercept해야 하지만 24개 test가 실패하는 것을 확인한다.
영향
브라우저 Gate가 제품 회귀와 무관하게 실패하고, server-mode 인증·오류 경계 및 Comments 연동을 올바른 origin에서 검증하지 못한다. README를 따르는 개발자도 잘못된 서버 주소를 사용하게 된다.
권장 조치
공개 환경 파일을 단일 기준으로 README·환경 가이드·Playwright route/probe를 동기화하고, 과거 host 검색과 mock/server focused test를 회귀 증거로 추가한다.
판정 기록
- 2026-07-30 — 설정·문서·테스트 문자열 대조와 두 브라우저 Gate의 반복 실패로 확정.
- 2026-07-30 —
P0-R2에서 E2E API origin helper와 문서 현재값을 정렬하고 focused/full Gate 분할 검증으로 수정 완료 판정.
7. 확정 항목의 plan·goal 전환
REV-P0-004→plan-task.md신규P0-R2- goal objective:
[P0-R2] API origin 단일 기준을 문서와 모든 Playwright route/probe에 동기화하고 mock/server Gate 회귀를 방지한다.
8. 리뷰 종료 판정
| 판정 항목 | 결과 | 근거 |
|---|---|---|
| 리뷰 범위 전체 확인 | 충족 | 설정·문서·정적·자동 Gate 확인 |
| 후보 항목 판정 완료 | 충족 | 1건 확정 |
| 확정 항목 plan 반영 | 충족 | P0-R2 완료 |
| 보류 항목의 담당·재개 조건 기록 | 해당 없음 | 보류 없음 |
| 검증 명령과 결과 기록 | 충족 | §4에 실제 결과 기록 |
최종 결론: 확정 발견 사항 수정 완료.
남은 항목: 없음.
9. 수정 후 검증 기록
- 2026-07-30 —
P0-R2RED:npm run e2e:mock -- tests/e2e/error-mapping.spec.ts는 4 failed / 4 passed로 과거 origin unhandled 500을 재현했고,npm run e2e -- tests/e2e/server-mode-boundary.spec.ts --project=chromium은 2 failed / 2 passed로 stale route/probe 실패를 재현했다. - 2026-07-30 —
tests/e2e/api-base-url.ts를 추가해 E2E route/probe가.env.development의VITE_API_BASE_URL을 읽게 하고, README와 환경 가이드를https://test-api.sodalive.net/https://api.sodalive.net로 정렬했다. - 2026-07-30 — GREEN focused:
npm run e2e:mock -- tests/e2e/error-mapping.spec.ts8 passed,npm run e2e -- tests/e2e/server-mode-boundary.spec.ts --project=chromium4 passed,npm run e2e -- tests/e2e/comments.spec.ts --project=chromium3 passed. - 2026-07-30 — Gate:
npm run e2e36 passed.npm run e2e:mock단일 실행은 900초 제한으로 188/228 진행 중 timeout됐으나, 같은 allowlist를 project별로 분할해chromium57 passed,webkit49 passed / 8 skipped,mobile-chrome52 passed / 5 skipped,mobile-safari48 passed / 9 skipped로 전체 mock matrix를 확인했다. - 2026-07-30 — 정적 검증:
rg -n 'test-character-admin|character-admin\.sodalive\.net' README.md docs/agent-guide tests/e2eno matches,npm run typecheck,npm run lint,npm run build모두 exit 0,tests/e2eLSP diagnostics 오류 0건.
10. 2차 점검 결과 — 2026-07-30
npm ci,npm run typecheck,npm run lint,npm run build가 모두 exit 0이었다.- 전체 unit은 72 files / 358 tests, server allowlist E2E는 36 tests, mock Chromium matrix는 57 tests가 통과했다.
- Phase 0 신규 발견은 없으며
REV-P0-004수정 완료 상태가 유지된다.
11. 2026-07-31 재점검
- 기준: commit
dd30e36323543e8f60e9983326503653e8001f12, 재점검 시작 시 working tree 변경 220개. 기존 사용자 변경은 수정하지 않고 현재 tree를 검토했다. - 검증:
npm run typecheck,npm run lint,npm run build는 exit 0,npm run test:run은 72 files / 360 tests passed,npm run e2e는 36 passed였다. - 계약·구성 판정: package scripts, 환경 mode 경계, build와 server allowlist에서 Phase 0 신규 결함은 확인되지 않았다.
REV-P0-004는 수정 완료 상태를 유지한다. - 교차 Phase: 당시 Mobile Safari 간헐 실패 후보는 이후 지원 project 축소로 현재 Task에서 제외했다.
- 신규 Task: 없음.
12. 최종 Phase별 점검 — 2026-07-31
- 검토 범위: package scripts, TypeScript·ESLint·production build, server/mock mode 실행 경계, 현재 Playwright project 구성을
P0Gate와 재대조했다. - 실행 증거:
npm run typecheck,npm run lint,npm run buildexit 0. server E2E는 샌드박스의 최초listen EPERM을 제품 실패와 분리한 뒤 승인된 로컬 실행에서 18/18 통과했다. - 판정: 현재 지원 project인 Chromium·Mobile Chrome 기준 기반 설정과 server allowlist에서 확정 신규 발견 사항 없음.
- 남은 위험: 실제 개발 API의 가용성·운영 배포 환경은 이 Phase 자동 검증 범위 밖이다.
- 신규 Task: 없음.
13. 종합 재점검 — 2026-07-31
REV-P0-005 — 문서 디렉터리의 .DS_Store가 version control index에 포함됨
| 항목 | 내용 |
|---|---|
| 심각도 | Low |
| 상태 | 수정 완료 |
| 관련 요구사항·계약 | Phase 0 재현 가능한 프로젝트 기반과 저장소 문서 유지보수; API 계약 영향 없음 |
| 소유 Task | P0-R3 |
| 근거 | git ls-files 'docs/20260725_AI캐릭터관리자웹/.DS_Store'가 해당 binary entry를 반환하고 .gitignore에는 .DS_Store 규칙이 없다. |
재현 또는 검증 절차
git ls-files | rg '(^|/)\.DS_Store$'를 실행한다.docs/20260725_AI캐릭터관리자웹/.DS_Store가 출력되는지 확인한다.rg -n '^\.DS_Store$' .gitignore가 no matches인지 확인한다.
영향과 권장 조치
운영체제별 binary metadata가 문서 변경에 섞여 불필요한 diff와 충돌을 만들 수 있다. 해당 entry만 제거하고 저장소 전역 ignore 규칙을 추가한다. 다른 사용자 파일이나 문서 내용은 정리하지 않는다.
판정 기록
- 2026-07-31 — 현재 index와 ignore 규칙을 정적으로 대조해 확정.
- 2026-07-31 — 애플리케이션 코드는 수정하지 않고
plan-task.md신규P0-R3로 전환. - 2026-07-31 —
P0-R3에서.DS_Store를 index와 working tree에서 제거하고 저장소 ignore 규칙을 추가해 수정 완료 판정.
Phase 0 결론
- 자동 검증:
npm run typecheck,npm run lint,npm run build:dev,npm run build:prod모두 exit 0. 두 build는 기존 500kB 초과 chunk warning만 출력했다. - 판정: runtime·환경 mode·script의 신규 결함은 없다. Low 1건은
P0-R3에서 수정 완료됐다. - 남은 위험: 실제 배포 환경과 개발 API 가용성은 자동 검증 범위 밖이다.
P0-R3 수정 후 검증 — 2026-07-31
- 무엇을: 문서 디렉터리의
.DS_Storestaged entry를 제거하고 저장소 ignore 규칙을 추가했다. - 왜: 운영체제별 binary metadata가 문서 변경과 충돌에 섞이지 않게 하기 위해서다.
- 검증:
git ls-files | rg '(^|/)\.DS_Store$'와git status --short --untracked-files=all | rg '\.DS_Store'는 no matches,rg -n '^\.DS_Store$' .gitignore는7:.DS_Store,git diff --check -- .gitignore docs/20260725_AI캐릭터관리자웹은 exit 0이었다.
14. 요청 기준 재리뷰 — 2026-07-31
- 기준: commit
dd30e36323543e8f60e9983326503653e8001f12와 사용자 변경을 포함한 current working tree. - 검증:
typecheck,lint,build:dev,build:prodexit 0, server-mode Chromium·WebKit·Mobile Chrome·Mobile Safari smoke/auth/boundary 36 passed. 두 build는 기존 500kB 초과 chunk warning만 표시했다. - 판정: Phase 0 runtime·환경·build 소유의 신규 기능 결함은 없다. 전체 unit 실패는
P9-R7의 mock E2E script 문서·test 정합성으로REV-P9-008에 귀속한다. - 문서 교차 항목: 상단 리뷰 상태가 완료된
P0-R3와 어긋나는 문제는REV-P10-008/P10-R7에서 과거 기록을 보존한 채 정리한다. - 신규 Phase 0 Task: 없음.
15. 최종 재검증 — 2026-07-31
- 검토 범위: package script, server/mock mode, 환경 변수, 개발·운영 build와 browser project 구성을 다시 확인했다.
- 실행 증거:
npm run test:run78 files / 394 tests,npm run e2e36 tests,npm run e2e:mock186 passed / 22 skipped가 통과했다.typecheck,lint,build:dev,build:prod, staged/unstaged diff check도 exit 0이었다. - 판정: Phase 0 소유의 확정 신규 발견 사항 없음. build의 502.94kB chunk warning은 PRD·plan에 hard limit가 없어 이번 Task로 전환하지 않는다.
- 남은 위험: 실제 배포 환경과 개발 API 가용성은 자동 검증 범위 밖이다.
- 신규 Phase 0 Task: 없음.
16. 2026-07-31 문서 기준 재리뷰
- 검토 범위:
package.json, Vite/Vitest/Playwright 설정, server/mock 명령, 환경 mode 경계, build 산출물과P0·P9Gate 기록을 PRD·plan에 대조했다. - 실행 증거:
npm run typecheck,npm run lint,npm run build:dev,npm run build:prodexit 0, server E2E 4 projects / 36 passed. build는 기존 503.04kB chunk warning만 표시했다. 전체 unit은 79 files / 397 tests 중 5 failed / 392 passed였고, 기반 코드가 아닌 integration harness 비결정성REV-P9-009/P9-R9로 분리했다. - 판정: Phase 0 runtime·실행 스크립트·환경 mode 소유의 확정 신규 발견 사항 없음. 후보·오탐·보류 0건, 신규 Phase 0 Task 없음.
- 남은 위험: 503.04kB warning은 문서 hard limit가 없어 Task로 전환하지 않았다. 실제 배포 환경과 개발 API 가용성은 자동 범위 밖이다.