생성과 검색의 하모니: RAG로 더 똑똑한 AI 만들기

Introduction

대규모 언어 모델(Large Language Model, LLM)은 놀라운 생성 능력을 보여주며 전 세계를 매료시켰습니다. 그러나 아무리 똑똑해 보여도, 이들은 하나의 치명적인 한계를 가지고 있습니다.

바로 거짓말을 너무 그럴듯하게 한다는 것입니다. (우아하게 표현하면 “Hallucination”이라 부르죠.)

모델이 알고 있는 지식은 학습 당시 데이터에만 기반합니다. 시간이 흐르면 정보는 낡아지고, 애초에 학습되지 않은 내용은 아예 알 수조차 없습니다.

“최신 뉴스 알려줘” “우리 회사 정책 요약해줘” 같은 요청을 던졌을 때, 모델이 거침없이 잘못된 답을 만들어내는 이유입니다.

이 문제를 해결하기 위해 등장한 접근 방식이 바로 RAG(Retrieval-Augmented Generation) 입니다.

이름 그대로, 검색(Retrieval) 을 통해 외부의 신선하고 신뢰할 수 있는 정보를 가져오고, 이를 바탕으로 생성(Generation) 을 수행하는 방식입니다.

쉽게 말하면,

“AI에게 최신 백과사전을 손에 쥐어주고 답변하라고 시키는 것”

이라고 생각하면 됩니다.

이 글에서는 RAG의 기본 개념부터 구조, 활용 방법, 그리고 도입 시 고려해야 할 포인트까지 체계적으로 정리해 보겠습니다.

RAG

RAG의 정의

RAGRetrieval-Augmented Generation의 약자로,

직역하면 “검색 강화 생성” 이라는 다소 생소한 표현이 됩니다.

좀 더 풀어서 설명하면,

“모델이 답변을 만들기 전에, 외부에서 신뢰할 수 있는 정보를 먼저 찾아오는 과정”을 추가한 생성 방식을 뜻합니다.

기존 LLM은 질문을 받으면 오직 자신의 내부 파라미터(학습된 지식)에만 의존해 답변을 생성합니다.

반면, RAG는 다음과 같은 두 단계로 동작합니다.

  1. 검색(Retrieval): 질문에 적합한 관련 문서를 외부 데이터 소스(예: 데이터베이스, 문서 저장소, 벡터 데이터베이스 등)에서 찾아옵니다.
  2. 생성(Generation): 검색된 문서들을 참고하여, 보다 정확하고 사실에 근거한 답변을 생성합니다.

즉, 기존 LLM의 기억력(모델 파라미터) 만으로 답하는 대신,

RAG는 필요한 내용을 실시간으로 찾아서 반영하는 “현명한 방법”을 택한 것입니다.

비유하자면,

“혼자 시험을 치는 학생”이 아니라,

교과서와 노트를 옆에 두고 시험을 치는 학생”이라고 볼 수 있습니다.

덕분에,

  • 최신 정보 반영,
  • 정확성 향상,
  • 도메인 특화 와 같은 장점이 생기며, 다양한 실제 업무에 활용 가능한 수준으로 진화하게 됩니다.

왜 RAG 가 필요한가

대규모 언어 모델(LLM)은 방대한 데이터로 학습되어 매우 다양한 질문에 답할 수 있습니다.

그러나, 그들의 “지식”은 학습 시점에 고정되어 있으며, 시간이 지나면 현실과 점점 어긋나기 시작합니다.

대표적인 문제는 다음과 같습니다:

  • 지식의 최신성 부재 → 모델이 최신 사건이나 변동 사항을 반영할 수 없습니다. (예: “2025년에 출시된 신제품 정보를 알려줘” → 대답 불가)
  • Hallucination(환각 현상) → 사실과 다른 답변을 그럴듯하게 만들어냅니다. (예: 존재하지 않는 논문, 허구의 제품 설명)
  • 도메인 전문성 한계 → 특정 기업, 특정 산업, 특정 제품과 같은 전문 지식에는 취약합니다. (예: “우리 회사 전용 ERP 시스템 설명해줘” → 대충 얼버무리는 답변)

