Articlemedium.com·2026년 6월 14일·0

Most RAG Problems Are Retrieval Problems. Here Are 8 Fixes That Worked for Me

Quick Summary

이 글은 RAG 품질 문제의 상당수가 프롬프트나 모델보다 검색 실패에서 비롯되며, 근거 문서가 컨텍스트에 들어오도록 검색 파이프라인을 먼저 고쳐야 한다고 설명한다.

Most RAG Problems Are Retrieval Problems. Here Are 8 Fixes That Worked for Me 관련 대표 이미지

🖼️ 인포그래픽

Most RAG Problems Are Retrieval Problems. Here Are 8 Fixes That Worked for Me 내용을 설명하는 본문 이미지

🖼️ 4컷 인포그래픽

Most RAG Problems Are Retrieval Problems. Here Are 8 Fixes That Worked for Me 내용을 설명하는 본문 이미지

💡 한 줄 요약

이 글은 RAG 품질 문제의 상당수가 프롬프트나 모델보다 검색 실패에서 비롯되며, 근거 문서가 컨텍스트에 들어오도록 검색 파이프라인을 먼저 고쳐야 한다고 설명한다.

📌 핵심 요약

  • 저자는 RAG 시스템이 나쁜 답을 냈을 때 처음에는 프롬프트를 더 엄격하게 바꾸었지만 효과가 거의 없었고, 실제 원인은 적절한 passage가 컨텍스트 창에 들어오지 않는 데 있었다고 말한다.
  • 가장 먼저 손볼 것은 청킹이다. chunk size가 너무 크면 잡음이 많아지고 너무 작으면 주변 맥락이 사라지므로, 예시로 RecursiveCharacterTextSplitter에서 chunk_size 1000과 chunk_overlap 200으로 시작하라고 제안한다.
  • Dense embedding만으로는 오류 코드, 제품명, 희귀 약어 같은 정확한 문자열을 놓칠 수 있으므로 BM25와 벡터 검색을 함께 쓰는 hybrid search가 중요하며, 여러 검색 결과는 RRF로 병합할 수 있다고 설명한다.
  • 초기 검색은 recall 중심이라 좋은 문서가 낮은 순위에 있을 수 있기 때문에, cross-encoder 기반 reranker로 query-document 쌍을 다시 평가해 상위 몇 개만 모델에 넘기는 방식이 비용 대비 효과적이라고 본다.
  • 저자는 프롬프트부터 고치지 말고 실제 retrieval 결과를 로그로 확인하라고 조언하며, 더 많은 chunk를 무작정 넣기보다 청킹, hybrid search, reranking, contextual chunking, metadata filter, query rewriting, MMR 등을 조합해 검색 품질을 높이라고 정리한다.

🧩 주요 포인트

  1. 저자는 RAG 시스템이 나쁜 답을 냈을 때 처음에는 프롬프트를 더 엄격하게 바꾸었지만 효과가 거의 없었고, 실제 원인은 적절한 passage가 컨텍스트 창에 들어오지 않는 데 있었다고 말한다.
  2. 가장 먼저 손볼 것은 청킹이다. chunk size가 너무 크면 잡음이 많아지고 너무 작으면 주변 맥락이 사라지므로, 예시로 RecursiveCharacterTextSplitter에서 chunk_size 1000과 chunk_overlap 200으로 시작하라고 제안한다.
  3. Dense embedding만으로는 오류 코드, 제품명, 희귀 약어 같은 정확한 문자열을 놓칠 수 있으므로 BM25와 벡터 검색을 함께 쓰는 hybrid search가 중요하며, 여러 검색 결과는 RRF로 병합할 수 있다고 설명한다.
  4. 초기 검색은 recall 중심이라 좋은 문서가 낮은 순위에 있을 수 있기 때문에, cross-encoder 기반 reranker로 query-document 쌍을 다시 평가해 상위 몇 개만 모델에 넘기는 방식이 비용 대비 효과적이라고 본다.
  5. 저자는 프롬프트부터 고치지 말고 실제 retrieval 결과를 로그로 확인하라고 조언하며, 더 많은 chunk를 무작정 넣기보다 청킹, hybrid search, reranking, contextual chunking, metadata filter, query rewriting, MMR 등을 조합해 검색 품질을 높이라고 정리한다.

🧠 상세 정리

1. 문제의 출발점: 프롬프트가 아니라 빠진 근거

저자는 RAG 시스템이 부정확한 답을 냈을 때 처음에는 많은 사람처럼 프롬프트를 손봤다고 말한다. 더 엄격한 지시를 넣고, 컨텍스트에서만 답하라는 문장을 추가했지만 품질은 거의 나아지지 않았다. 이후 한 단계 앞을 보니, 문제는 모델이 아니라 정답을 뒷받침할 passage가 컨텍스트 창에 애초에 들어오지 않는 경우가 대부분이었다. 근거가 없으면 아무리 프롬프트를 다듬어도 답을 grounding할 수 없다는 것이 글의 핵심 전제다.

2. 청킹과 overlap이 검색 품질의 상한을 정한다

저자가 가장 먼저 권하는 개선은 청킹을 바로잡는 것이다. chunk size는 이후 검색, reranking, 생성 전체의 상한을 정하는 요소로 제시된다. 너무 큰 chunk는 답이 잡음 속에 묻히게 만들고, 너무 작은 chunk는 필요한 주변 맥락을 잃게 만든다. 글에서는 RecursiveCharacterTextSplitter를 사용할 때 chunk_size 1000, chunk_overlap 200 정도로 시작하라고 제안한다. overlap은 경계에 걸친 답이 잘려 나가지 않도록 이전 chunk의 끝부분을 다음 chunk로 조금 이어주는 역할을 한다.

