07. 정량 평가, 테스트 한계, 그리고 LocalLens 회고
LocalLens를 개발하면서 저는 검색 점수가 높은 모델을 고르는 것만으로 로컬 파일 검색기가 완성되지 않는다는 점을 배웠습니다. 파일을 처음 색인하는 데 걸리는 시간, 수정·삭제된 파일을 반영하는 방식, 검색한 파일을 실제로 여는 흐름까지 연결돼야 했습니다.
이 회고에서는 경량 모델을 선택한 이유와 PDF 검색에서 시도한 접근, 파일 동기화와 테스트에서 남긴 과제를 돌아봅니다. 아래 평가는 프로젝트 당시의 실험 조건과 구현 범위를 기준으로 정리했습니다.
점수와 인덱싱 시간을 함께 보고 모델을 선택하기
텍스트 인코더는 검색 점수만으로 선택하지 않았습니다. 문서가 많아질수록 색인 시간이 사용 경험에 직접 영향을 주기 때문에, 모델 크기와 처리 시간을 함께 고려해 경량 모델을 선택했습니다. 후보별 MIRACL 점수와 500개 문서 처리시간 표는 인코더 선택 과정에 모았습니다.
이 과정에서 배운 점은 검색 점수가 높은 모델과 로컬 환경에 적합한 모델이 반드시 같지는 않다는 것입니다. 당시 실행 조건의 결과를 다른 환경의 보장된 성능으로 일반화하지 않습니다.
PDF의 시각 정보를 검색에 반영하기
PDF에서는 본문 텍스트만 추출하면 표와 그래프, 이미지에 담긴 정보가 빠질 수 있었습니다. 이를 보완하기 위해 PyMuPDF로 추출한 텍스트에 VLM이 생성한 시각 요소 설명을 결합하고, 이 텍스트를 기존 TextEncoder에 전달했습니다.
평가에서는 text-only 방식과 text+VLM caption 방식을 비교했습니다. text+VLM에서 소폭이지만 일관된 개선을 관찰했으나, 이 결과를 모든 PDF에 적용할 수 있는 큰 폭의 성능 향상으로 보지는 않았습니다.
| 항목 | 당시 평가 범위 |
|---|---|
| 평가 방식 | text-only, OCR, text+OCR, text+VLM 비교 구조 |
| 평가 지표 | Recall@K, MRR, 처리 시간 |
| 관찰한 결과 | text+VLM에서 소폭이지만 일관된 개선 |
| 남은 한계 | 더 큰 평가셋과 재현 가능한 실험 결과 필요 |
이 과정에서 배운 점은 PDF를 새로운 임베딩 모델이 필요한 파일로만 볼 필요는 없다는 것이었습니다. 시각 요소를 검색 가능한 설명으로 바꾸면 기존 텍스트 검색 흐름을 활용할 수 있었습니다. 반면 설명의 품질과 외부 VLM 호출 시간에 영향을 받는다는 비용도 함께 생겼습니다.
검색 결과와 실제 파일 상태를 맞추기
제가 중요하게 다룬 설계 중 하나는 VectorStore의 역할 분리였습니다. FAISS는 유사한 벡터를 찾고, SQLite는 파일 경로와 수정 시간 등 메타데이터를 관리하도록 구성했습니다. 두 저장소는 같은 ID로 연결했습니다.
검색 결과에 파일이 나타나더라도 이미 삭제된 파일이거나 수정 전 내용을 가리킨다면 사용자는 원하는 결과를 얻기 어렵습니다. 그래서 신규·수정·삭제된 파일을 구분하고, 변경된 파일만 임베딩하는 동기화 흐름을 적용했습니다.
이 작업을 통해 검색 품질에는 모델의 유사도 점수뿐 아니라 실제 파일 상태를 반영하는 일관성도 포함된다는 점을 배웠습니다. 파일 유형별 인코더와 인덱스를 나누는 것, 결과의 파일 경로를 찾아 사용자가 바로 열 수 있게 하는 것도 같은 흐름의 일부였습니다.
다만 수정 시간인 mtime만으로는 모든 변경을 감지할 수 없습니다. 내용이 바뀌어도 수정 시간이 보존되면 놓칠 수 있고, FAISS와 SQLite를 갱신하는 중간에 실패하면 두 저장소의 상태가 어긋날 수 있습니다. 당시에는 로컬 데스크톱 프로토타입의 동기화 흐름을 구현했으며, 변경 감지의 정밀도와 중간 실패 복구는 후속 과제로 남겼습니다.
테스트를 작성하는 것과 통과 상태를 유지하는 것
인코더, 검색 엔진, PDF 처리기, VLM 클라이언트를 확인하는 테스트 코드를 구성했습니다. 그러나 당시 테스트에는 변경된 코드 구조를 따라가지 못한 클래스 참조가 일부 남아 있었습니다.
테스트 파일이 있다는 사실만으로 변경 후 동작까지 검증됐다고 볼 수는 없었습니다. 테스트 대상과 현재 인터페이스를 맞추고, 실제로 실행한 결과를 유지해야 한다는 점을 배웠습니다.
| 구분 | 당시 확인한 상태 |
|---|---|
| PDF processor 확인 코드 | 텍스트·이미지 추출, 결합 텍스트, VLM client 확인 흐름 |
| search flow 확인 코드 | sample directory 검색 흐름 확인 |
| encoder 테스트 | 변경된 코드 구조에 맞지 않는 일부 클래스 참조 |
| 남은 작업 | 테스트 정비와 변경 후 재실행 결과 관리 |
이 글에서 정리한 테스트 상태는 당시 프로젝트에 대한 회고입니다. 이후 변경된 코드 전체가 통과했다는 의미는 아닙니다.
로컬 중심 구조에 남은 외부 의존성
LocalLens는 로컬 파일을 색인하고 검색하지만, PDF 내부 이미지의 설명을 생성할 때는 외부 VLM을 호출했습니다. 따라서 완전한 오프라인 검색기를 구현한 것은 아니었습니다.
로컬 중심으로 처리할 수 있는 부분과 외부 호출이 필요한 부분을 구분하는 것이 중요했습니다. 특히 PDF 처리에서는 설명 품질뿐 아니라 호출 비용과 지연, 외부 서비스 의존성까지 함께 고려해야 했습니다.
| 한계 | 당시 상태 | 개선 방향 |
|---|---|---|
| 외부 VLM 호출 | PDF 내부 이미지 설명에 외부 호출 사용 | caption caching, local VLM 검토 |
| 모델 최적화 부족 | 양자화나 가속 엔진 적용은 다루지 못함 | ONNX, TensorRT, batching 검토 |
| 모달리티 확장 부족 | 텍스트, 이미지, PDF 중심 구현 | audio/video 검색은 후속 과제 |
| 평가 데이터 부족 | PDF 평가 결과 일반화 어려움 | 더 큰 평가셋과 재현 가능한 실험 로그 확보 |
다음 작업에서 가져갈 기준
LocalLens를 통해 저는 모델 선택, 파일 관리, 평가를 분리해서 끝낼 수 없다는 점을 배웠습니다. 모델이 적절해도 파일 상태가 맞지 않으면 검색 결과를 사용할 수 없고, 구현이 동작해도 평가 조건이 남아 있지 않으면 개선 효과를 비교하기 어렵습니다.
다음 개선에서는 PDF 설명 캐싱과 로컬 VLM을 검토해 반복 호출과 외부 의존성을 줄이고 싶습니다. 파일 동기화의 변경 감지와 복구도 보강할 과제입니다. 모델 최적화나 검색 대상 확장에 앞서, 같은 데이터와 조건에서 검색 품질·처리 시간·테스트 결과를 다시 확인할 수 있는 평가 흐름을 갖추는 것을 우선하겠습니다.
