# Task-514 완료 보고서: Docling 파싱 캐시 + 한국어 FTS 고도화

## SCQA

**S**: libs/doc_parser.py의 Docling PDF 파싱은 건당 약 48초 소요되며, libs/search.py의 키워드 검색은 'simple' tsvector 기반으로 한국어 부분 매칭이 불가능하다.

**C**: 동일 문서 재처리 시 48초가 매번 소요되어 사용자 경험이 저하되고, "보험" 검색 시 "보험설계사"가 매칭되지 않아 한국어 검색 정확도가 낮다.

**Q**: 캐시로 재처리 시간을 0.01초로 단축하고, trigram 기반 FTS로 한국어 부분 매칭을 지원할 수 있는가?

**A**: SHA-256 기반 파일 캐시(doc_parser.py)와 pg_trgm 기반 trigram 인덱스 + ILIKE fallback(search.py)을 구현하여 해결했다. pytest 103건 전체 통과, pyright 에러 0건.

---

## 작업 내용

### 1. Docling 파싱 결과 캐시 (TODO #1)
- `doc_parser.py`에 SHA-256 content hash 기반 로컬 파일 캐시 추가
- 캐시 디렉토리: `/home/jay/workspace/libs/.parse_cache/`
- 캐시 키: `hashlib.sha256(file_bytes).hexdigest()`
- 캐시 값: ParseResult를 JSON으로 직렬화/역직렬화
- `parse_pdf(file_bytes, *, use_cache=True)` — 기본값 True, False로 강제 재파싱 가능
- `clear_cache()` — 캐시 전체 삭제 함수
- 캐시 로드 실패 시 graceful fallback (재파싱)

### 2. 한국어 FTS 고도화 (TODO #2)
- SQL 마이그레이션 `002_korean_fts.sql` 생성 (Supabase 미실행)
  - pg_trgm 확장 활성화
  - GIN trigram 인덱스 `idx_chunks_content_trgm` 추가
  - trigram 임계값 0.3 → 0.1 하향 (한국어 짧은 단어 매칭 위해)
  - hybrid_search() v2: tsvector → trigram similarity() + ILIKE fallback
- search.py `keyword_search()`: RPC 결과 비어있을 때 Supabase ILIKE fallback 추가

---

## 생성/수정 파일 목록

- `/home/jay/workspace/libs/doc_parser.py` — 캐시 로직 추가 (use_cache, clear_cache 등)
- `/home/jay/workspace/libs/search.py` — keyword_search ILIKE fallback 추가
- `/home/jay/workspace/libs/migrations/002_korean_fts.sql` — 신규 생성
- `/home/jay/workspace/libs/tests/test_doc_parser.py` — TestParseCache 클래스 6개 테스트 추가
- `/home/jay/workspace/libs/tests/test_search.py` — TestKoreanKeywordSearch 클래스 4개 테스트 추가
- `/home/jay/workspace/libs/.gitignore` — 신규 생성 (.parse_cache/)

---

## 테스트 결과

pytest 103건 전체 통과 (16.12s):
- 기존 테스트 93건: 통과
- 신규 캐시 테스트 6건 (TestParseCache): 통과
- 신규 한국어 검색 테스트 4건 (TestKoreanKeywordSearch): 통과

pyright 에러 0건, black/isort 포매팅 준수.

---

## 발견 이슈 (3건)

1. **ILIKE 특수문자 이스케이프 미처리 (WARN)**: search.py의 ILIKE fallback에서 `%{query}%` 사용 시 쿼리에 `%`나 `_`가 포함되면 LIKE 패턴으로 해석됨. Supabase SDK 레벨에서 SQL 인젝션은 방지되나, 패턴 특수문자 처리는 추후 개선 필요.

2. **캐시 동시성 미처리 (WARN)**: 동일 파일을 동시에 여러 프로세스에서 파싱할 경우 캐시 파일 쓰기 충돌 가능. 현재 단일 프로세스 환경에서는 문제 없으나, 멀티프로세스 환경에서는 file lock 추가 필요.

3. **pyrightconfig.json 추가됨 (INFO)**: 불칸이 pyright 경로 해결을 위해 `/home/jay/workspace/libs/pyrightconfig.json`을 생성함. 기존 워크스페이스 설정과 충돌 가능성은 낮음.

---

## 셀프 QC

- [x] 1. 다른 파일 영향: parse_document()가 parse_pdf()를 호출하나, use_cache가 keyword-only + 기본값 True이므로 기존 호출 호환
- [x] 2. 엣지 케이스: 빈 bytes → ValueError, 캐시 손상 → 자동 삭제 후 재파싱, ILIKE fallback 실패 → warning + 빈 결과
- [x] 3. 작업 지시 일치: 캐시 전략/디렉토리/TTL/use_cache/clear_cache/SQL/search.py 모두 지시사항 충족
- [x] 4. 에러 처리: 캐시 로드 실패 graceful, ILIKE 실패 시 warning, 기존 예외 처리 유지
- [x] 5. 테스트 커버리지: 캐시 히트/미스/강제재파싱/클리어/디스크저장/결과일치 + 한국어 기본/금소법/fallback/미실행

---

## 비고
- SQL 마이그레이션은 파일만 생성됨 (Supabase 미실행). 배포 시 수동 실행 필요.
- 기존 인터페이스(parse_pdf, parse_document, ParseResult, semantic_search, keyword_search, hybrid_search) 모두 하위호환 유지.
