📚 Agentic AI - 기업용 자율 에이전트 개발 6장 · 에이전트 ④ RAG 문서검색 Agentic AI란

표가 아니라 긴 글에 답이 있을 때

한 줄 요약

1장의 마지막 질문 — "불량 상품 반품은 며칠 이내인가요?" 의 답은 CSV에도 웹에도 없습니다. 사내 PDF 안에 문장으로 적혀 있습니다. 문장은 계산할 수 없으니 찾아서 근거로 써야 합니다. 이 방식을 RAG 라고 합니다.


1. 지금까지의 세 에이전트로는 안 되는 질문

"승승장구몰에서 불량 상품 반품은 며칠 이내에 신청해야 하나요?"

에이전트 왜 안 되나
① 사내 데이터 조회 (3장) orders.csv 는 주문 기록입니다. 규정이 없습니다
② 웹검색 (4장) 승승장구몰은 가상의 회사입니다. 인터넷에 없습니다
③ CSV 데이터분석 (5장) 계산할 숫자가 아닙니다

답은 여기 있습니다.

data/docs/환불교환정책.pdf

  (주)승승장구  SEUNGSEUNG COMMERCE
  CS-POL-2026-014
  환불·교환·반품 운영 정책
  ...
  본 정책은 「전자상거래 등에서의 소비자보호에 관한 법률」에 근거하여
  승승장구몰(이하 '회사')이 판매하는 상품의 환불·교환·반품 ...

PDF 안에 문장으로 적혀 있습니다.


2. 숫자와 문장은 다르게 다룹니다

이번 장에서 가장 중요한 구분입니다.

5장 — CSV 데이터분석 6장 — RAG 문서검색
답이 있는 곳 표의 문서의 문장
질문 예 "평균 평점은?" "반품 기간은?"
답을 얻는 법 계산한다 찾아서 인용한다
도구가 하는 일 pandas 식 실행 관련 조각 검색
답의 성격 3.8 "수령일로부터 30일 이내"

"평균 평점 3.8" 은 원래 데이터 어디에도 안 적혀 있습니다. 계산으로 만들어 낸 값이죠.
"수령일로부터 30일 이내" 는 문서에 그대로 적혀 있습니다. 만들어 내면 안 되고, 찾아야 합니다.

이 구분이 흐려지면 위험합니다. 규정을 "계산"하려 들면 그게 곧 환각입니다. 1장에서 LLM이 일반 전자상거래법으로 반품 기간을 추론해 낸 것이 정확히 그 사고였습니다.


3. 그냥 PDF를 통째로 넣으면 안 되나

가장 단순한 방법부터 생각해 봅시다.

아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.

full_text = read_pdf_text()          # 5,526자
answer = llm.invoke(f"{full_text}\n\n질문: 반품은 며칠 이내인가요?")

우리 실습 문서 정도면 실제로 이렇게 해도 됩니다. PDF 5종을 다 합쳐도 5,526자니까요.

그런데 이 방법은 곧 무너집니다.

문서 양 통째로 넣기
PDF 5종 (5,526자) ✓ 된다
사규 100건 토큰 수가 늘어난다. 질문할 때마다 전부 보낸다
사내 문서 10,000건 컨텍스트 윈도를 넘는다

그리고 양이 적어도 문제가 있습니다.

  1. 질문할 때마다 전체를 보냅니다 → 2장에서 본 그 비용 문제
  2. 관련 없는 내용이 섞이면 답이 흐려집니다 → 로봇청소기 매뉴얼을 보며 반품 규정을 답하게 됩니다
  3. 어디서 나온 답인지 알 수 없습니다 → 출처를 못 밝힙니다

필요한 부분만 골라서 넣는 것이 RAG입니다.


4. RAG란

RAG(Retrieval-Augmented Generation) — 우리말로는 검색 증강 생성입니다. 이름 그대로입니다.

검색(Retrieval)   질문과 관련된 조각을 문서에서 찾는다
증강(Augmented)   그 조각을 프롬프트에 넣어 준다
생성(Generation)  LLM이 그것만 근거로 답을 만든다

그림으로 보면 이렇습니다.

질문"반품 며칠?"① 관련 조각 찾기검색"상품 불량·하자의 경우 수령일로부터 30일 이내…"② 조각 + 질문을 LLM에게"수령일로부터 30일 이내에 신청하셔야 합니다"근거: 환불교환정책.pdf 1쪽찾는 것과 답하는 것은 다른 일입니다. 답이 이상하면 검색과 답변 중 어느 단계의 문제인지 먼저 확인해야 합니다.
RAG 는 두 단계로 이루어진다 — 관련 조각을 찾고, 그 조각과 질문을 함께 LLM 에게 준다

핵심은 ①입니다. LLM은 그대로인데, 무엇을 보여 줄지가 달라집니다.


5. 검색이 어려운 이유

"관련된 조각을 찾는다"가 생각보다 까다롭습니다. 단어가 안 겹치기 때문입니다.

사용자가 묻는 말"반품 며칠 이내에 해야 하나요?"문서에 적힌 말"청약철회 기간은 상품 수령일로부터 …"↳ '반품'이라는 단어가 문서에는 없다단어가 겹치지 않아도 찾아내야 합니다. 그래서 글자가 아니라 의미로 찾는 임베딩이 필요합니다.
묻는 말과 문서의 말이 다르다 — 글자가 겹치지 않아도 찾아내야 한다

단어로 찾으면(if "반품" in 문장) 이 조각을 놓칩니다.

뜻이 비슷한 것을 찾아야 합니다. 그러려면 "뜻이 비슷하다"를 컴퓨터가 계산할 수 있어야 하죠.

