1. RAG 란?
RAG (Retrieval-Augmented Generation) 은 LLM 이 새로운 정보를 검색하고 통합할 수 있도록 하는 기술이다. LLM 이 외부 데이터 소스에서 정보를 검색한 뒤, 그 결과를 기반으로 응답을 생성하는 구조로 구성된다.
LLM 을 단독으로 사용했을 때 없는 사실을 생성하는 Hallucination 문제나, 최신 데이터 부족으로 인한 문제 등이 발생한다. RAG 를 사용하면 모델의 학습에 사용된 데이터 이외에 새로운 추가 정보를 제공함으로 이러한 문제들을 해결할 수 있다. 또한 응답 생성에 참고해야 하는 내용을 제공함으로 사용자가 원하는 내용을 더 정확하게 얻을 수 있다.
2. RAG 핵심 개념 및 동작 흐름

1) Indexing
사전 준비 단계로 RAG 를 구성하기 위해 데이터를 검색 가능한 형태로 변환하고 저장하는 단계이다. 문서를 chunk 단위로 분할하고 분할한 텍스트로 embedding 을 생성한다. 그리고 생성된 결과를 Vector DB 에 저장하여 추후 검색 가능한 상태로 준비한다.
2) Retrieval
사용자의 질문과 관련된 문서를 찾는 단계이다. 사용자 질문을 embedding 하여 vector 로 변환하고 변환된 쿼리로 유사도 계산을 통해 Vector DB 에서 관련성이 높은 문서들을 조회한다.
3) Augmentation & Genaration
검색된 결과를 기반으로 프롬프트를 구성하고 답변을 생성하는 단계이다. 검색 결과를 필터링하거나 re-ranking 을 통해 가공하여 사용한다.
그렇게 가공된 검색 결과와 사용자 질문에 프롬프트 엔지니어링을 적용하여 구성한 프롬프트를 LLM 에 전달하고 결과를 사용자에게 반환한다.
- Vector DB
문서 검색시에 단순한 키워드 검색이 아닌 의미 기반 검색을 위해서는 embedding 을 통해 데이터를 저장하고 이를 조회할 수 있어야 한다. 이를 위해서 사용되는 것이 Vector DB 이다.
미리 필요한 데이터들을 Vector DB 에 저장해두고 Retrieval 로 문서를 검색할 때에 사용한다.
3. RAG 구현 예제
이번에는 RAG 구현 예제를 작성해보려 한다. RAG 를 활용한 예제를 작성하기에 앞서 RAG 를 사용하지 않은 코드를 작성하고 똑같은 질문에 대해서 RAG 유무에 따라 어떻게 결과가 달라지는지 비교해보려 한다.
예제 쿼리는 chatGPT 로 생성했는데, 실제로 존재하지 않는 가상의 기술에 대한 질문을 한다. 이를 통해 관련 정보가 없는 질문에 대답할 때와 RAG 를 통해 해당 기술과 관련된 정보를 제공받았을 때의 답변 차이를 비교해보겠다.
먼저 RAG 를 사용하지 않고 LLM 쿼리를 실행하는 에제이다. Vector DB 나 특별한 데이터 관련 작업 없이 바로 OpenAI client 에게 쿼리를 요청한다.
from openai import OpenAI
LLM_MODEL = "gpt-5"
QUERY = "What is AcmeDB optimized for?"
client = OpenAI()
response = client.responses.create(
model=LLM_MODEL,
input=[
{"role": "user", "content": QUERY}
]
)
print(response.output_text)
코드를 실행한 결과는 아래와 같이 출력된다. "AcmeDB" 라는 기술에 대해서 정보가 없어서 대답을 할 수 없다는 응답을 반환했다.
I’m not sure which “AcmeDB” you mean—there are multiple projects and products with that name. Could you share a link or a brief description? With the specific AcmeDB in question, I can tell you exactly what it’s optimized for.
이번에는 RAG 를 통해 "AcmeDB" 에 대한 정보를 제공해주고 쿼리를 실행해보곘다.
쿼리를 날리기 앞서 chroma db 를 사용하여 AcmeDB 에 대한 정보를 가지고 있는 vector DB 를 먼저 생성한다. 그 다음 vector db 에 쿼리를 실행해서 질문과 관련된 문서들을 조회한다. 그리고 조회된 문서를 기반으로 LLM 모델에 전송할 프롬프트를 구성했다.
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
from openai import OpenAI
import chromadb
LLM_MODEL = "gpt-5"
EMBEDDING_MODEL = "text-embedding-3-small"
COLLECTION_NAME="my-collection"
QUERY = "What is AcmeDB optimized for?"
client = OpenAI()
# vector db 초기화
chroma_client = chromadb.Client()
embedding_function = OpenAIEmbeddingFunction(model_name=EMBEDDING_MODEL)
collection = chroma_client.create_collection(
name=COLLECTION_NAME,
embedding_function=embedding_function
)
# 문서 저장
documents = [
"AcmeDB is a distributed database optimized for write-heavy workloads. It uses LSM-tree and supports horizontal scaling."
]
collection.add(
documents=documents,
ids=["1"]
)
# 관련 문서 조회
results = collection.query(
query_texts=[QUERY],
n_results=1
)
documents = results["documents"][0]
# prompt 생성
context = "\n".join(documents)
prompt = f"""
Answer based only on the context below.
Context:
{context}
Question:
{QUERY}
"""
response = client.responses.create(
model=LLM_MODEL,
input=[
{"role": "user", "content": prompt}
]
)
print(response.output_text)
rag 기반으로 구성한 프롬프트의 질문 결과는 아래와 같이 출력되었다. vector DB 에 저장한 문서의 내용과 일치하는 것을 확인할 수 있다.
Write-heavy workloads.
[Reference]
- https://ko.wikipedia.org/wiki/%EA%B2%80%EC%83%89%EC%A6%9D%EA%B0%95%EC%83%9D%EC%84%B1
'AI' 카테고리의 다른 글
| [LLM] LangChain (0) | 2026.03.28 |
|---|---|
| [LLM] Vector, Embedding (0) | 2026.03.21 |
| [LLM] OpenAI SDK Quickstart (0) | 2026.03.09 |
| [LLM] LLM Provider 와 OpenAI API (0) | 2026.02.11 |