# Ask HN: 로컬에서 RAG를 어떻게 구현하고 있나요?

> Clean Markdown view of GeekNews topic #25854. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=25854](https://news.hada.io/topic?id=25854)
- GeekNews Markdown: [https://news.hada.io/topic/25854.md](https://news.hada.io/topic/25854.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-01-16T05:32:36+09:00
- Updated: 2026-01-16T05:32:36+09:00
- Original source: [news.ycombinator.com](https://news.ycombinator.com/item?id=46616529)
- Points: 37
- Comments: 3

## Summary

해커뉴스에서 사용자가 로컬 환경에서 Retrieval-Augmented Generation(RAG) 을 어떻게 구현하는지 묻는 질문에 대한 답변을 정리했습니다. SQLite FTS5나 BM25, grep 같은 전통 검색으로도 충분한 성능을 얻을 수 있다는 댓글들이 많고, 필요 시 Postgres+pgvector나 FAISS 메모리 적재 등 **가벼운 구성**을 선호합니다. 특히 코드 검색에서는 임베딩보다 BM25+트라이그램 조합이 빠르고 안정적이라는 의견이 우세하며, 검색 품질 향상을 위해 하이브리드 검색·리랭킹·RRF 같은 기법도 함께 논의되고 있습니다.

## Topic Body

- 해커뉴스에서 사용자가 로컬 환경에서 **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가 더 유용할 수 있음 (심볼명으로 조회, 정의/사용 위치 탐색)

## Comments



### Comment 49353

- Author: tensun
- Created: 2026-01-16T21:37:51+09:00
- Points: 2

한글 잘되는지 의문 스럽네요.

### Comment 49531

- Author: ryj0902
- Created: 2026-01-20T13:12:13+09:00
- Points: 1

조악한 사내 RAG 시스템 성능을 보고 이런 포스트를 보니 관점이 약간씩 바뀌긴 하네요

### Comment 49284

- Author: neo
- Created: 2026-01-16T05:32:36+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46616529) 
- 우리 팀은 Q&A 데이터베이스를 운영 중임  
  질문과 답변을 **trigram 인덱스**와 **임베딩**으로 모두 색인해 Postgres에 저장함  
  검색 시 `pgvector`와 trigram 검색을 함께 사용하고, **관련도 점수**로 결과를 결합함  

- 검색 단계에서는 CPU 친화적인 고효율 텍스트 임베딩 모델을 개발했음  
  [MongoDB/mdbr-leaf-ir](https://huggingface.co/MongoDB/mdbr-leaf-ir) 모델로, 같은 크기 모델 중 **리더보드 1위**를 차지함  
  [Snowflake/snowflake-arctic-embed-m-v1.5](https://huggingface.co/Snowflake/snowflake-arctic-embed-m-v1.5) 모델과 호환 가능함  
  [search-sensei 데모](http://search-sensei.s3-website-us-east-1.amazonaws.com)를 통해 **semantic 검색 vs BM25 vs hybrid** 비교 가능함  
  예를 들어, 임베딩 모델은 “j lo”가 “Jennifer Lopez”를 의미한다는 걸 인식함  
  또한 [훈련 레시피](https://arxiv.org/abs/2509.12539)를 공개했으며, **보통 수준의 하드웨어**로도 쉽게 학습 가능함
  - 이 모델의 **임베딩 속도와 recall**이 minish나 model2vec 같은 정적 워드 임베딩과 비교해 어떤지 궁금함  

- 나는 2024년 4월부터 **Meta-Llama-3-8B**로 벡터를 생성했음  
  Python과 Transformers를 RTX-A6000에서 사용했는데, 빠르지만 **소음과 발열**이 심했음  
  이후 M1 Ultra로 옮기고 Apple의 MLX 라이브러리를 사용했는데, 속도는 비슷하면서 훨씬 조용함  
  Llama 모델은 4k 차원이라 fp16 기준 8KB/청크이며, 이를 `numpy.save()`로 SQLite의 BLOB 컬럼에 저장함  
  검색 시 SQLite에서 모든 벡터를 불러와 `numpy.array`로 만든 뒤 **FAISS**로 검색함  
  RTX6000의 faiss-gpu는 매우 빠르고, M1 Ultra의 faiss-cpu도 내 용도(하루 몇 쿼리)에는 충분히 빠름  
  500만 청크 기준 메모리 사용량은 약 40GB로, 두 장비 모두 여유롭게 처리 가능함  

- 대부분의 복잡한 문서는 Markdown 파일임  
  [tobi/qmd](https://github.com/tobi/qmd/)라는 간단한 CLI 도구를 추천함  
  예전에는 fzf 기반 워크플로를 썼지만, 이 도구는 **더 나은 퍼지 검색**을 제공함  
  코드 검색에는 사용하지 않음
  - 소개를 보고 **golang으로 작성된 grep 대체 도구**일 줄 알았는데, Markdown 헤딩 가중치 같은 기능이 있을 거라 예상했음  

- 코드 검색에는 **벡터 데이터베이스를 쓰지 말라**고 권함  
  임베딩은 느리고 코드에는 맞지 않음  
  **BM25 + trigram** 조합이 더 좋은 결과를 내며, 응답 속도도 빠름
  - Postgres에서도 **하이브리드 검색**이 가능함  
    [plpgsql_bm25](https://github.com/jankovicsandras/plpgsql_bm25) 프로젝트를 참고할 수 있음  
    BM25와 pgvector를 **Reciprocal Rank Fusion**으로 결합한 예시와 Jupyter 노트북도 포함됨  
  - 나도 동의함. 예전에 grep 대체 도구로 하이브리드 검색을 써봤는데, **지속적인 재색인**이 번거로웠음  
    코드용이 아닌 모델을 쓰면 벡터 검색이 **노이즈**를 많이 유발함  
    지금은 `gpt-oss 20B`를 ripgrep과 함께 루프 돌리는 방식이 훨씬 빠르고 정확함  
  - BM25와 벡터 검색을 함께 제공하는 **간단한 서비스나 Docker 이미지**를 아는 사람 있는지 궁금함  
  - 파일 경로나 시그니처에 적용했을 때 좋은 결과를 얻었음  
    BM25와 **결합(fusion)** 하면 더 향상됨  
  - 문서 검색용으로 **RAG**를 사용하는 것에 대한 의견이 궁금함  

- 로컬 RAG 실험용으로 [local-LLM-with-RAG](https://github.com/amscotti/local-LLM-with-RAG)를 만들었음  
  Ollama의 “nomic-embed-text”로 임베딩을 생성하고, **LanceDB**를 벡터 DB로 사용함  
  최근에는 “agentic RAG”로 업데이트했지만, 작은 프로젝트에는 과할 수도 있음
  - 나도 비슷한 걸 하고 있음. [lance-context](https://github.com/nicholaspsmith/lance-context)를 사용 중이며, 훨씬 단순한 버전임  
  - “RAG”가 무슨 뜻인지 설명해줘서 고마움. 이 스레드를 읽으며 헷갈렸음  

- fp16 벡터를 SQLite에 BLOB으로 저장하고, 필터링 후 메모리에 로드해 **행렬-벡터 곱(matvec)** 으로 유사도 계산함  
  numpy나 torch가 멀티스레딩/BLAS/GPU를 활용하면 매우 빠름  
  병목이 생기면 [sqlite-vector](https://github.com/sqliteai/sqlite-vector)로 마이그레이션할 예정임  
  날짜나 위치 같은 필터로 데이터가 많이 줄어들기 때문에 효율적임  
  백엔드는 교체 가능한 인터페이스 뒤에 감춰져 있음  

- 내 문서의 95%가 작은 Markdown 파일이라 **SQLite FTS5**로 일반 텍스트 검색 인덱스를 사용함  
  이미 인덱스가 있어서 mastra agent에 바로 연결했음  
  각 파일에는 짧은 설명 필드가 있어, 키워드 검색 후 설명이 일치하면 전체 문서를 로드함  
  설정에 한 시간 정도 걸렸고, 매우 잘 작동함  
  - 사실 그게 바로 **RAG(Retrieval-Augmented Generation)** 임  
    임베딩 기반 검색이 더 흔하긴 하지만, 본질은 동일함  

- 우리는 Postgres에 익숙해서 **PGVector**로 시작했음  
  나중에 프롬프트의 반정형 필드가 필요한 콘텐츠와 **100% 일치**한다는 걸 발견함  
  운영자가 입력과 문서 양쪽에 태그를 넣기 시작했기 때문임 (약 50개 문서 정도)  
  그래서 먼저 필드를 검색해 해당 파일을 프롬프트에 넣고, 그다음에 임베딩 검색을 수행함  
  결과적으로 85%의 경우 **vectordb가 필요 없음**
  - 대부분의 vectordb는 **해결책을 찾는 망치** 같음  

- 나는 [llmemory](https://github.com/juanre/llmemory)를 만들어 로컬과 회사 앱 양쪽에서 사용 중임  
  PostgreSQL + pgvector 기반이며, **하이브리드 BM25**, **멀티 쿼리 확장**, **reranking** 기능을 포함함  
  처음 공개하는 거라 약간의 버그는 있을 수 있음  
  성능에는 꽤 만족함
