# Task-507.3 완료 보고서

**담당**: 헤르메스 (개발1팀)
**작업일**: 2026-03-13

---

## SCQA

**S**: InsuRo 서버의 ai_parser.py가 Anthropic SDK를 직접 사용하여 Claude API를 호출하고 있으며, gdrive.py의 환경변수명이 .env.keys와 불일치하고, AI 분석 결과가 DB에 저장되지 않는 상태이다.

**C**: Anthropic SDK 의존은 API 키 관리 부담을 유발하고, 환경변수 불일치는 배포 시 오류를 야기하며, 분석 결과 미저장은 데이터 유실 위험이 있다.

**Q**: Claude CLI 전환, 환경변수 정비, Supabase DB 연동을 통해 API 키 의존을 제거하고 안정적인 데이터 파이프라인을 구축할 수 있는가?

**A**: Claude CLI(subprocess) 전환으로 anthropic 패키지 의존 제거, gdrive.py에 INSURO_ prefix 우선 + fallback 패턴 적용, main.py에 Supabase fcpa_config upsert 로직 추가 완료. pytest 41건 전체 통과(기존 37 + 신규 4), pyright 에러 0건.

---

## 작업 내용

### 1. ai_parser.py — Anthropic SDK → Claude CLI 전환
- `import anthropic` 제거 → `import subprocess`, `import os` 추가
- `analyze_fcpa_pdf()`: `anthropic.Anthropic().messages.create()` → `subprocess.run(["claude", "-p", prompt, "--model", "sonnet"])`
- timeout 120초 설정, returncode 검증 후 RuntimeError 발생
- `extract_text_from_pdf()`, `parse_ai_response()` 변경 없음

### 2. gdrive.py — 환경변수 매핑
- `INSURO_GOOGLE_CLIENT_ID` → `GOOGLE_CLIENT_ID` fallback 패턴 적용
- `INSURO_GOOGLE_CLIENT_SECRET` → `GOOGLE_CLIENT_SECRET` fallback
- `INSURO_GOOGLE_REFRESH_TOKEN` → `GOOGLE_REFRESH_TOKEN` fallback
- docstring에 INSURO_ prefix 우선 적용 반영

### 3. main.py — Supabase DB upsert 추가
- `from supabase import create_client` import 추가
- `/api/insuro/fcpa/upload` 엔드포인트에서 AI 분석 결과를 `fcpa_config` 테이블에 upsert
- 환경변수: `INSURO_NEW_SUPABASE_URL` / `INSURO_NEW_SERVICE_ROLE_KEY` 우선, fallback 포함
- try/except로 감싸 Supabase 실패가 업로드 응답을 방해하지 않도록 처리
- pyright `type: ignore[index]` 1건 (Supabase SDK 타입 한계)

### 4. requirements.txt
- `anthropic>=0.20.0` 제거 (supabase는 기존에 있음)

### 5. run.sh (신규)
- `.env.keys` source 후 uvicorn 실행 (port 8001)
- `chmod +x` 완료

### 6. scripts/get_refresh_token.py (신규)
- Google OAuth2 Refresh Token 발급 헬퍼
- INSURO_GOOGLE_CLIENT_ID/SECRET 사용

### 7. 테스트 수정
- conftest.py: `mock_anthropic_response` 제거 → `mock_subprocess_claude` 추가, env_vars에 INSURO_ 변수 추가
- test_ai_parser.py: `patch("ai_parser.anthropic.Anthropic")` → `patch("ai_parser.subprocess.run")` 전환, CLI 실패/timeout 테스트 2건 추가
- test_main.py: Supabase mock 추가, `test_upload_triggers_supabase_upsert`, `test_upload_success_even_when_supabase_fails` 2건 추가

---

## 생성/수정 파일 목록

- `/home/jay/projects/InsuRo/server/ai_parser.py` (수정)
- `/home/jay/projects/InsuRo/server/gdrive.py` (수정)
- `/home/jay/projects/InsuRo/server/main.py` (수정)
- `/home/jay/projects/InsuRo/server/requirements.txt` (수정)
- `/home/jay/projects/InsuRo/server/run.sh` (신규)
- `/home/jay/projects/InsuRo/server/scripts/get_refresh_token.py` (신규)
- `/home/jay/projects/InsuRo/server/tests/conftest.py` (수정)
- `/home/jay/projects/InsuRo/server/tests/test_ai_parser.py` (수정)
- `/home/jay/projects/InsuRo/server/tests/test_main.py` (수정)

---

## 테스트 결과

- **pytest**: 41 passed, 0 failed (1.27초)
  - test_ai_parser.py: 16건 (기존 14 → 16, 신규 2건)
  - test_gdrive.py: 8건 (변경 없음)
  - test_main.py: 17건 (기존 15 → 17, 신규 2건)
- **pyright**: 0 errors, 0 warnings
- **warnings**: JWT InsecureKeyLengthWarning 17건 (테스트용 짧은 시크릿 — 프로덕션 무관)

---

## 발견된 이슈

1. **GOOGLE_REFRESH_TOKEN 미발급**: .env.keys에 `INSURO_GOOGLE_REFRESH_TOKEN`이 아직 없음. `scripts/get_refresh_token.py` 실행 후 발급 필요.
2. **Supabase RLS 정책**: `fcpa_config` 테이블에 anon key로 쓰기 가능한지 미확인. service_role_key(`INSURO_NEW_SERVICE_ROLE_KEY`)가 필요할 수 있음. 현재 코드는 service_role_key 우선 사용.
3. **pyright type: ignore 1건**: `main.py:134` — Supabase SDK의 `.data` 타입이 `list | None | bool | ...` 으로 추론되어 subscript 접근 시 type: ignore 필요. 런타임에는 문제 없음.

---

## 비고

- Supabase 연동은 try/except로 격리되어 있어 환경변수 미설정 시에도 기존 기능(PDF 업로드 + AI 분석)은 정상 동작
- `anthropic` 패키지 제거로 의존성 경량화 달성
- 서버 실행: `bash /home/jay/projects/InsuRo/server/run.sh`
