# task-2189 완료 보고서: AI 호출 subprocess → API 전환

**팀**: dev3-team (다그다)
**작업 레벨**: Lv.2
**프로젝트**: InsuRo

---

## SCQA

**S**: InsuRo `server/ai_parser.py`의 `analyze_fcpa_pdf` 함수가 `subprocess.run(["claude", "-p", "--model", "sonnet"])` 방식으로 Claude CLI를 호출하고 있었다.

**C**: subprocess 방식은 shell injection 보안 위험, 프로세스 생성 오버헤드로 인한 성능 저하, 에러 핸들링 어려움이 있다. FastAPI 비동기 환경에서 동기 subprocess.run 호출은 이벤트 루프를 블로킹한다.

**Q**: subprocess.run을 제거하고 Python anthropic SDK 직접 호출로 전환하여 보안과 성능을 개선할 수 있는가?

**A**: `anthropic.AsyncAnthropic` SDK로 전환 완료. subprocess import 제거(0건 확인), async/await 비동기 호출 적용, try/except 에러 핸들링 개선. 기존 API 응답 포맷 유지. pytest 349건 전체 통과(0 실패), 신규 테스트 7건 추가 통과.

---

## 수정 파일 목록

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| server/ai_parser.py:10 | `import subprocess` 제거 | grep "subprocess" → 0건 | verified |
| server/ai_parser.py:12 | `import anthropic` 추가 | grep "import anthropic" → 1건 | verified |
| server/ai_parser.py:109-155 | `analyze_fcpa_pdf` async + SDK 호출 전환 | grep "AsyncAnthropic" → 1건 | verified |
| server/ai_parser.py:153-156 | TextBlock 타입 안전 처리 (hasattr 검사) | grep "hasattr" → 1건 | verified |
| server/main.py:615 | `ai_parser.analyze_fcpa_pdf()` → `await ai_parser.analyze_fcpa_pdf()` | grep "await ai_parser.analyze_fcpa_pdf" → 1건 | verified |
| server/requirements.txt | `anthropic>=0.30.0` 추가 | grep "anthropic" → 1건 | verified |
| server/tests/test_ai_parser.py | 신규 테스트 7개 작성 | grep "def test_" → 7건 | verified |

---

## 테스트 결과

- **신규 테스트**: 7/7 PASS (test_ai_parser.py)
- **전체 회귀**: 349/349 PASS, 0 FAIL (server/tests/)
- **goal_assertion**: `grep -n "subprocess" server/ai_parser.py` → 0건 확인

---

## L1 스모크테스트 결과

- 서버 재시작: 성공 (uvicorn, port 8000)
- API 응답 확인: `curl http://localhost:8000/api/status` → `{"status":"ok"}`
- 스크린샷: 해당없음 (백엔드 작업)

---

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **pyright: `message.content[0].text` 타입 에러** — content block이 TextBlock 외 다른 타입일 수 있음. `hasattr` 검사 + `type: ignore[union-attr]` 적용
2. **pip 실행 시 불필요 파일 생성 (`server/=0.30.0`)** — 삭제 및 커밋
3. **pytest-asyncio strict 모드 호환** — 테스트에 `@pytest.mark.asyncio` 데코레이터 정확히 적용

### 범위 외 미해결 (1건)
1. **main.py: `on_event` deprecation 경고** — 범위 외 사유: FastAPI lifespan 전환은 별도 리팩토링 대상

---

## Gemini PR 리뷰 결과

- PR: https://github.com/JonghyukJeon/InsuRo/pull/30
- High 1건: 모델 ID `claude-sonnet-4-6` 의문 → **기각** (claude-sonnet-4-6은 최신 공식 모델 ID, PR에 기각 사유 코멘트 등록)
- Medium 1건: `content[0]` IndexError 방어 → **수용** (빈 리스트 검사 추가 후 push)
- Medium 1건: DigitalNamecard.tsx 전화번호 검증 → **범위 외** (본 작업 대상 아님)
- 판정: 미수정 High 0건 → PASS → 자동 머지 완료

## 머지 판단

- **머지 필요**: Yes → **머지 완료**
- **브랜치**: task/task-2189-dev3 (삭제됨)
- **워크트리 경로**: /home/jay/projects/InsuRo/.worktrees/task-2189-dev3
- **머지 의견**: subprocess 완전 제거 확인, 349건 테스트 전체 통과, Gemini 리뷰 PASS. 머지 완료.

---

## 모델 사용 기록

- 팀원: 루(Lugh) / 작업: subprocess→SDK 전환 코딩 (MT-1~3) / 모델: sonnet
- 팀원: 모리건(Morrigan) / 작업: 테스트 작성 (MT-4) / 모델: sonnet
- 팀장: 다그다 / 작업: 설계, 통합, pyright 수정, L1 스모크테스트 / 모델: opus

---

## 셀프 QC 체크리스트

- [x] 1. 영향 파일: ai_parser.py (main.py에서 호출), main.py (await 추가)
- [x] 2. 엣지 케이스: API 키 미설정, API 에러, TextBlock 아닌 응답 — 모두 처리됨
- [x] 3. 작업 지시와 정확히 일치: subprocess 제거, SDK 전환, async 지원, 에러 핸들링
- [x] 4. 보안: API 키 환경변수 로드 (하드코딩 없음), subprocess shell injection 제거
- [x] 5. 테스트: 7개 케이스로 정상/에러/엣지 경로 커버
- [x] 6. 발견 이슈 모두 직접 해결 (3건)
- [x] 7. SOLID/DRY 위반 없음
- [x] 8. 인터페이스 변경: analyze_fcpa_pdf가 async로 변경 → main.py await 적용 완료
- [x] 13. L1 스모크테스트: 서버 재시작 + API 200 확인

## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회