그게 임베딩(embedding) 입니다. 3절에서 다룹니다. 미리 결과만 보면 이렇습니다.

질문: "불량 상품 반품은 며칠 이내에 신청해야 하나요?"

  0.815  상품 불량·하자의 경우 수령일로부터 30일 이내에 반품을 신청할 수 있습니다.
  0.726  단순 변심에 의한 청약철회는 수령일로부터 7일 이내에 가능합니다.
  0.588  VIP 등급은 6개월 누적 구매 금액 150만원 이상 고객에게 부여됩니다.
  0.518  배터리는 일반 사용 시 약 7일, GPS 사용 시 약 18시간 지속됩니다.

숫자가 높을수록 뜻이 가깝습니다. 관련 있는 두 문장이 위로 올라왔습니다.


6. 이번 장의 5단계

① 로드   PDF를 읽어 들인다                         (2절)
② 청킹   긴 글을 검색하기 좋은 조각으로 자른다        (2절)
③ 임베딩 조각을 '의미를 담은 숫자'로 바꾼다           (3절)
④ 저장   벡터를 인덱스에 담아 파일로 보관한다  ← 한 번만  (5절)
⑤ 검색   질문과 가까운 조각을 찾아 근거로 쓴다        (7절)

다섯 단계는 성격에 따라 두 종류로 나뉩니다. ①~④는 한 번만, ⑤는 질문할 때마다. 그림으로 보면 이렇습니다.

한 번만 — 인덱스 만들기PDF 5개Document 8쪽PyPDFLoader조각 15개Recursive(500,50)벡터 15개임베딩 API ×15인덱스save_local검색할 때 저장된 인덱스를 사용질문할 때마다질문벡터 1개임베딩 API ×1인덱스와 비교가까운 조각 k개프롬프트에 넣기 → LLM → 답 + 출처임베딩 API는 인덱스를 만들 때 15번, 질문할 때 1번만 부릅니다. 질문마다 문서 전체를 다시 읽지 않습니다.
인덱스 만들기는 한 번, 검색은 질문할 때마다 — 두 흐름을 갈라서 본다

위 띠는 한 번, 아래 띠는 질문마다. 두 띠를 잇는 것이 저장된 인덱스입니다.

④가 중요합니다. 임베딩은 시간과 비용이 듭니다. 한 번 만들어 파일로 저장해 두면 다음부터는 불러오기만 하면 됩니다. 이걸 안 하면 실행할 때마다 다시 만들며 시간을 버립니다 — 8장에서 이 인덱스를 가져다 쓸 때도 마찬가지고요.


7. 이번 장이 도착하는 곳

  Q: 불량 상품 반품은 며칠 이내에 신청해야 하나요?
  A: 상품 불량·하자로 인한 반품은 상품 수령일로부터 30일 이내에 신청하셔야 합니다.
  근거: 환불교환정책.pdf 1쪽, 환불교환정책.pdf 2쪽

  Q: 스마트워치 Fit 5의 배터리는 얼마나 가나요?
  A: 승승 스마트워치 Fit 5의 배터리는 일반 사용 시 약 7일, GPS 사용 시 약 18시간 지속됩니다.
  근거: 제품매뉴얼_스마트워치.pdf 1쪽, 멤버십정책.pdf 1쪽, 제품매뉴얼_로봇청소기.pdf 1쪽

  Q: 승승장구몰 해외 배송은 며칠 걸리나요?
  A: 사내 문서에서 해외 배송에 대한 정보를 찾을 수 없습니다.

세 가지를 눈여겨보세요.

  1. 1장에서 "3개월"이라고 지어냈던 답이 "30일"로 정확해졌습니다
  2. 출처가 붙습니다 — 어느 문서 몇 쪽인지
  3. 문서에 없는 것은 "찾을 수 없다" 고 합니다

출처가 답과 상관없어 보이는 문서까지 여러 개 나옵니다. 배터리 질문에 멤버십정책.pdf 가 왜 붙었을까요? 검색이 항상 정해진 개수를 돌려주기 때문입니다. 7절에서 다룹니다 — 지금은 "원래 그렇다"고만 알아 두세요.

두 번째가 특히 중요합니다. 답을 사람이 검증할 수 있게 됩니다. 3장 7절에서 "도구가 없는 영역은 여전히 위험하다"며 미뤄 둔 문제의 답이 이것입니다.

배터리 답을 기억해 두세요일반 7일 / GPS 18시간. 8장에서 이 숫자가 결정적인 근거가 됩니다. 5장에서 본 리뷰 불만 "GPS를 켜면 하루도 못 갑니다. 일주일 간다는 설명과 너무 달라요" 와 나란히 놓이는 순간, 무엇을 해야 할지가 보입니다.


핵심 정리

  • 표에 든 숫자는 계산하고, 문서에 쓰인 문장은 검색해서 근거로 씁니다. 이 구분이 흐려지면 환각입니다.
  • 문서를 통째로 넣는 것은 양이 늘면 무너집니다 — 비용·정확도·출처 세 가지 문제.
  • RAG = 검색(Retrieval) + 증강(Augmented) + 생성(Generation). 필요한 조각만 골라 넣습니다.
  • 검색이 어려운 이유는 단어가 안 겹치기 때문입니다. "반품"과 "청약철회"처럼요.
  • 그래서 임베딩으로 뜻이 얼마나 가까운지 숫자로 계산합니다.
  • 5단계 — 로드 · 청킹 · 임베딩 · 저장 · 검색. 저장은 한 번만 하면 됩니다.
  • 이번 장에서 처음으로 답에 출처를 붙입니다. 사람이 검증할 수 있게 됩니다.
  다음 절 →02. 왜 문서를 잘게 잘라야 하나 청킹