RAG 시스템 구현: 크롤링

발행: (2026년 3월 25일 AM 03:00 GMT+9)
7 분 소요
원문: Dev.to

Source: Dev.to

소개

저는 “Crawl, walk, run” 시리즈 게시물을 다양한 주제로 시작하려고 합니다. 첫 번째 주제로 Retrieval‑Augmented Generation (RAG)을 선택했습니다. 이번 단계에서는 RAG 시스템의 핵심 개념을 다루고, 브리티시 컬럼비아 주 정부의 HR 정책 PDF를 지식 베이스로 사용한 간단한 예제로 적용해 보겠습니다. 문서를 처리하고, 청크화하고, 로컬 벡터 데이터베이스에 임베딩함으로써, 에이전트가 BC 정부 정책에서 직접 추출한 근거 있는 답변을 제공할 수 있게 됩니다.

RAG는 표준 LLM을 정보에 기반한 AI 에이전트로 전환하는 일반적인 설계 패턴입니다. 표준 모델이 “블랙 박스”처럼 동작하는 반면, RAG는 에이전트에게 “오픈‑북 테스트”를 제공하여 문서에 직접 연결함으로써 지식 컷오프를 우회하고 사실적 근거와 인용을 제공합니다. 파인‑튜닝이 필요 없으며, 데이터를 빠르게 업데이트할 수 있어 LLM과 데이터 사이에 실시간 다리를 구축할 수 있습니다.

청킹 및 분할

모든 정보를 매번 AI에 입력하는 것은 현실적이지 않습니다. 대신 텍스트를 청크라 불리는 더 작고 관리하기 쉬운 조각으로 나누어 AI가 효율적으로 처리하고 검색할 수 있게 합니다.

코드: LangChain으로 PDF 분할

from langchain_community.document_loaders import PyPDFLoader, DirectoryLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

loader = DirectoryLoader(
    DATA_DIR,
    glob="./**/*.pdf",
    loader_cls=PyPDFLoader
)
docs = loader.load()

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=100
)
chunks = text_splitter.split_documents(docs)

재귀 문자 청킹은 고정 크기 청킹에 비해 겹침을 보장함으로써 청크 경계에서 부분 문장이 손실되는 것을 방지합니다.

임베딩

임베딩 과정은 텍스트 청크를 벡터(의미를 포착하는 부동소수점 숫자 배열)로 변환합니다. 차원이 높다고 해서 항상 더 좋은 결과가 나오는 것은 아니며, 간단한 문서의 경우 검색 정확도를 향상시키지 못하고 지연 시간과 계산 오버헤드만 증가시킬 수 있습니다.

핵심 포인트

  • 일관된 모델: 인덱싱과 검색 모두에 동일한 임베딩 모델을 사용하세요. 모델마다 단어의 중요도를 다르게 평가할 수 있어(예: 주어 vs. 동작) 결과에 영향을 줄 수 있습니다.
  • 임베딩 유형 선택: 문서는 보통 길고 구조화되어 있는 반면, 사용자 쿼리는 짧고 노이즈가 많습니다. 이러한 비대칭을 잘 처리할 수 있는 임베딩 모델을 선택하세요.

유사도 검색

사용자 쿼리가 임베딩되면, RAG 시스템은 벡터 데이터베이스에 대해 유사도 검색을 수행하여 가장 관련성이 높은 청크를 찾습니다. 대부분의 벡터 데이터베이스는 코사인 유사도를 사용하며, 이는 벡터의 크기가 아니라 벡터 사이의 각도를 측정합니다. 이를 통해 시스템은 길이와 단어 빈도가 다른 텍스트들 사이에서도 의도를 매칭할 수 있습니다.

에이전트 구현

HR 질문을 처리하기 위해 Google의 Agent Development Kit (ADK) 를 사용하여 RAG 시스템에 직접 연결되는 에이전트를 구축했습니다.

Code: Defining the HR Agent

from .tools import query_hr
from langchain.tools import FunctionTool
from langchain.agents import LlmAgent

hr_rag_tool = FunctionTool(func=query_hr)

hr_agent = LlmAgent(
    name="hr_agent",
    model="gemini-3.1-pro-preview",
    description="Specialist in company HR policies and procedures.",
    instruction=(
        "You are a professional HR assistant. Your goal is to answer questions "
        "using ONLY the information retrieved from the 'query_hr' tool. "
        "When calling the 'query_hr' tool, ensure all string arguments are properly formatted as standard JSON strings with double quotes.\n\n"
        "RULES:\n"
        "1. If the tool returns relevant information, summarize it clearly.\n"
        "2. You MUST cite your sources using the format: (Source: [Source Name], Page: [Page Number]).\n"
        "3. If the tool results do not contain the answer, state: 'I'm sorry, I couldn't find that in our HR documents.'\n"
        "4. Do not use outside knowledge or make up facts about company policy."
    ),
    tools=[query_hr],
)

에이전트에 명확한 지시와 벡터 데이터베이스를 검색할 올바른 도구를 제공함으로써, 사용자는 몇 초 안에 정확한 답변을 얻을 수 있습니다.

다음 단계

프로토타입은 작동하지만 개선할 여지가 많습니다. 이 간단한 RAG 시스템을 고성능 엔진으로 발전시키기 위해 향후 작업은 다음에 집중될 것입니다:

  1. 청크 세분화 개선: 다양한 청크 크기와 겹침 전략을 실험합니다.
  2. 재정렬 레이어: 검색된 결과의 관련성을 높이기 위해 재정렬 단계를 도입합니다.
  3. 정밀도 향상: 임베딩 모델과 유사도 임계값을 최적화합니다.

아직 Agent Development Kit을 사용해보지 않았고 더 알고 싶다면 ADK Crash Course – From Beginner to Expert 를 확인하세요. 이 코스에는 무료 GCP 크레딧을 받을 수 있는 링크가 포함되어 있습니다.

Repository

전체 코드와 데이터는 제 GitHub 저장소에서 확인하실 수 있습니다 → 여기.

0 조회
Back to Blog

관련 글

더 보기 »