
검색 증강 생성 (RAG): 작동 원리, 10가지 고급 기술 및 일반적인 한계점
요약
RAG(검색 증강 생성)의 기본 원리와 프로덕션 환경에서의 실무적인 구현 방법을 다룹니다. RAG의 작동 단계, 키워드 검색과 벡터 검색의 차이점, 그리고 시스템 성능을 높이기 위한 고급 기술과 한계점을 상세히 설명합니다.
핵심 포인트
- RAG는 LLM의 내부 지식과 외부 데이터베이스를 결합하여 최신 정보 및 내부 데이터를 활용함
- 임베딩, 벡터 데이터베이스, LLM을 활용한 4단계 파이프라인으로 작동
- 단순 키워드 매칭을 넘어 의미 기반의 벡터 검색을 통해 답변 정확도 향상 가능
- 프로덕션 환경에서 발생할 수 있는 문제점과 이를 해결하기 위한 10가지 고급 기술 소개
당신의 AI 모델은 어제 무슨 일이 일어났는지 모릅니다. 당신의 AI 모델은 회사의 내부 급여 명세서를 알지 못합니다. 당신의 AI 모델은 무지를 인정하기보다 자신 있게 답변을 지어낼 것입니다. RAG (Retrieval Augmented Generation, 검색 증강 생성)는 이 세 가지 문제를 해결하기 위해 존재하며, RAG를 제대로 이해하는 것은 당신이 AI 시스템을 구축하는 방식을 변화시킵니다.
이 기사에서는 다음 내용을 다룹니다:
- RAG란 무엇이며 왜 업계가 이에 의존하는가
- 프로덕션 환경에서 RAG 시스템을 망가뜨리는 7가지 실제 문제
- 당신의 RAG 시스템이 제대로 작동하는지 측정하는 방법
- 10가지 고급 기술 (필요한 경우 다이어그램 포함)
- RAG가 완전히 잘못된 도구인 경우
원래 기술은 언어 모델의 내부 지식과 외부 문서 인덱스를 결합한 2020년 Facebook AI 논문에서 유래되었습니다. 공식적인 정의를 원한다면 그 논문이 여전히 적절한 시작점입니다:
Lewis et al., "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks," 2020.
섹션 1: RAG란 실제로 무엇인가
RAG는 Retrieval Augmented Generation의 약자입니다. AI 모델이 질문에 답변하기 전에, 시스템은 데이터베이스에서 관련 사실을 가져온 다음, 그 질문과 함께 해당 사실들을 모델에 전달합니다.
- 1단계: 사용자가 일상 언어로 쿼리 (Query)를 보냅니다.
- 2단계: 임베딩 모델 (Embedding model)이 쿼리를 벡터 (Vector, 정확한 단어가 아닌 의미를 나타내는 숫자 그리드)로 변환합니다.
- 3단계: 벡터 데이터베이스 (Vector database)가 해당 벡터와 의미상 가장 유사한 저장된 청크 (Chunks)를 찾습니다.
- 4단계: LLM (Large Language Model)이 질문과 검색된 청크를 사용하여 답변을 작성합니다.
키워드 검색 (Keyword search) vs 벡터 검색 (Vector search)
이것은 RAG가 왜 존재하는지를 설명하는 비교입니다.
| 키워드 검색 (Keyword search) | 벡터 검색 (Vector search) | |
|---|---|---|
| 일치 기준 | 정확한 단어 (Exact words) | 의미 (Meaning) |
| ... |
실제 사례 (Real-world case): 한 통신사 고객 지원 봇이 "셀 커버리지 (cell coverage)"에 대한 고객 질문을 "네트워크 신호 강도 (network signal strength)"라는 용어로 작성된 지식 베이스(knowledge base)와 대조했습니다. 키워드 검색은 이러한 쿼리의 약 30%에 대해 아무런 결과도 반환하지 않았습니다. 검색기(retriever)를 벡터 검색으로 전환하자, 단 하나의 지원 문서도 수정하지 않고도 그 격차의 대부분을 메울 수 있었습니다.
핵심 요점 (Key takeaway): 벡터 검색은 키워드 검색을 대체하는 것이 아니라, 사용자가 문서와는 다른 방식으로 표현할 때 발생하는 격차를 메워줍니다. 많은 운영 시스템(production systems)은 두 방식 모두를 실행하고 결과를 병합합니다.
섹션 2: 운영 환경에서 RAG를 망가뜨리는 7가지 문제점
10개의 테스트 질문에서 잘 작동하는 데모는 실제 운영 환경(production)에서의 동작에 대해 거의 아무것도 알려주지 않습니다. 다음은 7가지 실패 패턴이 모여 있는 지점입니다.
문제 1: 대화 기록(Conversation history) 부재
사용자가 "Avery는 누구인가요?"라고 물은 다음 "그녀의 급여는 얼마인가요?"라고 묻습니다. 기본적인 설정은 모든 메시지를 완전히 새로운 것으로 취급하므로, "그녀"라는 단어는 급여 문서 중 첫 번째로 순위가 매겨진 것을 가져오게 되며, 이는 완전히 다른 사람의 것일 수 있습니다.
실제 사례 (Real-world case): 한 사내 인사(HR) 챗봇이 "그녀의 급여는 얼마인가요?"라는 질문에 잘못된 직원의 급여를 세 번이나 답변했고, 팀이 대화 기록 누락을 추적한 후에야 원인을 찾아냈습니다. 해결책 (Fix): 매 호출 시마다 사용자(user)와 어시스턴트(assistant)의 모든 이전 메시지를 모델에 전달하세요. 한 번은 오후 내내 작업하여 찾아내기도 했습니다.
문제 2: 검색이 마지막 메시지만 참조함
전체 이력을 포함하더라도, 검색 (retrieval) 단계가 문자 그대로 마지막 메시지만 검색한다면, "그녀의 연봉은 얼마인가요"라는 질문에는 여전히 이름이 포함되어 있지 않습니다. 해결책: 쿼리를 날리기 전에 대화 이력을 하나의 검색 문자열로 결합하세요. "그녀의 연봉은 얼마인가요" 대신 "Avery, 그녀의 연봉은 얼마인가요"라고 검색하는 것입니다.
문제 3: 2번 해결책이 주제 전환을 방해함
Avery에 대해 여러 차례 대화한 후, 사용자가 "IOTY 상은 누가 받았나요?"라고 질문합니다. 결합된 검색 문자열이 이제 Avery의 이름에 의해 지배되고 있기 때문에, 시스템은 계속해서 Avery와 관련된 청크 (chunk)를 반환합니다. 아직 깔끔한 해결책은 존재하지 않습니다. 쿼리 재작성 (query rewriting), 최신성 가중치 부여 (recency weighting), 그리고 전용 "클린 쿼리 (clean query)" 모델이 모두 부분적인 도움을 줍니다.
반론: 일부 팀은 대부분의 대화가 여러 차례 동안 하나의 주제를 유지하기 때문에, 최신성 가중치 부여만으로도 대부분의 실제 사례를 해결할 수 있다며 이 문제가 과장되었다고 말합니다. 반면 다른 이들은 남은 실패 사례들이 바로 사용자가 인지하고 신뢰를 잃게 되는 바로 그 순간들이라고 지적합니다.
문제 4: 너무 작은 청크는 문맥을 잃음
이름이 헤딩 (heading)에 있거나 다른 청크에 있었기 때문에, 어떤 청크는 이름 없이 "상을 받았다"라고만 말합니다. 실제 사례: 한 법률 검색 도구가 계약서 이름이 붙지 않은 조항 텍스트를 반환하여, 변호사들이 모든 결과를 수동으로 추적해야 했습니다. 데이터 주입 (ingestion) 시점에 각 청크의 메타데이터 (metadata)에 문서 제목을 추가함으로써 청크 크기를 건드리지 않고도 이 문제를 해결했습니다.
문제 5: 너무 큰 청크는 관련성을 희석함
누군가의 경력, 연봉, 수상 경력 및 리뷰 전체를 다루는 청크는 관련 없는 텍스트로 희석되기 때문에, "누가 상을 받았나요"와 같은 좁은 질문에 대해 결코 높은 점수를 받을 수 없습니다.
실제 사례: SaaS 제품을 위한 지원 봇을 운영하는 한 팀은 더 풍부한 문맥과 더 나은 답변을 기대하며 청크 크기를 500에서 1500 토큰 (token)으로 늘렸습니다. 하지만 대신 그들의 평가 세트 (eval set)에 대한 정확도가 떨어졌는데, 이는 검색된 각 청크가 이제 세 가지의 관련 없는 주제를 담고 있었고, 모델이 가끔 중간에 묻혀 있는 잘못된 주제를 바탕으로 답변했기 때문입니다. 그들은 작은 중첩 (overlap)을 포함하여 600 토큰으로 되돌렸고, 재현율 (recall)은 다시 올라갔습니다.
문제 6: RAG는 근본적으로 근사적임
논리적으로 타당해 보이는 시스템이 10개의 질문에는 통과하고 11번째 질문에서 실패하는 이유는, 벡터 유사도 (vector similarity)가 실제 이해가 아닌 수학적 지름길이기 때문입니다. 매번 올바른 청크 (chunk)가 나타난다는 보장은 없습니다. 유일한 실질적인 해결책은 모든 것을 측정하는 것입니다 (섹션 3).
문제 7: 쿼리 시점의 잘못된 인코더 (encoder)
하나의 임베딩 모델 (embedding model)로 벡터 저장소 (vector store)를 구축하고, 다른 모델로 쿼리를 수행하면 차원 불일치 (dimension mismatch)로 인한 충돌이 발생합니다. 서로 다른 모델은 텍스트를 완전히 다른 수학적 공간에 배치합니다. 즉, 300차원 벡터는 3000차원 벡터와 비교할 수 없습니다.
경고: 인코더 버전을 혼용하는 것은 RAG 시스템의 운영 환경에서 발생하는 가장 흔한 장애 중 하나입니다. 임베딩 모델 버전을 고정하고, 변경 사항이 발생하면 단순한 설정 업데이트가 아닌 전체 재색인 (re-ingestion) 작업으로 취급하십시오.
요약 표
| 문제 | 근본 원인 | 해결책 |
|---|---|---|
| 대화 기록 없음 | 현재 메시지만 모델로 전송됨 | 매 호출 시 전체 기록을 전달 |
| ... |
접근 방식으로서의 RAG의 장단점
| 장점 | 단점 |
|---|---|
| 새로운 데이터에 대한 미세 조정 (fine-tuning)보다 저렴함 | 검색 품질이 결코 보장되지 않으며, 확률적일 뿐임 |
| ... |
핵심 요점: 검색 품질이 프롬프트 품질보다 더 중요합니다. 잘못된 문서가 검색된다면, 세상에서 가장 뛰어난 프롬프트라도 답변을 바로잡을 수 없습니다.
섹션 3: RAG 시스템이 실제로 작동하는지 측정하는 방법
측정 없이는 RAG 작업이 추측에 불과하게 됩니다.
1단계: 골든 데이터셋 (golden dataset) 구축. 자체 데이터에서 실제 질문과 정답을 수집하십시오.
질문: "권위 있는 IOTY 상을 누가 수상했나요?"
키워드: ["Maxine", "Thompson"]
완벽한 답변: "Maxine Thompson이 2023년에 IOTY 상을 수상했습니다."
2단계: 검색 품질 측정
2단계: 검색 품질 측정
최종 답변을 평가하기 전에, 검색 시스템이 올바른 컨텍스트를 반환하는지 확인해야 합니다. 이 지표들은 검색 성능을 측정하는 데 도움을 줍니다.
| 지표 | 측정 내용 |
|---|---|
| MRR (Mean Reciprocal Rank) | 첫 번째 관련 청크가 얼마나 높은 순위로 매겨지는지를 측정합니다. 순위 1의 관련 청크는 1.0을, 순위 2는 0.5를, 순위 3은 0.33을 얻습니다. |
| ... |
핵심 통찰: 대부분의 RAG 시스템에서 Recall@K가 Precision보다 더 중요합니다. 몇 개의 관련 없는 청크는 보통 사소한 노이즈만 추가하지만, 올바른 청크를 검색하지 못하는 것은 종종 부정확하거나 불완전한 답변으로 이어집니다.
대부분의 RAG 시스템에서 정밀도(precision)보다 재현율(recall)이 더 중요합니다. 관련성 있는 청크가 누락되는 것이 잘못된 답변이고, 추가적인 관련 없는 청크는 단지 노이즈일 뿐입니다.
3단계: LLM을 심사위원으로 사용하여 답변 품질 측정. 두 번째로 강력한 모델이 정확도, 완전성(
2. 인코더 선택 (Encoder selection). 평가 세트(eval set)를 대상으로 여러 임베딩 모델 (embedding models)을 테스트하세요. 이미지의 경우, 먼저 캡션 (caption)을 생성한 뒤 해당 캡션을 벡터화 (vectorize)하세요. PDF의 경우, 임베딩하기 전에 코드 라이브러리를 사용하여 마크다운 (markdown)으로 변환하세요. 이를 위해 모델 호출 (model call) 비용을 낭비하지 마세요.
3. 프롬프트 엔지니어링 (Prompt engineering). 가장 많이 간과되는 기술입니다. 정적 컨텍스트 (Static context, 회사 상세 정보, 현재 날짜, 도메인 규칙)와 올바른 이력 처리 (history handling)를 결합하는 것이 전체 아키텍처 (architecture)를 재구축하는 것보다 더 나은 결과를 가져오는 경우가 많습니다.
4. 문서 재작성 (Document rewriting). 숫자 테이블은 벡터화 (vectorize)가 잘 되지 않습니다. 데이터를 수집(ingestion)하기 전에 자연어로 재작성하세요: "사용자가 질문하는 방식에 맞춰 이 테이블을 재작성하세요."
쿼리 시점 (Query-time) 기술은 검색되는 대상과 모델에 도달하기 전 결과가 필터링되는 방식을 변경합니다:
5. 쿼리 재작성 (Query rewriting) (위 다이어그램 참조). 검색하기 전에 모델을 호출하여 다음과 같이 프롬프트를 입력하세요: "대화 속의 모든 대명사를 해결하여 이를 독립적인 쿼리 (standalone query)로 재작성하세요." 이는 "그녀의 급여"와 같은 문제를 직접적으로 해결합니다.
6. 쿼리 확장 (Query expansion). 하나의 재작성된 쿼리 대신, 여러 가지 표현을 생성하여 그 모두로 검색을 수행한 다음 결과를 통합(pool)하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기