RAG는 이 문제들을 해결합니다.

  • 모델이 외부 데이터 소스를 검색하여,
  • 최신, 정확, 도메인 특화 정보를 활용한 답변을 생성합니다.

즉,

“모델 자체를 계속 재학습(fine-tuning)할 필요 없이”,

“지식 업데이트를 외부 데이터로 즉시 반영”할 수 있습니다.

이 접근법은 특히 다음과 같은 상황에서 강력한 힘을 발휘합니다:

상황전통 LLMRAG 활용 시
1. 최신 뉴스 요약불가능가능
2. 기업 내부 문서 기반 답변어려움가능
3. 민감한 데이터 반영 (사내 데이터 등)곤란가능
4. 비용 및 유지보수(모델 재학습)매우 큼대폭 절감

RAG의 기본 구조

RAG는 겉으로 보기엔 단순하지만, 내부적으로는 검색과 생성의 절묘한 협력으로 움직입니다.

구조를 이해하면, 왜 이 방식이 LLM의 약점을 극복할 수 있는지 자연스럽게 알 수 있습니다.

RAG는 크게 두 개의 핵심 컴포넌트로 구성됩니다:

1. Retriever (검색기)

  • 사용자의 질문(쿼리)을 받아,
  • 외부 데이터 소스(문서, 데이터베이스, 벡터DB 등)에서
  • 관련성 높은 문서나 정보를 검색합니다.

쉽게 말하면, “책꽂이에서 필요한 책을 순식간에 찾아오는 사서”입니다.

Retriever의 성능이 좋을수록, 모델이 참고할 정보의 품질이 높아지고,

그 결과 최종 답변의 정확도도 함께 올라갑니다.

주요 기술 요소:

  • 문서 임베딩(Embedding)
  • 벡터 검색(Vector Search)
  • 유사도(Similarity) 기반 검색 알고리즘

2. Generator (생성기)

  • Retriever가 가져온 문서를 입력으로 받아,
  • 문서의 내용을 분석하고,
  • 질문에 맞는 자연스러운 답변을 LLM을 통해 생성합니다.

비유하자면, “찾아온 책을 읽고, 질문에 맞춰 요약해주는 똑똑한 비서”입니다.

Generator는 검색된 정보만 참고하기 때문에,

  • Hallucination(환각) 발생 확률이 줄어들고,
  • 사실 기반(Fact-based) 답변을 생성할 수 있습니다.

전체 흐름을 요약하면 다음과 같습니다.

  1. 사용자가 질문을 입력합니다.
  2. Retriever가 관련 문서나 데이터를 빠르게 찾아옵니다.
  3. Generator가 이 자료를 읽고, 질문에 대한 답변을 만듭니다.
  4. 최종 사용자에게 팩트 기반의 답변이 제공됩니다.

대표적인 RAG 아키텍처

RAG는 “검색하고 생성한다”는 단순한 개념 위에 구축되지만,

구현 방식은 사용하는 도구와 목적에 따라 다양하게 달라집니다.

대표적인 RAG 아키텍처는 다음과 같은 구성요소를 중심으로 설계됩니다:


1. OpenAI + 벡터DB 기반 아키텍처

  • LLM: OpenAI의 GPT-4 또는 GPT-3.5 Turbo 등 사용
  • Embedding 모델: OpenAI의 text-embedding-ada-002 등
  • Vector DB: Pinecone, Weaviate, FAISS, Chroma 등
  • 흐름:
    1. 질문을 Embedding → 벡터화
    2. Vector DB에서 유사도 검색
    3. 검색된 문서를 Prompt에 삽입
    4. LLM이 최종 답변 생성

