# Baseline Metrics — Phase 0~5 완료 (v0.6.0)

측정일: 2026-04-17 (Phase 0 시작) / 최종 갱신: 2026-04-21 (v0.6.0 태그)

이 문서는 아키텍처 리팩토링의 진행을 수치로 추적한다.

---

## 🎉 최종 진행 현황 (v0.6.0)

| Phase | 상태 | 완료일 | 주요 산출 |
|---|---|---|---|
| 0 | ✅ 완료 | 2026-04-17 | test baseline 48 복구, AnalysisService deprecated |
| 1 | ✅ 완료 | 2026-04-17 | Step Catalog, applicability validator, checkpoint_io, manifest 필드 확장 |
| 2 | ✅ 완료 | 2026-04-17 | CheckpointSync 5-way 분해, ShotSelectionService, SnapshotService, SettingsRegistry, api_endpoint |
| 3 | ✅ 완료 | 2026-04-18 | step 경계 재정의, SceneAnalysisContext DTO, SceneContextLoader |
| 3b (1~6) | ✅ 완료 | 2026-04-18 | **ImageService 5,281→1,224 (-77%)** Service 3-way 분할 |
| 4 | ✅ 완료 | 2026-04-18 | **AnalysisService 1,137줄 제거**, outlook_dedup UPSERT |
| 5 | ✅ 완료 | 2026-04-20 | **Frontend React Query 전환**, EpisodeDetail 1,358→148 (-89%) |
| 세션 E | ✅ 완료 | 2026-04-20 | **Backend `except: pass` 38→0** (silent failure 제거) |

**최종 태그**: `v0.6.0` (커밋 `631a082`)

### Phase 3 부분 완료 세부
- **3.1 Image step 경계 재정의**: `skip_composite` 플래그 분기로 달성 (로드맵의 두 메서드 분리 대신 플래그 기반). `_mark_composite_done` 제거. ImageService 내부 분리는 3.3으로 이월.
- **3.6 SceneAnalysisContext DTO**: dataclass + SceneContextLoader 도입. `detail_steps._execute` 로드 170줄 분리. `_analyze_one` 본문 closure 참조는 점진 전환 (Phase 3b).
- **3.2 PromptService / 3.3 ReferenceImageService / 3.4 SceneImageService / 3.5 shim**: 이번 세션 범위 밖. 별도 Phase 3b 세션에서 처리.

---

## 1. 코드 크기 (wc -l) — v0.6.0 최종

| 파일 | 초안 | 최종 | Δ | 비고 |
|---|---|---|---|---|
| `backend/app/services/image_service.py` | 5,281 | **1,224** | **−4,057 (−77%)** | Phase 3b 3-way Service 분할 |
| `backend/app/api/v1/steps.py` | 1,518 | **496** | −1,022 (−67%) | Phase 2 5-way + Phase 1 catalog |
| `backend/app/services/analysis_service.py` | 1,137 | **0 (삭제)** | −1,137 (−100%) | Phase 4 제거 |
| `backend/app/core/steps/detail_steps.py` | 1,021 | **885** | −136 | Phase 3.6 Loader 분리 + 3b |
| `backend/app/core/steps/image_steps.py` | 746 | **726** | −20 | Phase 3.1 `_mark_composite_done` 제거 |
| `backend/app/core/step_manifest.py` | 612 | 734 | +122 | Phase 1 manifest 필드 확장 |
| `backend/app/core/step_runner.py` | 343 | 354 | +11 | Phase 1 applicability + modifies_checkpoints |
| `frontend/src/pages/EpisodeDetail.tsx` | 1,358 | **148** | **−1,210 (−89%)** | Phase 5 분할 완료 |
| `frontend/src/pages/ProjectDetail.tsx` | 483 | **363** | −120 (−25%) | Phase 5 세션 D |
| `frontend/src/pages/Episodes.tsx` | 360 | **268** | −92 (−26%) | Phase 5 세션 D |
| `frontend/src/pages/Dashboard.tsx` | 227 | **196** | −31 (−14%) | Phase 5 세션 D |

### 신규 파일 (Phase 1~5 + 세션 E 누적)

**Backend**:
- Phase 1 (3): `step_catalog.py`, `applicability.py`, `checkpoint_io.py`
- Phase 2 (10): `checkpoint_sync/` 7 파일 + `shot_selection_service.py` + `snapshot_service.py` + `settings_registry.py`
- Phase 3 (3): `dto/scene_analysis.py`, `steps/scene_context_loader.py`, `dto/__init__.py`
- Phase 3b (2): `reference_image_service.py`, `scene_image_service.py`, `image_service_helpers.py`