3. Hybrid search와 RRF: 의미 검색과 정확한 문자열 검색을 함께 쓰기

저자는 dense embedding이 의미를 잡는 데는 좋지만 정확한 문자열에는 약하다고 설명한다. 실제 사례로, 지원 봇이 connection error의 의미는 설명할 수 있었지만 ERR_CONN_REFUSED라는 구체적 문서에는 도달하지 못했다고 한다. Dense embedding이 해당 토큰을 연결 관련 의미로 뭉개는 동안, BM25는 그 정확한 문자열을 즉시 찾을 수 있었다. 그래서 벡터 검색과 BM25를 함께 돌리고, Reciprocal Rank Fusion으로 순위 목록을 병합하는 방식을 권한다. RRF는 점수 보정 없이 여러 ranked list를 합칠 수 있다는 점이 장점으로 제시된다.

4. Reranking: 넓게 찾고, 제대로 다시 고르기

초기 retrieval은 보통 recall을 높이는 데 초점이 있어 넓은 후보군을 가져오지만, 실제로 가장 좋은 passage가 1위가 아니라 7위쯤에 있을 수 있다고 저자는 말한다. 이때 reranker는 query와 document 쌍을 더 정교하게 읽고 다시 점수를 매겨 순서를 바꾼다. 글에서는 cross-encoder 방식과 Cohere의 rerank-v3.5 같은 예시를 언급한다. 비용은 초기 검색보다 조금 더 들지만 LLM 생성 호출에 비하면 작기 때문에, 넓게 가져온 뒤 rerank하고 상위 몇 개만 남기는 접근이 합리적이라고 설명한다.

5. Contextual chunking: chunk가 스스로 맥락을 갖게 만들기

저자는 단독으로 보면 애매한 chunk가 검색에서 잘 잡히지 않는 문제도 강조한다. 예를 들어 '제한은 분당 5,000 요청'이라는 chunk만 있으면 어떤 API인지, 어떤 요금제인지 알 수 없어 검색 가능성이 떨어진다. 이를 해결하기 위해 각 chunk마다 LLM이 짧은 설명을 작성하게 하고, 그 문장을 chunk 앞에 붙인 뒤 embedding하는 방법을 제안한다. 이 방식은 색인 시점에 chunk마다 추가 LLM 호출 비용이 들지만 한 번만 지불하면 된다. 저자는 실제 수치 개선에서 이 변경이 가장 큰 영향을 준 단일 변화였다고 말한다.

6. 하지 말아야 할 일과 조합 가능한 개선책

글의 후반부는 저자가 과거의 자신에게 해주고 싶은 조언으로 정리된다. 먼저 프롬프트부터 손대지 말고 retrieval이 실제로 무엇을 반환했는지 로그로 확인하라고 한다. 또한 chunk size를 한 번 정하고 잊지 말고, 256, 512, 1024처럼 여러 크기를 자신의 데이터에서 측정하라고 권한다. Dense-only 검색은 코드, ID, 희귀 이름을 놓칠 수 있으므로 피해야 하며, 순위가 나쁜 것을 감추려고 chunk를 20개씩 넣는 것도 좋지 않다고 말한다. Query rewriting, metadata filter, parent-document retriever, de-dupe/MMR 같은 방법들은 모두 검색 후보의 질과 다양성을 높이는 보완책으로 제시된다.

🧾 핵심 주장 / 시사점

  • 이 글의 핵심은 RAG 개선의 첫 디버깅 지점을 생성 프롬프트가 아니라 retrieval 로그로 옮기라는 점이다.
  • 청킹, hybrid search, reranking, contextual chunking은 서로 대체재가 아니라 누적 효과를 내는 단계별 개선책으로 설명된다.
  • 더 많은 컨텍스트를 넣는 방식은 근본 해결이 아니며, 좋은 후보를 넓게 찾고 다시 정렬한 뒤 중복과 잡음을 줄여 보내는 것이 더 중요하다.

✅ 액션 아이템

  • 청킹을 먼저 조정해 chunk_size는 1000, chunk_overlap는 200을 기준으로 잡음 증가와 맥락 손실을 동시에 점검한다.
  • prampt를 먼저 바꾸지 말고 우선 retrieval 로그를 추적해 적절한 passage가 컨텍스트 창에 실제로 들어오는지 검증한다.
  • BM25와 dense 임베딩을 결합한 hybrid search로 후보를 모은 뒤 RRF 병합 후 cross-encoder reranker를 적용해 상위 소수만 LLM에 전달해 재정렬한다.

❓ 열린 질문

  • chunk_size 1000과 chunk_overlap 200 기준값은 어떤 지표 기반으로 언제 조정할지 판단할 것인가?
  • 초기 검색에서 좋은 문서를 더 많이 끌어오려면 BM25와 벡터 가중치 배분을 어떻게 정량화할 것인가?
  • cross-encoder reranker를 어떤 top-k 범위에 적용하면 비용 대비 정확도 향상이 가장 효율적으로 확인되는가?

관련 문서

공통 태그와 주제 흐름을 기준으로 같이 보면 좋은 문서를 이어서 제안합니다.