이 구조는 빠르게 구축할 수 있고, OpenAI의 최신 모델 성능을 손쉽게 활용할 수 있다는 장점이 있습니다.


2. Hugging Face RAG 모델 (End-to-End)

  • LLM + Retriever가 하나로 통합된 End-to-End 모델 제공
  • 대표 모델: facebook/rag-token-base, facebook/rag-sequence-base
  • 특징:
    • Retriever와 Generator가 학습 시부터 함께 최적화됨
    • 직접 fine-tuning 가능 (도메인 특화)

단점은 운영 복잡성과 자체 모델 관리 비용이 커질 수 있다는 점입니다.


3. AWS 기반 RAG (Bedrock + Knowledge Base)

  • LLM: Amazon Bedrock 기반 (Anthropic Claude, Cohere Command R, etc.)
  • Knowledge Base: Amazon OpenSearch Service 또는 자체 S3 문서 기반
  • Vector Search: Bedrock Knowledge Base 자동 관리
  • 흐름:
    1. Knowledge Base에 문서를 등록
    2. Bedrock이 질문을 Vector Search
    3. 검색 결과를 LLM에 전달
    4. LLM이 문서를 인용하며 응답 생성

AWS 환경에서 통합 인증, 보안 정책을 그대로 가져갈 수 있어, 기업용으로 매우 매력적입니다.


4. 자체 구축형 (Self-Hosted RAG)

  • Embedding 모델: OpenAI / Huggingface / Cohere / 자체 훈련 모델
  • Vector DB: FAISS / Vespa / Milvus 등
  • LLM: 오픈소스 모델 (LLaMA 3, Mistral, DeepSeek, 등) 또는 Huggingface Transformers
  • 흐름:
    1. 자체 서버 또는 클라우드에 모든 요소 구축
    2. 데이터 보안, 커스터마이징 자유도 극대화
    3. 운영 및 튜닝 비용 상승

📋 간단 요약 표

항목특징추천 대상
OpenAI + VectorDB빠른 구축, API 기반스타트업, 프로토타입
Huggingface RAGEnd-to-End 통합 학습 가능연구, 실험 목적
AWS Bedrock Knowledge Base통합 보안, 관리형 서비스엔터프라이즈 환경
자체 구축(Self-Hosted)자유도 최강, 운영 비용 높음대규모 커스터마이징 필요 기업

정리하면,

“RAG를 구축하는 방법은 많지만, 본인의 상황(속도, 비용, 자유도)에 맞춰 현명하게 선택해야 한다”는 것입니다.

RAG의 한계

RAG는 확실히 대규모 언어 모델의 한계를 극복하는 혁신적인 방법입니다.

그러나, 이 세상에 완벽한 기술이 없듯이, RAG 역시 몇 가지 중요한 한계를 가지고 있습니다.


1. 검색 품질에 따라 성능이 좌우된다

RAG의 기반은 “좋은 정보 검색”입니다.

검색된 문서가 부정확하거나, 질문과 관련성이 낮으면, 생성된 답변 역시 부정확해집니다.

“구글 검색이 엉뚱한 링크를 던져주면, 아무리 똑똑한 사람이 읽어도 엉터리 답을 할 수밖에 없겠죠?”

대응 방안: 좋은 Retriever와 양질의 데이터베이스가 필수입니다.


2. 실시간성(Latency) 문제가 발생할 수 있다

RAG는 검색 + 생성 두 단계를 거치기 때문에,

순수 LLM 호출보다 응답 시간이 길어질 수 있습니다.

  • 대용량 데이터셋을 검색해야 할 때
  • 네트워크 레이턴시가 있을 때
  • 복잡한 문서 Retriever 파이프라인을 사용할 때

“빨리빨리”를 외치는 세상에서, RAG는 때로는 한 박자 느린 대답을 할 수 있습니다.

대응 방안: 검색 최적화, 캐싱 전략 도입, 멀티스테이지 Retrieval 설계


