# InsuRo 소식지/보험료 파일 저장을 Google Drive로 전환

## 작업 레벨: Lv.2

## 프로젝트 시스템 3문서
- DevSystem: `/home/jay/workspace/memory/plans/anu-guide-system/plan.md`

## 프로젝트
- InsuRo: `/home/jay/projects/InsuRo`
- 서버: `/home/jay/projects/InsuRo/server` (FastAPI, port 8001)

## 배경
현재 소식지/보험료 PDF·PPTX 파일이 Supabase Storage에 저장되는데, 무료 플랜 1GB 한도. 매월 수백 MB 업로드하면 몇 달이면 초과. 제이회장님 지시로 Google Drive(15GB 무료, 확장 가능)로 전환.

## 사전 확인 완료
- 서비스 계정: `anu2026@insuwiki-j2h.iam.gserviceaccount.com`
- 키 파일: `/home/jay/.config/gcloud/service-accounts/insuwiki-j2h-fa603f4f75f5.json`
- InsuRo Drive 폴더 ID: `1NEvqk0QZcJUO_6jBatgZdu-vXUHQeCvU`
- 접근 테스트: ✅ 성공 (편집자 권한 확인됨)
- 기존 `gdrive.py` 모듈 존재 (ensure_folder, upload_pdf 함수)

## ★ 핵심 설계 포인트

### 1. 폴더 구조 (월별 자동 구분)
```
InsuRo (root: 1NEvqk0QZcJUO_6jBatgZdu-vXUHQeCvU)
├── fcpa/              ← 기존 유지
├── newsletters/       ← 소식지 루트
│   ├── 2026-03/       ← 월별 하위 폴더 (자동 생성)
│   │   ├── DB손보_소식지_0304.pdf
│   │   └── 한화생명_소식지_0301.pptx
│   └── 2026-04/
│       └── ...
└── premium-data/      ← 보험료 데이터 루트
    ├── 2026-03/
    │   └── 3대질병진단비_보험료_2603.pptx
    └── 2026-04/
        └── ...
```

- 사용자가 업로드 시 선택한 `month_key` (예: "2026-04")로 하위 폴더 자동 생성
- `gdrive.py`의 `ensure_folder()` 활용 → 폴더 없으면 자동 생성, 있으면 재사용

### 2. 업로드 플로우 (서버 경유)
```
프론트 (AdminNewsletters.tsx / AdminPremiumData.tsx)
  ↓ 파일을 서버 API로 전송 (multipart/form-data)
서버 (main.py — /api/insuro/upload-to-drive)
  ↓ 1. 파일 수신
  ↓ 2. Google Drive에 업로드 (서비스 계정)
  ↓ 3. Drive 파일 ID/URL 반환
  ↓ 4. Supabase DB에 file_url(Drive URL) 저장
  ↓ 5. 텍스트 추출 (task-2213에서 구현한 parse-premium-file 로직)
프론트
  ↓ 응답 받고 UI 업데이트
```

### 3. gdrive.py 확장
기존 `gdrive.py`는 OAuth2 기반인데, **서비스 계정 기반으로 전환/추가**해야 함:

```python
def get_drive_service_sa():
    """서비스 계정 기반 Drive 서비스 (OAuth2 불필요, 만료 없음)"""
    from google.oauth2 import service_account
    SA_PATH = os.environ.get("GOOGLE_DRIVE_SA_PATH", 
              "/home/jay/.config/gcloud/service-accounts/insuwiki-j2h-fa603f4f75f5.json")
    creds = service_account.Credentials.from_service_account_file(
        SA_PATH, scopes=["https://www.googleapis.com/auth/drive.file"]
    )
    return build("drive", "v3", credentials=creds)
```

