# InsuRo → InsuWiki 소식지 데이터 연계 (단방향 push)

## 작업 레벨: Lv.4

## 프로젝트 시스템 3문서
- DevSystem: `/home/jay/workspace/memory/plans/anu-guide-system/plan.md`
- InsuWiki: `/home/jay/workspace/memory/plans/insuwiki/` (확인 후 참조)

## 프로젝트
- InsuRo: `/home/jay/projects/InsuRo` (서버: `/home/jay/projects/InsuRo/server`)
- InsuWiki: `/home/jay/projects/insuwiki/nextapp` (Next.js + Firebase/Firestore)
- InsuWiki Functions: `/home/jay/projects/insuwiki/functions`

## ★★★ 핵심 규칙
**데이터 흐름: InsuRo → InsuWiki 단방향 push만 허용**
**InsuWiki DB → InsuRo 방향 절대 금지**

## 배경
인슈로에서 소식지/보험료 PDF를 업로드하면 텍스트가 추출되고 AI 분석이 가능해짐. 이 데이터를 인슈위키 지식으로도 활용하여, 인슈위키에서 보험사별 최신 소식지 정보를 확인할 수 있게 함.

## 구현 상세

### Phase 1: InsuWiki 수신 API 엔드포인트

#### 1-1. InsuWiki Next.js API Route 추가
경로: `/home/jay/projects/insuwiki/nextapp/src/app/api/newsletter-sync/route.ts`

```typescript
// POST /api/newsletter-sync
// InsuRo 서버에서 소식지 분석 완료 시 호출

import { NextRequest, NextResponse } from 'next/server';
import { getFirebaseAdmin } from '@/lib/firebase-admin';
import { getFirestore } from 'firebase-admin/firestore';

export async function POST(req: NextRequest) {
  // 1. API 키 인증 (인슈로 서버만 호출 가능)
  const apiKey = req.headers.get('x-api-key');
  if (apiKey !== process.env.INSURO_SYNC_API_KEY) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const body = await req.json();
  // body: {
  //   company_name: "ABL생명",
  //   month_key: "2026-03",
  //   title: "GA소식지 2026년 3월",
  //   extracted_text: "...",
  //   source: "insuro_newsletter",  // or "insuro_premium"
  //   source_id: "uuid",  // InsuRo DB의 레코드 ID
  // }

  // 2. Firestore에 저장
  getFirebaseAdmin();
  const db = getFirestore();
  
  await db.collection('newsletter_updates').doc(body.source_id).set({
    company_name: body.company_name,
    month_key: body.month_key,
    title: body.title,
    extracted_text: body.extracted_text,
    source: body.source,
    synced_at: new Date(),
  });

  return NextResponse.json({ status: 'ok', id: body.source_id });
}
```

#### 1-2. InsuWiki 환경변수
- `INSURO_SYNC_API_KEY`: 인슈로↔인슈위키 통신용 공유 키 (양쪽 .env에 동일한 값)

### Phase 2: InsuRo 서버에서 push 호출

#### 2-1. 소식지/보험료 업로드 완료 후 InsuWiki에 자동 push
`server/main.py`의 `/api/insuro/upload-to-drive` 엔드포인트에서, 텍스트 추출 성공 후:

```python
import requests

INSUWIKI_SYNC_URL = os.environ.get("INSUWIKI_SYNC_URL", "https://insuwiki.vercel.app/api/newsletter-sync")
INSURO_SYNC_API_KEY = os.environ.get("INSURO_SYNC_API_KEY", "")

async def push_to_insuwiki(record_id, company_name, month_key, title, extracted_text, source):
    """소식지/보험료 데이터를 인슈위키에 push (비동기, 실패해도 무시)"""
    try:
        resp = requests.post(INSUWIKI_SYNC_URL, json={
            "company_name": company_name,
            "month_key": month_key,
            "title": title,
            "extracted_text": extracted_text[:10000],  # 최대 10000자
            "source": source,
            "source_id": record_id,
        }, headers={
            "x-api-key": INSURO_SYNC_API_KEY,
        }, timeout=10)
        logger.info(f"InsuWiki sync: {resp.status_code}")
    except Exception as e:
        logger.warning(f"InsuWiki sync failed (non-blocking): {e}")
```

- **실패해도 인슈로 업로드에 영향 없음** (non-blocking)
- 텍스트 최대 10000자 (큰 문서는 앞부분만)

### Phase 3: InsuWiki UI — "최근 소식지 업데이트" 표시

#### 3-1. Firestore 컬렉션
- `newsletter_updates`: 소식지/보험료 업데이트 데이터
  - `company_name`, `month_key`, `title`, `extracted_text`, `source`, `synced_at`

#### 3-2. InsuWiki 페이지에 "최근 업데이트" 섹션
보험사별 위키 페이지 또는 별도 "소식지 업데이트" 페이지에서:
- 최근 3개월 소식지 업데이트 목록 표시
- 보험사명, 발행월, 제목, 핵심 요약
- 펼치기 → 전체 추출 텍스트

#### 3-3. InsuWiki 컴포넌트 추가
- `nextapp/src/components/NewsletterUpdates.tsx` (신규)
- Firestore `newsletter_updates` 컬렉션 조회 → 보험사별 그룹화 → 최신순 표시

### Phase 4: 통합 테스트

#### 4-1. 전체 플로우 테스트
1. InsuRo 어드민 → 소식지 PDF 업로드
2. 텍스트 추출 + Google Drive 저장 + DB 저장
3. InsuWiki API push (자동)
4. InsuWiki Firestore에 데이터 확인
5. InsuWiki 페이지에서 "최근 업데이트" 표시 확인

## affected_files

### InsuRo (서버)
- `server/main.py` (수정 — upload-to-drive 후 push_to_insuwiki 호출)
- `server/.env` (수정 — INSUWIKI_SYNC_URL, INSURO_SYNC_API_KEY 추가)

### InsuWiki (Next.js)
- `nextapp/src/app/api/newsletter-sync/route.ts` (신규 — 수신 API)
- `nextapp/src/components/NewsletterUpdates.tsx` (신규 — UI 컴포넌트)
- `nextapp/.env` (수정 — INSURO_SYNC_API_KEY 추가)
- `firestore.rules` (수정 — newsletter_updates 컬렉션 규칙)

## 환경변수 (양쪽)
- `INSURO_SYNC_API_KEY`: 랜덤 UUID 생성하여 양쪽에 동일 설정
- `INSUWIKI_SYNC_URL`: InsuWiki Vercel 배포 URL + /api/newsletter-sync

## ★ 주의사항
- InsuWiki가 InsuRo DB를 직접 읽는 코드 절대 금지
- push 실패 시 인슈로 업로드에 영향 없어야 함 (try/except + non-blocking)
- 인슈위키 Firestore에 저장된 데이터는 인슈위키 자체 데이터로 취급

## 검증 시나리오
1. 소식지 PDF 업로드 → InsuWiki Firestore에 데이터 자동 push 확인
2. 보험료 PPTX 업로드 → InsuWiki Firestore에 데이터 자동 push 확인
3. InsuWiki "최근 업데이트" 페이지에서 push된 데이터 표시
4. push 실패 시 → 인슈로 업로드는 정상 완료 (non-blocking)
5. API 키 없이 InsuWiki API 호출 → 401 차단
6. InsuRo npm run build 성공
7. InsuWiki npm run build 성공