3. 검색된 문서를 무조건 믿는다

현재 대부분의 RAG 시스템은,

검색된 문서가 진실인지 아닌지 검증하지 않고 그대로 답변에 반영합니다.

  • 가짜 뉴스
  • 오래된 정보
  • 편향된 데이터

이런 문서가 검색될 경우, 답변도 오류를 포함할 위험이 있습니다.

“엉터리 교과서를 들고 시험을 치는 것과 비슷한 상황”이 벌어질 수 있습니다.

대응 방안: 데이터 소스 품질 관리, 문서 평가 및 필터링 기능 추가


4. 복잡한 쿼리에 대한 한계

사용자 질문이 단순 검색으로 해결되지 않는 경우,

(예: 복잡한 추론, 요약, 다중 문서 조합 등)

기본 RAG만으로는 만족스러운 결과를 얻기 어렵습니다.

예시:

  • “다음 세 개 논문의 핵심 차이점을 표로 정리해줘”
  • “이 정책 변화가 향후 시장에 미칠 영향을 예측해줘”

이건 단순 검색 + 생성이 아니라 추론(Reasoning) 이 필요한 영역입니다.

대응 방안:

  • Multi-hop Retrieval
  • Re-ranking
  • Chain-of-Thought + RAG 조합 시도

RAG를 적용할 때 고려 사항

RAG는 뛰어난 기술이지만,

막상 실제 프로젝트에 적용하려고 하면 ‘기술’ 외에도 생각할 것들이 산처럼 많습니다.

단순히 모델을 고르는 것 이상의 고민이 필요합니다.


1. 데이터 품질이 최우선이다

RAG는 외부 데이터를 검색해서 답변을 생성하는 구조입니다.

“쓰레기를 검색하면, 쓰레기를 생성합니다.” (Garbage In, Garbage Out)

체크리스트:

  • 정확하고 신뢰할 수 있는 데이터인가?
  • 최신성을 유지하고 있는가?
  • 데이터 포맷(텍스트 정제, 청크 나누기)은 적절한가?

Tip:

가능하면 데이터에 버전 관리(Tagging) 를 적용해 두세요.

나중에 데이터 오류 추적이 훨씬 쉬워집니다.


2. Retriever의 성능을 신경 써라

아무리 대단한 LLM을 써도,

Retriever가 관련 문서를 못 찾아오면 헛수고입니다.

체크리스트:

  • Embedding 품질은 충분한가?
  • 벡터DB 튜닝(Top-K, nprobe 등)이 최적화되어 있는가?
  • Query Expansion, Reranking 적용 여부

Tip:

검색 품질 테스트를 주기적으로 하세요.

(실제 사용자 질문 100개 정도로 Recall/Precision 평가)


3. Prompt 설계를 신중하게 하라

검색된 문서를 모델에 넘길 때, Prompt에 어떻게 녹이느냐가 중요합니다.

체크리스트:

  • 문서 길이가 LLM 입력 한도(Token limit)를 넘지 않는가?
  • “문서 인용”을 유도하는 Prompt를 구성했는가?
  • 문서와 질문 간 관련성을 명확히 드러내는 문장 구조를 사용했는가?

Tip:

검색 결과를 “당신은 아래 문서만 참고해서 답변해야 합니다”라고 명시하는 식으로,

Hallucination 방지용 Prompt 가이드라인을 추가하세요.


4. Latency(지연 시간) 관리

RAG는 기본적으로 검색 + 생성 두 단계를 거칩니다.

즉, 단순 LLM보다 응답 시간이 느릴 수밖에 없습니다.

체크리스트:

  • 검색 시간을 최적화했는가? (Index 튜닝, 캐시 도입)
  • 문서 수를 Top-K 조정으로 제한했는가?
  • 비동기 처리를 통한 병렬 최적화를 적용했는가?

Tip:

중요한 시스템이라면 Latency SLA(서비스 응답 시간 기준)를 사전에 설정해두세요.