**Frontend (Phase 5)**:
- Query 훅 (16): useEpisode/useStills/useEntities/useWorldGuide/useProgress/useGenStatus/useScreenplay/useWorldRules/useProjectList/useEpisodesList/useEpisodesProgress/useProject/useMembers/useActivities/useProjectSummary/usePlanningDoc/useStillImages
- Mutation 파일 (9): useShotToggle + useCreateProject + useAnalyzeEpisode + useCreateEpisode + useMemberMutations(3) + usePlanningDocMutations(3) + useStillMutations(15)
- Components (4): `components/episode/` EpisodeHeader(80), EpisodeWorldGuide(359), EpisodeActionBar(146), EpisodeStills(524)
- Types: `types/project.ts`

**Docs**:
- `docs/architecture-easy/` 8개 파일 (비전문가용 가이드)
- `frontend/public/pipeline_explained.html` (일반인용 시각화)
- `docs/product-roadmap-discussion.md`

### 신규 파일 (Phase 1~3 누적)
- Phase 1 (3): `step_catalog.py`, `applicability.py`, `checkpoint_io.py`
- Phase 2 (10): `checkpoint_sync/` 7 파일 + `shot_selection_service.py` + `snapshot_service.py` + `settings_registry.py`
- Phase 3 (3): `dto/scene_analysis.py`, `steps/scene_context_loader.py`, `dto/__init__.py`

---

## 2. 대형 함수 크기

| 함수 | 파일 | 라인 | 리팩토링 Phase |
|---|---|---|---|
| `_sync_checkpoints_to_db` | `steps.py:768-1487` | **722** | Phase 2 (5-way 분해) |
| `SceneDetailStep._execute` | `detail_steps.py:45-927` | **882** | Phase 3 (DTO + 분할) |
| `_build_final_scene_prompt` | `image_service.py:62-272` | **211** | Phase 3 (DTO 추출) |

> `SceneDetailStep._execute` 882줄: shot-more 브랜치 신규 주입 로직(scene_camera_flow, scene_consistency fixed_elements, dead character variant) 누적으로 확장됨. Phase 3 DTO 분리의 난이도 상향 신호.
> `_build_final_scene_prompt` 211줄: Codex 리뷰로 측정 재검증 — 이전 초안의 388/496줄 값은 내부 중첩 함수까지 포함한 오측정이었음. 실제 top-level 함수 경계는 line 273의 `_select_and_recommend_angle` 직전에서 종료.

---

## 3. Step Manifest

| 구분 | 개수 | 비율 |
|---|---|---|
| **Total** | **48** | 100% |
| `applicability: always` | 38 | 79% |
| `applicability: if_planning_doc` | 1 | 2% |
| `applicability: if_has_outlooks` | 1 | 2% |
| `applicability: on_demand` | 5 | 10% |
| `applicability: disabled` | 3 | 6% |
| **Active (always + if_*)** | **40** | 83% |

Category별:
- `analysis`: 41
- `image`: 5
- `auxiliary`: 2

Active 40개의 Phase별 배치 (`docs/architecture/00-overview.md` 기준):
- Phase 1 (텍스트 전처리): 8 — planning_doc_analysis 포함
- Phase 2 (엔티티): 11
- Phase 3 (샷/비트): 3
- Phase 4 (씬 연출): 13
- Phase 5 (이미지): 5

---

## 4. 결함 패턴 분포

| 패턴 | 개수 | 측정 방법 | 리팩토링 Phase |
|---|---|---|---|
| 하드코딩 downstream 분기 | 4 | 초안 `00-analysis.md` + Codex 신규 발견 | Phase 1 |
| DELETE→INSERT 위반 (steps.py) | 5+ | `grep "db.query.*\\.delete()"` | Phase 2 |
| DELETE→INSERT 위반 (전체) | 12+ | outlook_dedup 6-way 포함 | Phase 4 |
| `except ... : pass/continue/return` | **29+** | `grep multiline except → pass\|continue\|return` | Phase 5 |
| API private 역의존 (image_steps → steps.py) | 2 | `image_steps.py:58,345` | Phase 3 |
| Image step 경계 붕괴 | 1 | `RefImageGenStep._mark_composite_done` | Phase 3 |
| AnalysisService 중복 실행 경로 | 1 | `/episodes/{id}/analyze`, `/reanalyze-scenes` | Phase 4 |

