Skip to main content

12장. 검색 증강 생성(RAG)의 기초

LLM은 말을 아주 그럴듯하게 잘한다. 그런데 그럴듯함과 정확함은 다르다. 특히 서비스에 붙는 순간 이 차이는 꽤 아프게 다가온다. 사용자는 오늘 바뀐 정책을 묻고, 회사 내부 매뉴얼을 기준으로 답을 기대하며, 방금 업로드한 문서를 읽고 설명해 달라고 요청한다. 하지만 모델은 학습 시점 이후의 정보를 자동으로 아는 것이 아니고, 우리 회사 위키를 태어날 때부터 읽고 나온 것도 아니다.

이 지점에서 RAG가 등장한다. RAG는 Retrieval-Augmented Generation, 우리말로는 검색 증강 생성이다. 이름은 조금 거창하지만 핵심은 단순하다. 먼저 필요한 정보를 찾아오고, 그 정보를 바탕으로 답하게 만드는 방식이다. 한마디로 말하면 "기억에만 의존하지 말고 자료를 펼쳐 놓고 대답하라"는 전략이다.

이 장에서는 RAG의 가장 기본적인 흐름인 문서 적재, 청킹, 임베딩, 검색, 컨텍스트 주입을 서비스 관점에서 차근차근 살펴본다. 여기서 중요한 것은 특정 벡터 데이터베이스 제품이나 유행하는 라이브러리 이름이 아니다. 어떤 도구를 쓰든 흔들리지 않는 기본 원리를 이해하는 것이다.

3부. 웹 서비스에 붙는 핵심 AI 기능 만들기 / 12장. 검색 증강 생성(RAG)의 기초

왜 RAG가 필요한가

요약이나 재작성 같은 기능은 사용자가 입력한 텍스트만 잘 다뤄도 꽤 좋은 결과가 나온다. 하지만 검색 기반 질의응답, 사내 문서 챗봇, 정책 안내 도우미, 제품 매뉴얼 상담, 계약서 질의응답 같은 기능은 이야기가 다르다. 이 경우 모델이 똑똑한 것만으로는 부족하고, 정확한 근거를 제때 가져오는 능력이 필요하다.

RAG가 필요한 이유는 크게 세 가지다.

  • 최신 정보를 다루기 위해서다. 모델이 학습하지 못한 최근 공지, 변경된 가격, 개정된 약관을 반영하려면 외부 지식원을 조회해야 한다.

  • 사내 지식을 다루기 위해서다. 내부 매뉴얼, 회의록, 운영 가이드, 고객 응대 정책 같은 정보는 공개 모델이 원래 알 수 없다.

  • 답의 근거를 좁히기 위해서다. 모델이 세상 모든 지식에서 아무거나 꺼내 답하도록 두기보다, 관련 문서 몇 개 안에서 답하게 하면 정확성과 일관성이 올라간다.

여기서 중요한 포인트가 하나 있다. RAG는 모델의 지능을 대체하는 기술이 아니라, 모델이 참고할 열린 책상을 만들어 주는 기술이라는 점이다. 모델은 여전히 읽고, 요약하고, 연결하고, 문장으로 답하는 역할을 맡는다. 다만 빈손으로 답하지 않게 만드는 것이다.

RAG란 무엇인가

RAG를 가장 쉽게 설명하면 "검색 + 생성"이다. 먼저 사용자의 질문과 관련 있는 문서를 찾고, 그 문서 일부를 프롬프트에 함께 넣은 뒤, 모델이 그 자료를 바탕으로 답을 생성하게 한다.

이 과정을 도서관에 비유해 보자. 사용자가 "우리 환불 정책에서 부분 환불은 언제 가능한가요?"라고 물었다고 하자. 그냥 기억력 좋은 직원에게 물어보는 방식은 순수 생성에 가깝다. 반면 RAG는 먼저 정책 문서를 찾아 책상 위에 펼쳐 놓고, 그 문서를 읽은 뒤 대답하는 방식이다. 훨씬 덜 위험하다.

RAG는 모델을 다시 학습시키는 방법과도 다르다. 모델 재학습이나 파인튜닝은 모델 내부의 성향이나 출력 스타일을 바꾸는 데 강하지만, 자주 바뀌는 지식을 매번 주입하기에는 비용과 운영 부담이 크다. 반면 RAG는 문서 저장소만 갱신하면 비교적 빠르게 최신 정보를 반영할 수 있다.

RAG 파이프라인 한눈에 보기