(예: 2초 이내 응답 보장)


5. 보안과 개인정보 보호

특히 기업 환경에서는,

검색 대상 문서나 생성된 답변이 민감 정보를 포함할 수 있습니다.

체크리스트:

  • 데이터 소스 접근 제어가 설정되어 있는가?
  • 검색 시 민감 정보 필터링이 적용되어 있는가?
  • 생성된 답변에 개인정보(PII)가 포함되지 않는가?

Tip:

Vector DB에도 암호화 저장(encrypted storage) 및 액세스 제어 정책을 적용하는 걸 잊지 마세요.

내 손으로 만들어보는 간단한 RAG

“좋다 좋다 하는데, 직접 안 해보면 남 얘기 같잖아요?”

이제 직접 RAG를 작동시켜 보겠습니다.

오늘 실습 목표는 심플합니다:

“PDF 문서 몇 개를 Vector DB에 저장하고, 질문하면 LLM이 검색 + 답변하도록 만든다.”

아키텍처 구성:

  • Embedding: AWS titan
  • Vector DB: FAISS (로컬 설치형)
  • LLM: OpenAI gpt-4 또는 gpt-3.5-turbo
  • 문서: 예제 PDF 파일 (ex: 회사 매뉴얼, 제품 설명서)

전체 코드 구조

rag-server/
 ├── main.py          # FastAPI 서버
 ├── document_loader.py # PDF 문서 로더
 └── vector_store.py    # 벡터DB 저장 및 검색 모듈

문서 로딩 및 벡터 DB 저장

  • document_loader.py
import fitz  # PyMuPDF
import pdfplumber
from typing import List

def extract_text_from_pdf(file_path: str) -> List[str]:
    texts = []
    with fitz.open(file_path) as doc:
        for page in doc:
            text = page.get_text()
            if text.strip():
                texts.append(text.strip())
    return texts

def extract_tables_from_pdf(file_path: str) -> List[str]:
    tables = []
    with pdfplumber.open(file_path) as pdf:
        for page in pdf.pages:
            table = page.extract_table()
            if table:
                table_text = "\\n".join(["\\t".join(row) for row in table if row])
                tables.append(table_text)
    return tables

def create_chunks(texts: List[str], chunk_size: int = 500) -> List[str]:
    chunks = []
    for text in texts:
        while text:
            chunks.append(text[:chunk_size])
            text = text[chunk_size:]
    return chunks
  • vector_store.py
import faiss
import numpy as np
import boto3
import json
from typing import List

# Bedrock Client
bedrock = boto3.client(
    service_name='bedrock-runtime',
    region_name='ap-northeast-2',  # 리전은 필요에 따라 수정
)

# Bedrock Embedding 호출 함수
def bedrock_embed(text: str) -> List[float]:
    response = bedrock.invoke_model(
        body=json.dumps({"inputText": text}),
        modelId="amazon.titan-embed-text-v2:0",  # Titan Embedding 모델 사용
        accept="application/json",
        contentType="application/json"
    )
    response_body = json.loads(response['body'].read())
    return response_body['embedding']

# FAISS Index 초기화
dimension = 1024  # Titan Embedding은 1536차원
index = faiss.IndexFlatL2(dimension)
stored_texts = []

def add_documents(texts: List[str]):
    vectors = []
    for text in texts:
        embedding = bedrock_embed(text)
        vectors.append(np.array(embedding, dtype=np.float32))
        stored_texts.append(text)
    index.add(np.vstack(vectors))

def retrieve_similar_documents(query: str, top_k: int = 5) -> List[str]:
    query_vector = np.array(bedrock_embed(query), dtype=np.float32).reshape(1, -1)
    distances, indices = index.search(query_vector, top_k)
    results = [stored_texts[i] for i in indices[0] if i < len(stored_texts)]
    return results

FastAPI 서버