> 초안에서 "`except: pass` 37건"으로 측정했으나 이번 재측정은 29+ (한 파일당 1건 이상 매칭으로 약간 부족 집계). Phase 5 진입 시 rg 정확 카운트로 재측정 예정.

---

## 5. 테스트

### 5.1 `tests/test_step_manifest_v3.py`
- **Phase 0 이전**: 11 failed / 9 passed (낡은 기대치)
- **Phase 0 이후**: **22 passed / 0 failed** ✅

### 5.2 전체 pytest suite
- **375 tests collected, 8 collection errors** (pytest --collect-only, 1394.62s ≈ 23분)
- 확인된 실패 예: `test_costume_trace.py`, `test_costume_trace_gpt.py` — `sqlalchemy.exc.OperationalError` (SQLite 의존)
- CLAUDE.md 규칙상 DB는 PostgreSQL — SQLite 의존 테스트는 legacy로 추정. Phase 4 또는 Phase 5 cleanup 대상
- 수집 시간 23분은 이상치 — 테스트 fixture 초기화 비용 과다 의심. 별도 조사 필요

### 5.3 Deprecated 엔드포인트 의존 테스트 (Phase 4 정리 예정)

Phase 0에서 `/analyze`·`/reanalyze-scenes`가 `deprecated=True`로 선언되어 호출 시 WARNING 로그 발생.
아래 기존 테스트 3건이 계속 이 경로를 사용 — 지금은 유지 (가용성), Phase 4에서 StepRunner 경로로 전환:

- `backend/tests/test_entities_api.py:298`
- `backend/tests/test_entities_api.py:310`
- `backend/tests/test_entities_api.py:338`

Frontend 호출자(`Episodes.tsx:133`, `EpisodeDetail.tsx:1077`)도 Phase 4 동시 마이그레이션 대상.

---

## 6. Frontend (hooks 카운트, Phase 5 대상)

| 파일 | useState | useEffect |
|---|---|---|
| `EpisodeDetail.tsx` | **34** | 7 |
| `ProjectDetail.tsx` | 16 | 6 |
| `Episodes.tsx` | 10 | 4 |

> 초안 `EpisodeDetail.tsx` useState "51개" 과대 측정, Codex "15개" 과소 측정. 이번 정확 재측정: **34**.
> Phase 5에서 React Query 도입 + 컴포넌트 분할 후 useState 합계 < 40 (3 파일 합쳐서) 목표.

---

## 7. 실행 경로 (Phase 0 변경 반영)

| 경로 | 상태 | 엔드포인트 |
|---|---|---|
| `StepRunner` | **공식** | `/api/v1/projects/{pid}/episodes/{eid}/steps/*` |
| `AnalysisService.run_analysis()` | **deprecated** (Phase 0 선언) | `/api/v1/projects/{pid}/episodes/{eid}/analyze` |
| `AnalysisService.reanalyze_scenes()` | **deprecated** (Phase 0 선언) | `/api/v1/projects/{pid}/episodes/{eid}/reanalyze-scenes` |

deprecated 두 엔드포인트
- FastAPI `deprecated=True` (OpenAPI 표시)
- 호출 시 `logger.warning` 로그
- Phase 4에서 제거 예정

---

## 8. 재측정 프로토콜

각 Phase 완료 시:
1. 이 파일에 `Phase N 완료 (YYYY-MM-DD)` 컬럼 추가
2. 변경된 수치 모두 갱신
3. 감소율 요약 (예: "`_sync_checkpoints_to_db` 722 → 0, 5-way Service로 분해")
4. 새 결함 발견 시 §4에 행 추가

### 측정 명령
```bash
# 파일 라인 수
wc -l backend/app/services/image_service.py backend/app/api/v1/steps.py ...

# Step manifest
cd backend && .venv/bin/python -c "
from app.core.step_manifest import STEP_MANIFEST
print(f'total: {len(STEP_MANIFEST)}')
# category, applicability 집계
"

# Step manifest 테스트
cd backend && .venv/bin/python -m pytest tests/test_step_manifest_v3.py -v

# except pass
grep -rn multiline 'except.*:\\s*\\n\\s*(pass|continue|return)' backend/app --include='*.py'

# DELETE→INSERT
grep -rn 'db\\.query.*\\.delete()' backend/app/api/v1/ backend/app/services/

# Frontend hooks
grep -c useState frontend/src/pages/EpisodeDetail.tsx
```

---

## 9. 참조

- 최종 로드맵: `02-final-roadmap.md`
- 9원칙: `01-principles-revised.md`
- 13개 결함 분석: `00-integrated-analysis.md`
- Phase 0 brief: `04-next-session-brief.md`