기본적인 RAG 파이프라인은 다음 다섯 단계로 이해하면 된다.

  • 문서를 수집하고 정리하는 문서 적재

  • 문서를 검색하기 좋은 단위로 나누는 청킹

  • 각 조각의 의미를 숫자 표현으로 바꾸는 임베딩

  • 질문과 가장 관련 있는 조각을 찾는 검색

  • 검색된 내용을 프롬프트에 넣어 답하게 하는 컨텍스트 주입

이 다섯 단계는 하나라도 대충 만들면 전체 품질이 무너진다. 많은 팀이 모델 성능만 의심하다가 결국 문서 정리나 청킹 문제를 뒤늦게 발견한다. RAG는 생각보다 데이터 공학적인 작업이다.

문서 적재: 무엇을 넣을 것인가부터 결정하라

RAG의 출발점은 문서다. 당연한 말 같지만, 실무에서는 이 단계가 가장 중요하다. 잘못된 문서가 들어가면 검색도, 답변도 잘못된다. 오래된 문서가 최신 문서와 섞여 있으면 모델은 자신 있게 틀린 말을 한다. 불완전한 문서를 넣으면 답도 불완전해진다.

문서 적재 단계에서 먼저 결정해야 할 것은 지식의 범위다. 예를 들어 고객센터 봇이라면 제품 소개 자료 전체보다 실제 고객 문의에 필요한 FAQ, 환불 정책, 배송 규정, 장애 공지, 관리자 운영 가이드가 더 중요할 수 있다. "넣을 수 있는 문서를 다 넣자"보다 "무엇을 답하게 할 것인가"가 먼저다.

문서를 적재할 때는 원문만 저장하지 말고 메타데이터도 함께 관리해야 한다. 메타데이터는 문서의 부가 정보다. 문서 제목, 작성일, 버전, 부서, 접근 권한, 언어, URL, 카테고리 같은 정보가 여기에 해당한다. 이 메타데이터는 나중에 검색 필터링과 권한 제어에 아주 중요하게 쓰인다.

예를 들어 인사팀 문서와 개발팀 문서를 같은 저장소에 넣더라도, 모든 사용자가 모든 문서를 검색하게 해서는 안 된다. 또 2024년 정책과 2026년 정책이 함께 존재한다면 최신 버전 우선 전략이 필요하다. 즉, 문서 적재는 단순 업로드가 아니라 서비스 규칙을 데이터에 반영하는 단계다.

문서를 넣기 전에 텍스트 정리도 필요하다. PDF에서 추출한 텍스트에는 종종 줄바꿈이 깨지고, 표가 이상하게 흩어지며, 머리글과 바닥글이 반복된다. 이런 잡음이 그대로 들어가면 검색 품질이 떨어진다. RAG는 멋진 모델보다 깨끗한 텍스트를 더 좋아한다.

청킹: 문서를 적당한 크기로 자르는 기술

문서를 통째로 검색하면 왜 안 될까? 이유는 간단하다. 너무 크기 때문이다. 사용자의 질문은 보통 문서 전체가 아니라 문서의 일부 문단과 관련 있다. 그런데 긴 문서 전체를 한 덩어리로 저장하면 검색 결과가 거칠어지고, 프롬프트에 넣기에도 부담스럽다.

그래서 문서를 작은 조각으로 나누는데, 이 작업을 청킹이라고 한다. 청크는 검색 가능한 최소 단위라고 생각하면 된다. 보통 한두 문장보다 길고, 문서 전체보다는 훨씬 짧다. 적당한 길이의 문단 묶음이라고 상상하면 이해하기 쉽다.

청킹에서 가장 흔한 질문은 "몇 글자, 몇 토큰으로 나눠야 하나요?"다. 정답은 고정 숫자가 아니라 문서의 성격에 따라 달라진다. 규정집처럼 문단 단위 의미가 또렷한 문서는 문단 기준 청킹이 잘 맞고, API 문서처럼 항목 구조가 명확한 문서는 섹션 기준 청킹이 더 좋다. 너무 짧게 자르면 맥락이 찢어지고, 너무 길게 자르면 검색이 뭉개진다.

청킹을 잘한다는 것은 단순히 같은 길이로 칼질하는 것이 아니다. 의미 단위를 보존하는 것이 핵심이다. 제목과 본문을 함께 묶을지, 표의 헤더와 행을 어떻게 살릴지, 질문-답변 형식 문서를 하나의 청크로 둘지 같은 판단이 필요하다.