### 4. 파일 업로드 함수 확장
```python
def upload_file_to_drive(file_bytes: bytes, filename: str, 
                         file_type: str, month_key: str) -> str:
    """
    파일을 Drive에 업로드하고 공유 URL 반환
    - file_type: "newsletter" 또는 "premium"
    - month_key: "2026-04" 형태
    """
    service = get_drive_service_sa()
    root_id = os.environ.get("INSURO_GOOGLE_DRIVE_FOLDER_ID")
    
    # 1. 타입별 루트 폴더
    type_folder = "newsletters" if file_type == "newsletter" else "premium-data"
    type_id = ensure_folder(service, root_id, type_folder)
    
    # 2. 월별 하위 폴더
    month_id = ensure_folder(service, type_id, month_key)
    
    # 3. 파일 업로드
    media = MediaIoBaseUpload(io.BytesIO(file_bytes), mimetype=guess_mimetype(filename))
    uploaded = service.files().create(
        body={"name": filename, "parents": [month_id]},
        media_body=media, fields="id"
    ).execute()
    
    # 4. 공유 설정 (anyone reader)
    service.permissions().create(
        fileId=uploaded["id"], body={"type": "anyone", "role": "reader"}
    ).execute()
    
    return f"https://drive.google.com/file/d/{uploaded['id']}/view"
```

### 5. 프론트엔드 변경
- 현재: 프론트에서 Supabase Storage에 직접 업로드 → 서버에 파싱 요청
- 변경: 프론트에서 서버 API에 파일 전송 → 서버가 Drive 업로드 + 파싱 일괄 처리

```tsx
// AdminNewsletters.tsx / AdminPremiumData.tsx
// Before: supabase.storage.from("newsletters").upload(...)
// After:
const formData = new FormData();
formData.append("file", file);
formData.append("month_key", monthKey);
formData.append("file_type", "newsletter"); // or "premium"
formData.append("company_name", selectedCompany || "");

const resp = await fetch(`${INSURO_API_BASE}/api/insuro/upload-to-drive`, {
  method: "POST",
  headers: { Authorization: `Bearer ${session.access_token}` },
  body: formData,
});
```

### 6. DB 저장
- `file_url` 필드에 Supabase Storage URL 대신 Google Drive URL 저장
- 기존 데이터는 그대로 유지 (마이그레이션 불필요)

### 7. "원본 파일" 링크
- 현재 UI에 "원본 파일" 링크가 있음 → Drive URL로 자동 전환
- Drive URL 클릭 시 Google Drive 뷰어에서 파일 열림

## affected_files
- `server/gdrive.py` (수정 — 서비스 계정 함수 + upload_file_to_drive 추가)
- `server/main.py` (수정 — /api/insuro/upload-to-drive 엔드포인트 추가)
- `src/pages/AdminNewsletters.tsx` (수정 — Supabase Storage → 서버 API)
- `src/pages/AdminPremiumData.tsx` (수정 — Supabase Storage → 서버 API)

## 환경변수 (서버)
- `INSURO_GOOGLE_DRIVE_FOLDER_ID` — InsuRo Drive 폴더 ID (이미 .env.keys에 있음)
- `GOOGLE_DRIVE_SA_PATH` — 서비스 계정 키 파일 경로 (기존 insuwiki SA 재사용)

## 검증 시나리오
1. 소식지 관리 → PDF 업로드 (2026-04 선택) → Google Drive에 `newsletters/2026-04/` 폴더 생성 + 파일 업로드 확인
2. 보험료 데이터 → PPTX 업로드 (2026-03 선택) → Google Drive에 `premium-data/2026-03/` 폴더 생성 + 파일 업로드 확인
3. "원본 파일" 링크 클릭 → Google Drive 뷰어에서 파일 열림
4. 텍스트 추출 + 보험사 자동 감지 정상 동작 (task-2213 로직 유지)
5. Supabase Storage에는 파일 업로드 안 됨 (Drive만 사용)
6. npm run build 성공
7. 서버 재시작 후 엔드포인트 정상 응답
