- 해커뉴스에서 사용자가 로컬 환경에서 Retrieval-Augmented Generation(RAG) 을 어떻게 구현하는지 묻는 질문
- 로컬 RAG에서 벡터DB 없이도 SQLite FTS5·BM25·grep 같은 텍스트 검색으로 충분히 굴리는게 가능하다는 흐름이 강하게 나타남
- 코드 검색은 임베딩이 느리고 노이즈가 크다는 경험담이 많고, BM25+트라이그램 같은 키워드 기반이 더 낫다는 주장도 다수 보임
- 벡터 검색이 필요할 때도 Postgres+pgvector, SQLite에 벡터 BLOB 저장, FAISS 메모리 적재처럼 가벼운 구성으로 해결하는 사례가 이어짐
- BM25+벡터를 합치는 하이브리드 검색과 RRF(Reciprocal Rank Fusion), 리랭킹, 멀티쿼리 확장 같은 조합으로 검색 품질 향상 가능
- “RAG=벡터DB”로 고정되지 않고, 문서 유형·규모·운영 부담에 따라 단순 검색→하이브리드→에이전트형으로 선택하는 경향이 드러남
검색 단계에서의 공통 결론
- 벡터DB나 그래프가 필수라는 전제보다, 기존 인프라·파일 타입·요구 성능에 맞춰 단순하게 시작하는 접근이 다수임
- 에이전트가 파일시스템이나 API를 직접 조회하는 방식이 설정·유지보수는 쉬우나 약간 느릴 수 있다는 언급 존재
- “RAG가 LLM에 넘기는 것은 검색 결과의 짧은 텍스트 조각” 이라는 인식이 성능 개선 포인트를 검색 품질로 돌리는 계기
- “RAG 정의”를 두고 벡터DB가 없더라도 retrieval+generation이면 RAG라는 반응과, 보통 벡터DB를 전제로 부르는 경우가 많다는 반응이 함께 존재함
임베딩 모델 및 벡터 검색
- MongoDB에서 개발한 mdbr-leaf-ir 임베딩 모델은 CPU 전용으로 동작하며, 해당 크기 모델 중 여러 리더보드에서 1위 기록
- 표준 2vCPU 서버에서 초당 약 22개 문서, 120개 쿼리 처리 가능
- BEIR 벤치마크에서 53.55점 기록 (all-MiniLM-L12-v2는 42.69점)
-
model2vec/minish 같은 정적 워드 임베딩은 추론 속도가 더 빠르지만 검색 정확도는 낮음
- 토큰화 + 룩업 테이블 + 평균만 수행하므로 트랜스포머 기반보다 빠름
- Meta-Llama-3-8B로 텍스트 청크별 벡터 생성 후 SQLite BLOB 컬럼에 저장하고, FAISS로 검색하는 방식도 활용됨
- 500만 청크 기준 약 40GB 메모리 사용
- A6000에서 faiss-gpu가 매우 빠르고, M1 Ultra의 faiss-cpu는 느리지만 하루 몇 번 쿼리 수준에는 충분
코드 검색에 대한 권장사항
- 코드에는 벡터 데이터베이스 사용을 지양하고, BM25+트라이그램 조합 권장
- 임베딩은 느리고 코드에 적합하지 않음
- 리랭커가 없으면 노이즈가 커지고, 파일 재인덱싱 부담이 큼
- 검색 응답 속도가 빠르고 결과 품질도 우수
- PostgreSQL에서 plpgsql_bm25로 BM25 검색 구현 가능
- pgvector와 결합한 하이브리드 검색 + Reciprocal Rank Fusion 지원
- 파일 경로 + 시그니처에 임베딩을 적용하고 BM25와 퓨전하면 좋은 결과 획득 가능
- gpt-oss 20B를 ripgrep과 함께 while 루프로 실행하는 에이전틱 방식도 효과적
데이터베이스 기반 솔루션
-
SQLite FTS5: 마크다운 파일 기반 문서에 적합, 벡터 DB 없이도 RAG 구현 가능
- 각 파일에 짧은 설명 필드를 두고 키워드 검색으로 문서 탐색
- SQLite에 fp16 벡터를 BLOB로 저장하고, 필터로 부분집합을 만든 뒤 메모리에서 유사도 계산을 돌리는 설계도 가능
- sqlite-vec, sqlite-vector, vec0, sqlite의 bm25 같은 선택지도
- “SQLite가 놀랄 만큼 잘 됨”
-
PostgreSQL + pgvector: 기존 Postgres 지식 활용 가능, 운영팀 인수인계 용이
- 하이브리드 BM25, 멀티쿼리 확장, 리랭킹 지원하는 llmemory 라이브러리도 있음
-
LanceDB: 임베디드 벡터 DB로 편리하게 사용 가능
- Ollama의 nomic-embed-text 임베딩과 함께 활용
- DuckDB: 벡터 유사도 검색 확장 기능 제공, 3GB 이하 소규모 프로젝트에 적합
- Meilisearch, Typesense, Manticore: Elasticsearch/OpenSearch보다 운영이 단순
하이브리드 및 에이전틱 검색
- nori(usenori.ai): SQLite + vec0 + fts5로 시맨틱 및 단어 검색 결합
- Turbopuffer: 벡터 + BM25 하이브리드 검색 지원
- 에이전틱 검색과 텍스트 검색 조합만으로도 상당히 좋은 결과 획득
- 벡터 검색과 그래프 RAG 추가 시 약간의 속도 및 품질 향상 가능
- Claude Code/Codex는 내부적으로 ripgrep 사용
- 파일 경로에 임베딩을 적용해도 효과적, BM25와 퓨전하면 더욱 개선
BM25 활용 사례
-
shebe: BM25 기반 코드베이스 인덱싱 및 검색 CLI/MCP 도구
- 리팩토링 워크플로우에 특히 유용 (예: Istio 업그레이드 시 변경 필요 위치 열거)
- 85%의 경우 벡터 DB 없이 태그 매칭만으로 충분
- 운영자들이 입력과 문서 모두에 태그를 추가하여 100% 매칭 달성
- 대부분의 벡터 DB는 "못 찾는 문제를 해결하려는 망치"라는 의견
특수 도구 및 라이브러리
- qmd: 마크다운 파일 검색용 CLI 도구, fzf보다 퍼지 쿼리 결과 우수
- ck: Rust 기반 시맨틱 grep 도구
-
Kiln: 드래그 앤 드롭으로 파일 추가, 다양한 설정 비교 가능
- 추출 방법, 임베딩 모델, 검색 방식(BM25, 하이브리드, 벡터) 비교 지원
- 검색 정확도 평가 및 평가 데이터셋 자동 생성 기능
-
libragen: 버전 관리되는 RAG 콘텐츠 라이브러리 생성용 CLI/MCP 서버
- GitHub 저장소를 RAG DB로 변환 가능
- piragi: 간단한 Python RAG 라이브러리, 로컬/S3/API 등 다양한 소스 지원
- ragtune: 로컬 RAG 검색 디버깅 및 벤치마킹용 CLI 도구
문서 처리 및 OCR
-
discovery: Qwen-3-VL-8B로 문서 OCR, ChromaDB로 벡터 저장
- BM25 + 임베딩 하이브리드 RAG 구현
- docling: 문서 추출용 도구, 여러 RAG 프로젝트에서 활용
- PDF 변환 시 테이블, 다중 컬럼, 페이지 걸친 테이블 처리가 어려움
- Mistral OCR 모델이 가장 좋은 결과 제공 (비공개 모델)
메모리 및 컨텍스트 관리
- RAG가 LLM에 전달하는 것은 짧은 검색 결과 문자열뿐
- 작은 모델에서는 TOP_K=5 정도가 한계, 그 이상은 컨텍스트 망각 발생
- 파일과 폴더를 사전 요약하는 방식으로 개선 가능
- Sonnet + 1M 컨텍스트 윈도우로 모든 내용을 컨텍스트에 넣는 방식도 사용
- 세션 파일에 대한 시맨틱 검색으로 Claude Code용 메모리 시스템 구축 사례
엔터프라이즈 및 대규모 활용
- 하루 30만 건 고객 상호작용 처리 시 지연시간과 정밀도가 중요
- 임베딩 + 전문 검색 + IVF-HNSW 하이브리드 접근법 사용
- 약 600개 분산 시스템의 정보 확산 관리가 과제
- KAG(Knowledge Augmented Generation) 접근법으로 비즈니스 규칙 매핑 실험 중
- 50만 건 이상 뉴스 기사에 대해 Postgres 벡터 DB로 완전 로컬 RAG 구현 성공
기타 도구 및 접근법
- AnythingLLM: 문서용 벡터 DB 번들 제공
- LibreChat: 문서용 벡터 DB 번들 포함
- ChromaDB: Obsidian 확장으로 시맨틱/하이브리드 검색 구현
- SurrealDB: 로컬 벡터화와 결합하여 사용
- OData 쿼리 인터페이스: LLM에 도구로 제공 시 효과적, 4만 행 Excel 분석 가능
- Nextcloud MCP Server: Qdrant를 벡터 DB로 사용, 개인 문서에 시맨틱 검색 제공
-
LSP(Language Server Protocol): Claude Code에 추가되었으나 현재 버그 존재
- TreeSitter가 더 유용할 수 있음 (심볼명으로 조회, 정의/사용 위치 탐색)