실무에서는 겹침, 즉 오버랩도 자주 사용한다. 예를 들어 앞 청크의 마지막 몇 문장을 다음 청크에도 일부 포함시키는 방식이다. 이렇게 하면 경계에서 잘린 정보를 어느 정도 복원할 수 있다. 다만 오버랩이 너무 크면 저장량과 검색 중복이 늘어난다.

좋은 청킹의 기준은 아름다운 분할이 아니라, 사용자의 질문에 답할 때 필요한 근거가 하나 또는 소수의 청크 안에 자연스럽게 담기는가에 있다.

임베딩: 의미를 숫자로 바꾸는 과정

청크를 나눴다면 이제 검색하기 좋게 바꿔야 한다. 여기서 등장하는 것이 임베딩이다. 임베딩은 텍스트의 의미를 숫자 벡터로 표현한 것이다. 벡터라는 말이 어렵게 들릴 수 있지만, 여기서는 "의미를 비교하기 위한 좌표" 정도로 이해하면 충분하다.

예를 들어 "환불 신청 방법"과 "환불은 어떻게 요청하나요?"는 단어가 완전히 같지 않아도 의미는 비슷하다. 키워드 검색만 쓰면 이 둘의 연결이 약할 수 있지만, 임베딩 검색은 의미의 유사성을 더 잘 포착한다. 그래서 RAG에서는 보통 각 청크를 임베딩으로 변환해 저장해 둔다.

사용자의 질문이 들어오면 질문도 같은 방식으로 임베딩하고, 질문 벡터와 가까운 청크 벡터를 찾는다. 가까울수록 의미가 비슷하다고 보는 것이다. 이것이 벡터 검색의 핵심이다.

여기서 주의할 점이 있다. 임베딩은 마법이 아니다. 문서가 지저분하거나, 청킹이 나쁘거나, 질의가 지나치게 모호하면 검색 성능도 떨어진다. 또 문서와 질문의 언어가 섞여 있거나 도메인 용어가 강한 경우에는 임베딩 모델 선택이 결과에 영향을 준다. 즉, 임베딩은 중요하지만 만능 열쇠는 아니다.

검색: 많이 찾는 것이 아니라 맞게 찾는 것

RAG의 심장은 검색이다. 사용자의 질문이 들어오면 시스템은 관련 있는 청크를 찾아 상위 몇 개를 반환한다. 이때 중요한 것은 많이 찾는 것이 아니라, 필요한 근거를 정확히 찾는 것이다.

가장 단순한 방식은 벡터 유사도 검색이다. 질문 임베딩과 가까운 청크를 상위 K개 고른다. 하지만 실무에서는 이 방식만으로 부족한 경우가 많다. 예를 들어 정확한 제품명, 에러 코드, 조항 번호처럼 특정 키워드가 중요한 질문은 전통적인 키워드 검색이 더 강할 수 있다.

그래서 자주 쓰는 방식이 하이브리드 검색이다. 의미 기반 벡터 검색과 키워드 검색을 함께 활용하는 방식이다. 쉽게 말해 "비슷한 뜻도 찾고, 정확한 단어도 놓치지 않기" 전략이다.

또 검색에는 필터가 중요하다. 사용자의 조직, 권한, 문서 버전, 문서 유형, 날짜 범위, 언어에 따라 검색 대상을 좁혀야 한다. 검색 품질 문제처럼 보이지만 사실은 필터 부재 문제인 경우가 많다. 모든 문서를 한 바구니에 넣고 유사도만 믿으면, 관련은 있지만 쓰면 안 되는 문서가 올라올 수 있다.

검색 단계에서는 재정렬도 고려할 수 있다. 먼저 넓게 후보를 찾고, 그다음 더 정교한 기준으로 순서를 다시 매기는 것이다. 초반에는 복잡하게 시작할 필요는 없지만, 서비스가 커질수록 "찾았는가"뿐 아니라 "맨 위에 제대로 올렸는가"가 중요해진다.

컨텍스트 주입: 찾은 문서를 어떻게 답변에 쓰게 할 것인가

좋은 검색 결과를 얻었다고 끝이 아니다. 모델이 그 정보를 제대로 활용해야 한다. 검색된 청크를 프롬프트에 넣는 과정을 컨텍스트 주입이라고 한다.

여기서 흔히 하는 실수는 관련 문서를 잔뜩 집어넣는 것이다. 하지만 컨텍스트는 많다고 좋은 것이 아니다. 관련 없는 정보가 섞이면 오히려 모델이 길을 잃는다. 긴 회의에서 말 많은 사람이 꼭 핵심을 잘 아는 건 아닌 것과 비슷하다.