from fastapi import FastAPI, UploadFile, File
from fastapi import Form
import os
from document_loader import extract_text_from_pdf, extract_tables_from_pdf, create_chunks
from vector_store import add_documents, retrieve_similar_documents

app = FastAPI()

UPLOAD_DIR = "/tmp"

@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
    contents = await file.read()
    file_path = os.path.join(UPLOAD_DIR, file.filename)

    with open(file_path, 'wb') as f:
        f.write(contents)

    texts = extract_text_from_pdf(file_path)
    tables = extract_tables_from_pdf(file_path)

    all_texts = texts + tables
    chunks = create_chunks(all_texts)

    add_documents(chunks)

    return {"message": f"{file.filename} uploaded and processed."}

@app.post("/ask")
async def ask_question(question: str = Form(...)):
    results = retrieve_similar_documents(question, top_k=5)
    return {"query": question, "results": results}

간단 테스트

  • RAG 데이터 입력
curl -X POST "<http://127.0.0.1:8000/upload>" -F "file=@/car_overview_test_english.pdf"

{"message": car_overview_test_english.pdf uploaded and processed."}
  • RAG 데이터 조회
curl -X POST "<http://127.0.0.1:8000/ask>" -F "question=What is an engine?"

{"query":"What is an engine?","results":["Overview of Cars\\n1. What is a Car?\\nA car is a vehicle designed for the transportation of people or goods. It primarily uses an engine to ge\\n2. Major Components\\nEngine: Device that provides power to the car\\nTransmission: Transfers the engine's power to the wheels\\nBrakes: Device that slows down or stops the car\\nTires: Parts that make contact with the road surface\\n3. Evolution of Cars\\n• In 1886, Karl Benz invented the world's first car.\\n• Rapid development followed alongside internal combustion eng","ine technology.\\n• Recently, eco-friendly cars such as electric and hydrogen vehicles have gained popularity.\\n4. Major EV Manufacturers\\nTesla - USA\\nHyundai - South Korea\\nBYD - China\\nVolkswagen - Germany","ine technology.\\n• Recently, eco-friendly cars such as electric and hydrogen vehicles have gained popularity.\\n4. Major EV Manufacturers\\nTesla - USA\\nHyundai - South Korea\\nBYD - China\\nVolkswagen - Germany","ine technology.\\n• Recently, eco-friendly cars such as electric and hydrogen vehicles have gained popularity.\\n4. Major EV Manufacturers\\nTesla - USA\\nHyundai - South Korea\\nBYD - China\\nVolkswagen - Germany","ine technology.\\n• Recently, eco-friendly cars such as electric and hydrogen vehicles have gained popularity.\\n4. Major EV Manufacturers\\nTesla - USA\\nHyundai - South Korea\\nBYD - China\\nVolkswagen - Germany"]}

Conclusion

대규모 언어 모델이 세상을 바꾸고 있는 지금, 그들의 약점을 보완하고 현실에 더 잘 맞는 답변을 제공하기 위한 필수 기술로 떠오른 것이 바로 RAG(Retrieval-Augmented Generation) 입니다.

단순히 “더 똑똑한 AI”를 만드는 것이 아니라 “신뢰할 수 있는 정보에 기반한 AI”를 만드는 방향으로의 진화 라고 볼 수 있습니다.

RAG는 단지 기술적 트렌드를 넘어,

기업 내부 지식 활용, 최신 정보 반영, 사용자 신뢰 확보라는 실질적 문제를 해결하는 열쇠로 활용될 수 있습니다.

하지만,

  • 데이터 품질
  • 검색 정확도
  • 응답 속도
  • 보안 및 프라이버시

등 현실적인 고려사항도 함께 챙겨야 실전에서 성공할 수 있습니다.

이제는 모델이 혼자 기억하는 시대에서,

“찾아서 답하는 시대”로 넘어가는 전환점에 서 있습니다.

RAG는 그 전환의 중심에 있습니다.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다