ADR 0039 — RAG CLI 마이그레이션 (Cloud Function 의존 제거 + 슬래시 커맨드)
상태: ship · 2026-05-08 관련 PR: PR-Sync-0 ~ PR-Sync-9 (#1834~#1843) + PR-Sync-followup (#1844) 관련 ADR: 0021 (Platform RAG), 0024 (V2 검색 품질), 0028 (pure/mutation 분리), 0029 (Firebase fail-loud), 0032 (RAG 평가 인프라)
배경
기존 RAG 인프라 (ADR 0021) 는 Cloud Function 자동화 중심이었음:
scheduledFetchLawGoKr(cron, 매일 02:00 KST) — 법제처 데이터 자동 syncmanualIncrementalFetchLawGoKr(callable) — ops 콘솔 "지금 실행" 버튼onPublicDocumentCreated(Firestore onCreate trigger) — 적재 시 임베딩 자동 생성
운영 결함 누적:
- cron page=1 한계 — 매일 page 1 만 fetch → 신규 판례가 page 1 에 등장 안 하면 영원히 누락 (5-04
5-07 매일 created=02) - 자동 trigger 디버깅 어려움 — onCreate 1회만 발화, 실패 시 doc 가 임베딩 없이 남음
- 운영 가시성 부재 — ops 콘솔 단일 진입점, "어디까지 sync 됐는지" 추적 불가
- 모델 필드명 drift —
embedding.versionvsembedding.modelVersion두 라이팅 경로가 다른 필드명
결정
production Firestore RAG 는 유지하되, Cloud Function trigger 의존을 제거하고 사용자 명시적 수동 sync 흐름 + Claude Code 슬래시 커맨드로 일원화한다.
폐기
scheduledFetchLawGoKr(cron)manualIncrementalFetchLawGoKr(callable)onPublicDocumentCreated(자동 임베딩 trigger)apps/ops/.../PublicRagScheduleStatusCard.tsx(cron health 카드)publicRagScheduleLog새 row 작성 (기존 데이터 보존)
신규
- scripts/sync-law-go-kr.ts — 통합 CLI (download + embed + upload + 워터마크)
- publicRagSyncWatermark/<watermarkId> Firestore 컬렉션 —
lastSyncedNativeIdsset 기록 - 6 Claude Code 슬래시 커맨드 +
/neohollo메타 hub - citation-existence 모듈 — korean-law-mcp
verify_citations패턴 차용 (환각 탐지)
유지
- Firestore vector store +
findNearest()web 검색 흐름 - Vertex AI text-embedding-004 (768-dim)
publicDocuments+publicDocumentsRaw2 컬렉션 구조fetchAndIngestLawGoKr(단건 query callable, ops 콘솔용)retryPublicDocEmbedding·bulkRetryPublicDocEmbeddings(수동 재시도 callable)- ADR 0032 평가 인프라 (
packages/business-logic/rag-eval/)
결정 근거
| 차원 | Cloud Function 자동화 (이전) | CLI + 슬래시 (현재) |
|---|---|---|
| 신규 데이터 회수 | page=1 만 (정체 위험) | page=1..N + 워터마크 set diff |
| 디버깅 | onCreate 1회 발화, 추적 어려움 | 동기 호출, 결과 즉시 |
| 운영 가시성 | publicRagScheduleLog 1일 1줄 | 워터마크 + lastRunStats + ASCII chart |
| 사용자 통제 | cron 자동 (사용자 무관) | 명시적 호출 |
| Cloud Function 비용 | cron + 매 doc embed × 2 함수 | 0 (CLI 만) |
| 환각 탐지 | 없음 | verifyCitations 모듈 |
트레이드오프
손실
- 자동화 사라짐 — 사용자가 매일 명시적으로
/sync-law호출 필요 - legal-news publish 흐름 변화 — publish 후 자동 임베딩 안 됨, 사용자가 ops
/public-rag의 retry 버튼 별도 클릭
이득
- 회수율 향상 — page=1..N + watermark 로 cron 의 page=1 한계 해결
- 운영 가시성 —
/rag-status한 번에 종합 진단 - 환각 탐지 — citation-existence 로 답변 신뢰도 측정 (Phase 0 Week 4 게이트와 연동)
- MCP 호환 — verify_citations / impact_map 패턴 차용으로 외부 도구 호환성 + 차별화 layer 추가 가능
- Cloud Function 운영 비용 ↓ — 3 함수 폐기 (scheduled + manual + onCreate trigger)
영향
사용자 (변호사·법무사)
- 영향 0 — web 검색 (apps/web) 흐름 그대로
운영자 (masterAdmin)
- 일일 운영 패턴 변화: ops 콘솔 클릭 → Claude Code 슬래시 커맨드
- 새 도구:
/neohollo메타 hub 로 모든 명령 reference
개발자
- 새 architecture: CLAUDE.md +
apps/docs/content/operations/rag-cli-tools.md업데이트 - 새 SSoT:
scripts/lib/embed-input-prepare.ts(4번째 미러, drift gate 32 테스트) - 새 패턴: 신규 doc 적재 시 직접 임베딩 (onCreate trigger 의존 금지)
Firestore
- 신규 컬렉션:
publicRagSyncWatermark/ - 폐기 컬렉션 (writes 0):
publicRagScheduleLog/(기존 데이터 보존) - 변경 schema:
embedding.version단일 (modelVersion 폐기, 마이그레이션 3,921 docs)
Cloud Functions
- 3 함수 삭제 → deploy 시 cloud 에서 자동 제거
- 1 함수 (
fetchAndIngestLawGoKr) 임베딩 직접 처리로 수정
검증 결과 (2026-05-08 ship 시점)
- publicDocuments 7,853 docs · 100% embedded · pending 0 · error 0
- 임베딩 모델 필드명 drift 0 (마이그레이션 3,921 docs)
- 정규화 prefix 결함 fix (
[N]제거 → 환각 탐지 false positive 감소) - 환각 탐지 검증: 상법 401조의2 제7항 = paragraph_missing 정확 ✓
- 영향 그래프 검증: 민법 103조 → 21건 인용 판례 ✓
후속 작업
- PR-Sync-7b: impact_map 정방향 + 사무소 layer (legacyDocuments) — MCP 차별화
- PR-Sync-8b: korean-law-mcp stdio 자동 spawn (paste 없이 자동 비교)
- PR-A 후속: 정규화 lawName 컨텍스트 추론
- 호·목 환각 탐지: 현재 항까지만 — 호/목 단위 추가
- 사무소 RAG 집계: tenant-isolated
legacyDocuments검색 quality 측정 (ADR 0024 V2 연동)
참고
- RAG CLI 도구 운영 가이드
- Platform RAG 운영
- 슬래시 커맨드 reference:
.claude/commands/rag-vs-mcp.md(Docusaurus 외부, 리포지토리 직접 참조) - 코드:
scripts/sync-law-go-kr.ts,packages/business-logic/src/rag-eval/citation-existence.ts
변경 이력
- 2026-05-08: 초안 작성 (Accepted). RAG CLI 마이그레이션 + Cloud Function 3종 폐기 + 환각 탐지 + impact_map.
- 2026-05-13 (Amended): Feature Registry STALE drift 분석에서
publicRagScheduleLogcollection 이 코드 미사용 (주석 1건만 —apps/ops/.../public-rag/page.tsx:82"cron 폐기 후 더 안 채워짐") 으로 발견됨. deprecated collection — 기존 데이터 보존 목적으로만 유지. 새 row 작성 없음. paths.ts 추가 불필요. PublicRagScheduleStatusCard 가 readonly 로 기존 row 만 표시.