컨텍스트 주입의 기본 원칙은 단순하다. 질문에 답하는 데 필요한 정보만 넣고, 모델에게 그 정보 안에서 답하게 지시하는 것이다. 예를 들어 시스템 프롬프트나 개발자 프롬프트에서 다음과 같은 규칙을 줄 수 있다. 제공된 문서를 우선 사용하고, 문서에 없는 내용은 모른다고 말할 것, 가능하면 근거 문서 제목이나 인용 구간을 함께 제시할 것 등이다.

이 단계에서 답변 형식도 매우 중요하다. 사내 도구라면 간단한 답과 함께 근거 문서 링크를 붙이는 것이 좋고, 고객용 서비스라면 친절한 설명 뒤에 "참고한 정책"을 덧붙이는 식이 더 적절할 수 있다. 즉, 컨텍스트 주입은 단순한 데이터 전달이 아니라 사용자 경험 설계의 일부다.

예제로 보는 RAG의 동작

온라인 쇼핑몰 운영팀을 위한 내부 상담 봇을 만든다고 가정해 보자. 이 봇은 배송 지연 대응, 환불 기준, 쿠폰 정책, CS 응대 문구를 안내해야 한다.

운영팀은 다음과 같은 문서를 가지고 있다. 환불 정책 문서, 배송 SLA 문서, 프로모션 운영 가이드, 고객 응대 매뉴얼, 장애 시 공지 템플릿. 이 문서들을 텍스트로 정리해 적재하고, 의미 단위로 청킹한 뒤, 각 청크를 임베딩해 저장한다.

이제 사용자가 "부분 환불은 배송 지연 때도 가능한가요?"라고 묻는다. 시스템은 질문을 임베딩한 뒤 관련 청크를 검색한다. 환불 정책 문서의 '부분 환불 조건' 섹션, 배송 지연 보상 기준 섹션, 예외 상황 처리 규정이 상위에 올라온다. 그리고 이 내용을 프롬프트에 함께 넣어 모델이 답변한다.

좋은 답변은 단순히 "가능합니다"가 아니다. 예를 들어 다음처럼 나와야 한다. 배송 지연만으로 자동 부분 환불이 되는 것은 아니며, 지연 사유와 고객 피해 범위에 따라 보상 또는 쿠폰 제공이 우선 검토된다. 다만 특정 조건에서는 부분 환불이 가능하다. 자세한 기준은 운영 정책 4.2와 배송 예외 규정 3.1을 따른다.

이 답변이 좋은 이유는 세 가지다. 내부 기준에 맞고, 근거를 좁혀 설명하며, 없는 규정을 지어내지 않기 때문이다. 바로 이것이 RAG가 서비스 품질에 주는 실질적 이점이다.

RAG 품질을 망치는 흔한 실수

RAG는 개념은 간단하지만 실제 품질은 쉽게 무너진다. 초반에 자주 겪는 실수들을 알아두면 시행착오를 많이 줄일 수 있다.

  • 문서 정리를 대충 하는 경우다. 오래된 버전, 중복 문서, 깨진 텍스트가 섞이면 검색도 답변도 혼란스러워진다.

  • 청킹을 너무 작게 하거나 너무 크게 하는 경우다. 전자는 맥락 손실, 후자는 검색 정확도 저하로 이어진다.

  • 검색 결과를 너무 많이 넣는 경우다. 관련성보다 양을 믿으면 모델이 핵심을 놓친다.

  • 메타데이터와 권한 필터를 무시하는 경우다. 검색 성능 이전에 보안 문제가 생길 수 있다.

  • 문서에 없는 내용을 모델이 보충하도록 방치하는 경우다. "모르면 모른다고 답하기" 규칙이 없으면 환각이 늘어난다.

이 다섯 가지는 모두 아주 현실적인 문제다. 멋진 아키텍처보다 먼저 이 기본 실수들을 줄이는 편이 훨씬 효과적이다.

RAG와 파인튜닝은 어떻게 다른가

초보 팀이 자주 헷갈리는 질문이 있다. "우리 서비스는 RAG를 써야 하나요, 아니면 모델을 튜닝해야 하나요?"

둘은 경쟁 관계라기보다 역할이 다르다. RAG는 외부 지식을 그때그때 가져와 답하게 하는 방식이고, 파인튜닝은 모델의 출력 습관이나 특정 작업 스타일을 길들이는 방식에 가깝다.

