"신경망 뭔가에 손 뻗기 전에 기억해: 40년 된 키워드 순위 함수가 이름·전문 용어·정확한 구절에선 여전히 이겨. GPU 는 절대 필요 없어."
역색인
전문 검색이 빠른 건 자료구조 뒤집기 하나 덕분이야. 순진한 배치는 각 문서를 담긴 단어로 매핑해; 단어를 찾으려면 모든 문서를 훑어야 해. 역색인은 그걸 뒤집어: 각 단어를 그걸 담은 문서(와 위치) 목록으로 매핑해. 이제 "afogato" 가 나타나는 모든 곳을 찾는 게 코퍼스 전체 스캔이 아니라 단일 조회야. SQLite 의 FTS5 확장이 바로 이 구조를, DB 바로 안에서, 외부 서비스 없이 짓고 쿼리해.
BM25: 모델 없는 순위
매치를 찾는 건 일의 절반이고, 순위 매기는 게 나머지 절반이고, 그게 BM25 가 하는 거야. 매칭되는 각 문서를 세 직관으로 점수 매겨:
- 단어 빈도, 포화와 함께. 네 단어를 더 언급하는 문서가 더 관련 있어 — 근데 수확 체감으로. 열 번째 등장은 아홉 번째에 거의 안 더해서, 페이지가 단어 반복만으론 못 이겨.
- 역문서빈도. 드문 단어가 흔한 것보다 더 많은 신호를 지녀. "afogato" 매칭이 "the" 매칭보다 훨씬 많이 알려줘서, 드문 매치는 가중이 올라가.
- 길이 정규화. 긴 문서는 자연히 더 많은 단어를 담아; BM25 는 길이를 할인해서 장황한 페이지가 짧고 핵심 있는 걸 못 이기게 해.
셋 다 인덱스 위 순수 산수야. 임베딩 없음, 학습 없음, GPU 없음 — 그리고 1990년대부터 조용히 훌륭했어.
키워드 검색이 여전히 중요한 이유
벡터 검색이 검색의 유행하는 절반이지만, 흐려. '비슷한 뜻인 걸 찾아' 엔 뛰어나고 '이 정확한 단어를 찾아' 엔 서툴러. 이름, 에러 코드, 드문 전문 용어, 특정 함수명, 정확한 표현 — 이게 바로 임베딩이 또렷한 쿼리를 흐린 이웃으로 번지게 하는 지점이야. BM25 는 그걸 딱 맞혀. 진짜 엔진에서 키워드 검색은 참아주는 레거시 경로가 아냐. 날카롭게 유지하는 정밀 도구야.
실제론 어떻게 생겼나
FTS5 는 순위를 order by 할 수 있는 일급 함수로 노출해. 텍스트 위에 가상 테이블을 만들고, MATCH 표현으로 쿼리하고, 내장 bm25() 점수로 정렬해. 전체가 로컬 파일에 대한 SQL 쿼리야 — 빠르고, 결정론적이고, 완전히 오프라인. 이게 더 화려한 검색이 앉는 지루하고 믿을 만한 기반암이야.