RAG는 생각보다 단순하다: 6가지 검색 구조와 과설계 피하기
RAG Is Simpler Than You Think
TL;DR Highlight
임베딩 전에 BM25와 쿼리 재작성부터 쓰면 대부분 해결된다
Who Should Read
RAG를 만들며 벡터DB·리랭킹부터 붙일지 고민하는 백엔드 개발자
Core Mechanics
- 임베딩부터 시작하면 일이 커진다
- 글쓴이는 많은 팀이 임베딩·벡터DB·리랭킹으로 바로 뛰어든다고 본다.
- 사용자는 '비밀번호 재설정 문서'를 찾고 싶을 뿐이라고 한다.
- 레시피 1은 BM25 전문 검색뿐이다
- Elasticsearch나 Postgres 전문 검색(full-text search)으로 API 비용이 0이고 10ms 미만이다.
- 청킹(문서 쪼개기)과 평가 설계가 필요 없고 모델 폐기 위험도 없다.
- 동의어("car" vs "automobile")와 의미 질문("How do I...?")에는 약하다.
- 쿼리 재작성이 임베딩보다 고치기 쉽다
- LLM으로 지저분한 질문을 키워드 검색어로 바꾸며 GPT-4o-mini 기준 쿼리당 약 $0.001이다.
- 결과가 나쁘면 재임베딩 없이 시스템 프롬프트만 고치면 된다.
- 사내 용어(예: Atlas)를 프롬프트에 적어 그대로 키워드로 쓰게 한다.
- 임베딩 방식은 데이터 성격으로 고른다
- 변경이 잦으면 on-the-fly 임베딩(검색 때마다 후보 문서만 임베딩)이며, 쿼리당 200-500ms가 추가된다.
- 자주 읽는 문서가 뚜렷하면 hot/cold 계층이다.
- 안정적인 대규모 코퍼스에 쿼리 하루 10K 초과면 전체 사전 임베딩이다.
- 모델 교체 비용이 방식마다 크게 다르다
Community Reactions
- BM25 중심 설계를 지지하는 현업 경험
- 대규모 RAG를 해 본 사람이 전문 검색이 과소평가되고 임베딩이 과대평가된다고 했다.
- 임베딩은 결국 재임베딩과 리랭킹에 벡터 검색 운영 부담까지 끌고 온다는 경험담이다.
- Lucene 위 쿼리 재작성을 추천하는 의견
- 에이전트가 문서 저장소를 반복 조회하는 쪽이 종착지라는 의견이다.
- 임베딩은 비결정성 위에 비결정성을 얹고 키워드 검색이 디버깅하기 쉽다는 주장이다.
- 코딩 에이전트에서 검색 인덱싱을 뺐다는 경험
- 검색 경로가 버그로 결과 0건이었는데도 한참 몰랐고 오히려 더 잘 동작했다고 한다.
- A/B 테스트 후 인덱싱을 없앴고 grep으로 충분했다는 경험이다. 아주 큰 코드베이스는 다르다고 했다.
- 반론과 글 품질 비판
- 문서 기반 RAG의 90%는 임베딩 시맨틱 검색이 기본이어야 한다는 반론이 있다.
- 글이 AI가 쓴 듯하고 근거 없이 나열만 한다는 비판이 있다.
- 'on-the-fly'와 '희소+밀집 리랭킹' 설명이 불명확하다는 지적도 있다.
How to Apply
- 지금 검색을 질문 유형별로 점검하기
- 30분 안에 최근 실패한 검색 질의 20개를 모아 '키워드형·대화형·사내 용어형'으로 분류한다.
- 아래 프롬프트로 쿼리 재작성 결과를 눈으로 확인한다.
- 사내 용어집을 쿼리 재작성 프롬프트에 넣기
- 사내 프레임워크·서비스 이름을 '수정 금지 키워드'로 시스템 프롬프트에 적는다.
- 재작성한 쿼리를 기존 BM25나 Postgres 전문 검색에 넣어 결과를 비교한다.
- 2주 A/B 테스트로 임베딩 도입 판단하기
- 재작성 적용군과 기존군을 2주간 비교한다.
- 부족하다는 데이터가 나올 때만 하이브리드(BM25 후보 50-100개를 임베딩으로 재정렬)를 붙인다.
- 복합 질문은 하위 질문으로 분해하기
- 질문 하나에 의도가 여러 개면 LLM이 하위 질문 목록을 JSON으로 내게 한다.
- 하위 질문별로 BM25를 병렬 호출해 결과를 합친다.
Try It
# Claude나 ChatGPT에 그대로 붙여넣기 (원문 쿼리 재작성 방법을 프롬프트로 옮긴 것)
너는 문서 검색용 쿼리 재작성기다. 사용자의 대화체 질문을 BM25 키워드 검색어로 바꿔라.
규칙:
- 불용어("how do I" 같은 표현)를 제거한다.
- 동의어를 덧붙인다.
- 복합 질문은 하위 검색어 여러 개로 나누고 JSON 배열로 낸다.
- 아래 사내 용어는 절대 바꾸지 말고 그대로 키워드로 쓴다.
{{사내 용어: 이름 - 설명 목록}}
질문: {{사용자 질문}}
출력: 검색어 목록만 JSON으로 낸다.
이어서 해 볼 것: 실패했던 질의 20개를 넣어 검색어를 만들고, 기존 BM25에 넣어 결과가 나아졌는지 확인해 보자.Terminology
관련 논문
트랜스포머는 '기억 저장소'에서 처음부터 만들어 낼 수 있었다
선형층→MLP→self-attention을 기억 저장소로 보면 용량이 64→약 2,700→100만 이상
400년치 고문서에 AI를 돌렸더니 잊힌 운석·코뿔소·화산 폭발이 나왔다
임베딩 검색과 싼 필터 모델로 400년 고문서를 뒤져 미기록 사건 발굴
EmbeddingGemma 2: 텍스트·이미지·오디오·비디오를 한 벡터 공간에 넣는 오픈 경량 임베딩 모델
740M 오픈 모델 하나로 텍스트·이미지·오디오·비디오를 같은 벡터 공간에서 검색
RAG-NAROK: 출처를 직접 반박하는 문서로 RAG 지식베이스를 오염시키는 공격
검색된 출처를 겨냥해 반박문을 심었더니 1위 검색과 탐지 회피가 높아졌다
텍스트냐 이미지냐 둘 다냐: 멀티모달 문서 QA 입력 방식 비교
문서 QA에서 페이지 이미지가 정확도는 높지만 느려서, 질문별 라우터로 지연 30% 줄였다
MS 임원이 AI 스크래핑을 '인류 역사상 최대의 노동 도둑질'이라 불렀다는 NYT 소송 공개 문서
NYT 소송 공개 문서에서 MS·OpenAI 내부의 스크래핑 인식이 드러났다
임베딩의 보편적 기하 구조 활용: 짝 데이터 없이 임베딩 공간 간 변환
짝 데이터 없이 임베딩을 다른 모델 공간으로 옮겼고, 벡터 DB 보안 위험이 드러났다