최신 정보, 사내 문서, 자주 바뀌는 정책을 다뤄야 한다면 RAG가 우선이다. 반대로 항상 같은 형식으로 답해야 하거나 특정 분류 기준을 매우 일관되게 적용해야 한다면 파인튜닝이나 다른 규칙 기반 보완이 도움이 될 수 있다.

실무에서는 둘을 함께 쓰기도 한다. 하지만 시작점으로는 대개 RAG가 더 현실적이다. 이유는 지식의 변경 주기가 빠르기 때문이다. 서비스 운영은 늘 변하고, 문서는 늘 업데이트된다. 그때마다 모델을 다시 다루는 것보다 문서 인덱스를 갱신하는 편이 훨씬 민첩하다.

최소한의 RAG는 어떻게 시작할까

처음부터 거대한 사내 검색 플랫폼을 만들 필요는 없다. 오히려 작게 시작하는 편이 좋다. 가장 추천하는 출발점은 범위가 좁고 문서 품질이 상대적으로 좋은 한 가지 문제를 선택하는 것이다. 예를 들어 고객센터의 환불 정책 챗봇이나 특정 제품 매뉴얼 Q&A처럼 답의 범위를 제한할 수 있는 주제가 적합하다.

처음 버전에서는 다음 정도면 충분하다.

  • 신뢰할 수 있는 문서 소스 하나를 정한다.

  • 문서를 정리해 텍스트와 메타데이터를 저장한다.

  • 의미 단위 중심의 단순한 청킹을 적용한다.

  • 임베딩 기반 검색으로 상위 몇 개 청크를 찾는다.

  • 검색된 문서만 근거로 답하게 프롬프트를 설계한다.

이렇게 만든 뒤에는 모델 교체보다 검색 결과를 직접 눈으로 보는 일이 더 중요하다. 사용자의 질문 20개 정도를 모아, 어떤 문서가 검색되었는지, 빠진 근거는 무엇인지, 청킹이 이상한 부분은 없는지 확인해 보자. RAG 품질 개선의 절반은 검색 결과를 읽어 보는 데서 시작한다.

서비스 관점에서 기억해야 할 핵심

RAG를 단지 "LLM 앞에 검색 붙이기" 정도로 이해하면 금방 한계에 부딪힌다. 서비스 관점에서 보면 RAG는 세 가지 층위가 동시에 맞아야 한다.

첫째는 데이터 층위다. 어떤 문서를 넣고 어떤 메타데이터를 관리할지 결정해야 한다. 둘째는 검색 층위다. 질문과 관련 있는 정보를 얼마나 잘 가져오는지가 핵심이다. 셋째는 응답 층위다. 가져온 정보를 사용자가 신뢰할 수 있는 형태로 설명해야 한다.

이 셋 중 하나라도 약하면 결과가 흔들린다. 문서가 나쁘면 검색이 좋아도 소용없고, 검색이 나쁘면 모델이 똑똑해도 소용없고, 응답 설계가 나쁘면 근거가 있어도 사용자가 불편해한다.

즉, RAG는 AI 기능이면서 동시에 정보 시스템이다. 그리고 그래서 더 중요하다. 최신 정보와 사내 지식을 다뤄야 하는 서비스라면 RAG는 있으면 좋은 옵션이 아니라, 제대로 만들기 위해 반드시 갖춰야 할 기본기다.

정리

이번 장에서 본 RAG의 핵심은 아주 명확하다. 모델에게 모든 것을 외우게 하려 하지 말고, 필요한 정보를 먼저 찾게 하라는 것이다. 그 흐름은 문서 적재, 청킹, 임베딩, 검색, 컨텍스트 주입으로 이어진다.

문서 적재는 무엇을 지식으로 삼을지 정하는 단계이고, 청킹은 검색 단위를 만드는 작업이며, 임베딩은 의미 기반 검색을 가능하게 하는 표현 방식이다. 검색은 관련 근거를 찾아오는 과정이고, 컨텍스트 주입은 그 근거를 바탕으로 모델이 답하게 만드는 단계다.

이 다섯 단계를 이해하면, 왜 어떤 RAG 시스템은 놀랄 만큼 정확하고 어떤 시스템은 엉뚱한 답을 하는지 감이 잡히기 시작한다. 다음 장에서는 이 기본기를 바탕으로 파일, 문서, 멀티모달 입력을 실제 서비스에서 어떻게 다뤄야 하는지 더 넓게 살펴보겠다.

책 목록

실전 LLM 서비스 개발: ChatGPT·Claude·Gemini API로 만드는 AI 웹 서비스의 설계부터 운영까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기