MongoDB Atlas 완전 정복 Part 5 — AI 시대의 Atlas: Vector Search, RAG, 에이전트 메모리
AI 시스템이 데이터 파편화 함정에 빠지는 이유를 진단하고, Atlas가 벡터 검색·하이브리드 검색·RAG 파이프라인·에이전트 메모리·실시간 스트림 처리를 하나의 플랫폼에서 통합하는 방법을 코드와 함께 단계적으로 설명한다. MongoDB Atlas 5편 시리즈 완결편.
시리즈 구성
목차
- AI 아키텍처 파편화의 함정 — Atlas 통합 전략
- Vector Search 완전 해부 — 임베딩부터 HNSW까지
- Voyage AI와 Automated Embedding
- Hybrid Search — 벡터와 키워드의 최적 결합
- RAG 파이프라인 구축 — LangChain + Atlas
- AI 에이전트 메모리 — LangGraph + Atlas
- Atlas Stream Processing — 실시간 AI 워크플로우
- GraphRAG — 관계 중심 지식 검색
- MongoDB Atlas 시리즈 최종 도입 결정 가이드
1. AI 아키텍처 파편화의 함정 — Atlas 통합 전략
AI 애플리케이션을 처음 구축할 때 팀은 자연스럽게 전문 도구를 조합한다. 운영 데이터는 PostgreSQL, 벡터 검색은 Pinecone이나 Weaviate, 캐시는 Redis, 이벤트 스트림은 Kafka, 임베딩 생성은 외부 API. 각 도구는 개별적으로 훌륭하지만 조합이 복잡해지면 문제가 시작된다.
[기존 AI 아키텍처 — 시스템 파편화]
서비스 계층
- PostgreSQL (운영 데이터)
- Pinecone / Weaviate (벡터 DB)
- Redis (캐시)
- Kafka (이벤트 버스)
- 외부 Embedding API (임베딩 생성)
실제 운영 비용:
- 데이터 동기화: 운영 DB 변경 시 벡터 DB도 반드시 갱신해야 함
- 보안 경계: 시스템마다 별도의 인증, 암호화, 감사 로그 설정
- 운영 포인트: 모니터링, 알림, 백업 대상이 시스템 수만큼 증가
- 일관성 리스크: 임베딩이 원본 데이터보다 오래된(stale) 상태 가능성
Atlas는 이 파편화를 하나의 플랫폼으로 통합한다는 설계 철학을 가진다. 운영 데이터, 벡터 검색, 전문 검색, 스트림 처리, 임베딩 생성 API를 같은 플랫폼에서 제공함으로써 동기화 문제와 보안 경계를 단순화한다.
이 통합 접근법이 항상 최선은 아니다. 팀이 이미 복잡한 관계형 조인이나 전문화된 스트리밍 시스템에 깊이 의존하고 있다면 억지로 Atlas로 이전하는 것보다 기존 스택을 유지하는 편이 낫다. 이 판단 기준은 이 글의 마지막 섹션에서 다룬다.
2. Vector Search 완전 해부 — 임베딩부터 HNSW까지
2-1. 임베딩이란 무엇인가
전통적인 키워드 검색은 단어가 일치하는지를 본다. 반면 벡터 검색은 의미를 본다. 임베딩 모델은 텍스트를 고차원 숫자 벡터로 변환하고, 의미가 가까운 텍스트는 벡터 공간에서도 거리가 가까워진다.
[임베딩 변환 예시]
"최신 스마트폰 충전기 추천" → [0.12, -0.84, 0.33, 0.67, ...] (1024차원)
"핸드폰 배터리 충전 제품" → [0.11, -0.81, 0.35, 0.65, ...] (1024차원) ← 의미 유사 → 거리 가까움
"자동차 엔진오일 교환" → [0.91, 0.42, -0.78, 0.22, ...] (1024차원) ← 의미 무관 → 거리 멀다
2-2. HNSW 인덱스와 벡터 검색 흐름
Atlas Vector Search는 HNSW(Hierarchical Navigable Small World) 그래프 알고리즘으로 근사 최근접 이웃 탐색을 수행한다. 수백만 개의 벡터 중에서 가장 유사한 문서를 밀리초 단위로 찾을 수 있는 이유가 HNSW의 계층적 그래프 탐색 덕분이다.
벡터 인덱스 생성
// mongosh로 벡터 인덱스 생성
db.products.createSearchIndex({
name: "vector_index",
type: "vectorSearch",
definition: {
fields: [
{
type: "vector",
path: "embedding",
numDimensions: 1024, // 임베딩 모델 차원 수에 정확히 맞춰야 함
similarity: "cosine" // cosine / dotProduct / euclidean 중 선택
},
{ type: "filter", path: "category" },
{ type: "filter", path: "price" }
]
}
})
| 유사도 지표 | 적합한 경우 | 특이사항 |
|---|---|---|
| cosine | 방향 기반 텍스트 의미 검색 | 벡터 크기(길이) 무관, 가장 보편적 |
| dotProduct | 정규화된 임베딩 벡터 | cosine과 동일 결과, 계산 비용 절감 가능 |
| euclidean | 절대 거리 기반 비교 | 이미지·지리 데이터에 적합 |
기본 벡터 검색 쿼리
// $vectorSearch aggregation pipeline
db.products.aggregate([
{
$vectorSearch: {
index: "vector_index",
path: "embedding",
queryVector: queryEmbedding, // 쿼리 텍스트의 임베딩 벡터
numCandidates: 100, // 후보 수 — topK의 10-20배 권장
limit: 5,
filter: { category: "전자제품" }
}
},
{
$project: {
name: 1,
description: 1,
score: { $meta: "vectorSearchScore" }
}
}
])
2-3. 벡터 양자화 — 메모리와 정확도 트레이드오프
Atlas Vector Search는 Automatic Quantization을 지원한다. 32비트 float 벡터를 압축된 표현으로 변환해 메모리 사용량을 줄이고 검색 처리량을 높인다. 정확도 손실은 어느 정도 발생하지만 실용적인 범위 안에서 조절할 수 있다.
// 양자화 옵션을 포함한 벡터 인덱스
db.products.createSearchIndex({
name: "vector_index_quantized",
type: "vectorSearch",
definition: {
fields: [{
type: "vector",
path: "embedding",
numDimensions: 1024,
similarity: "cosine",
quantization: "scalar" // "scalar" (int8) 또는 "binary"
}]
}
})
| 양자화 방식 | 메모리 절감 | 속도 | 정확도 보존 | 권장 상황 |
|---|---|---|---|---|
| 없음 (float32) | 기준 | 기준 | 100% | 정확도 최우선 소규모 컬렉션 |
| scalar (int8) | ~4배 | 향상 | ~95%+ | 균형 잡힌 운영 환경 |
| binary | ~32배 | 매우 향상 | ~85%+ | 대규모 근사 검색, 비용 우선 |
3. Voyage AI와 Automated Embedding
3-1. Voyage AI 임베딩 모델
MongoDB가 Voyage AI를 인수한 이후, Atlas는 임베딩 생성을 외부 API 없이 플랫폼 안에서 처리하는 방향으로 발전하고 있다. 소스 작성 시점(2026년 초)을 기준으로 Voyage 4 계열이 발표되었으며, 모델별 차원 수와 GA 상태는 공식 문서에서 반드시 확인해야 한다.
| 모델 | 차원 수 | 특징 | 권장 용도 |
|---|---|---|---|
| voyage-4-large | 1536 | 최고 정확도 | 고정밀 검색, 법률·의료 문서 |
| voyage-4 | 1024 | 균형·기본 | 일반적인 RAG 파이프라인 기본값 |
| voyage-4-lite | 512 | 고속·저비용 | 대용량 검색, 비용 최적화 |
| voyage-4-nano | 256 | 초경량 | 모바일 환경, 프로토타이핑 |
| multimodal-3.5 | 1024 | 텍스트+이미지 | 멀티모달 검색 |
모델 이름, 차원 수, 가용 리전은 출시 시점에 따라 달라질 수 있다. 프로덕션 도입 전에 Voyage AI 공식 문서와 Atlas 릴리즈 노트를 확인한다.
3-2. Automated Embedding — 임베딩 파이프라인 단순화
Automated Embedding은 벡터 인덱스 정의 시 임베딩 모델을 지정하면, 문서 삽입·업데이트 시 자동으로 임베딩을 생성하고 저장하는 기능이다. 별도의 임베딩 생성 파이프라인을 운영하지 않아도 된다.
// Automated Embedding 인덱스 정의
// API 형태는 공식 Atlas Vector Search 문서에서 최신 스펙 확인 필요
db.articles.createSearchIndex({
name: "auto_embed_index",
type: "vectorSearch",
definition: {
fields: [{
type: "vector",
path: "embedding",
autoEmbed: {
source: "content", // 임베딩 대상 텍스트 필드
model: "voyage-4" // 사용할 Voyage AI 모델
},
numDimensions: 1024,
similarity: "cosine"
}]
}
})
// 문서 삽입 시 embedding 필드가 Atlas에 의해 자동 생성됨
db.articles.insertOne({
title: "MongoDB Atlas 완전 정복",
content: "Atlas는 DBaaS를 넘어 AI 데이터 플랫폼으로..."
// embedding 필드: Atlas가 자동으로 채워서 저장
})
Automated Embedding의 도입 효과는 크다. 별도의 임베딩 서버가 없어도 되고, 원본 데이터와 임베딩의 동기화 문제가 플랫폼 수준에서 해결된다. 이 기능의 GA 상태, 지원 모델 목록, 과금 구조는 소스 작성 시점 이후 변경될 수 있으므로 공식 Atlas 릴리즈 노트를 기준으로 판단한다.
4. Hybrid Search — 벡터와 키워드의 최적 결합
4-1. 벡터 검색만으로 부족한 이유
벡터 검색은 의미적 유사도에 강하지만 정확한 키워드 매칭에는 약하다. "iPhone 15 Pro 충전기 문제"를 검색할 때 벡터 검색은 "스마트폰 충전 관련 문서"를 의미적으로 잘 찾지만, 정확히 "iPhone 15 Pro"라는 모델명이 포함된 문서를 우선시하지 못할 수 있다.
Atlas Search의 BM25 기반 전문 검색(Full-Text Search)은 정확한 키워드 일치에 강하다. Hybrid Search는 두 방식의 강점을 결합한다.
4-2. RRF — 두 결과를 하나로 융합하는 방법
RRF(Reciprocal Rank Fusion)는 벡터 검색 순위와 BM25 검색 순위를 수식으로 결합해 최종 순위를 도출하는 알고리즘이다. 각 후보 문서의 RRF 점수는 1 / (k + rank) 형태로 계산되며, 두 검색 결과에서 모두 상위에 랭크된 문서가 높은 최종 점수를 얻는다.
from langchain_mongodb import MongoDBAtlasVectorSearch
from langchain_mongodb.retrievers import MongoDBAtlasHybridSearchRetriever
# 하이브리드 검색 리트리버 구성
# 패키지명·클래스명은 langchain-mongodb 버전에 따라 달라질 수 있음
retriever = MongoDBAtlasHybridSearchRetriever(
vectorstore=vector_store,
search_index_name="search_index", # Atlas Search (BM25) 인덱스
top_k=5,
fulltext_penalty=60, # RRF k 파라미터 (BM25 측)
vector_penalty=60 # RRF k 파라미터 (벡터 측)
)
results = retriever.invoke("iPhone 15 Pro 충전기 문제")
RRF의 k 파라미터(위 코드에서 fulltext_penalty, vector_penalty)는 두 점수 체계의 균형을 조정한다. k가 클수록 순위 차이에 따른 점수 격차가 줄어들어 두 시스템의 결과가 더 균등하게 반영된다. 기본값 60은 범용적으로 검증된 시작점이다.
5. RAG 파이프라인 구축 — LangChain + Atlas
5-1. RAG가 필요한 이유
RAG(Retrieval-Augmented Generation)는 LLM이 "자신이 학습한 데이터 밖의 정보"를 데이터베이스에서 검색해 답변을 생성하는 패턴이다. LLM 단독 사용 시 발생하는 Hallucination(환각)과 최신 정보 부재 문제를 완화하는 현재 AI 애플리케이션의 핵심 설계 패턴이다.
5-2. 전체 RAG 파이프라인 구현
# pip install langchain-mongodb langchain-openai pymongo
from langchain_mongodb import MongoDBAtlasVectorSearch
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from pymongo import MongoClient
# 1. Atlas 연결 및 벡터 스토어 초기화
client = MongoClient(ATLAS_URI)
collection = client["mydb"]["documents"]
# Voyage AI 사용 시: from langchain_voyageai import VoyageAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
vector_store = MongoDBAtlasVectorSearch(
collection=collection,
embedding=embeddings,
index_name="vector_index",
text_key="content",
embedding_key="embedding"
)
# 2. 문서 수집 및 청킹 (Ingestion)
loader = PyPDFLoader("company_policy.pdf")
documents = loader.load()
splitter = RecursiveCharacterTextSplitter(
chunk_size=512, # 너무 크면 컨텍스트 품질 저하, 너무 작으면 맥락 손실
chunk_overlap=64, # 청크 경계에서 맥락이 잘리지 않도록 오버랩 설정
separators=["\n\n", "\n", ".", " "]
)
chunks = splitter.split_documents(documents)
vector_store.add_documents(chunks)
# 3. 검색기(Retriever) 설정
retriever = vector_store.as_retriever(
search_type="similarity",
search_kwargs={"k": 5, "score_threshold": 0.7}
)
# 4. RAG 체인 구성 (LangChain Expression Language)
llm = ChatOpenAI(model="gpt-4o", temperature=0)
prompt = ChatPromptTemplate.from_template("""다음 컨텍스트를 기반으로 질문에 답하세요.
컨텍스트에 없는 내용은 "해당 정보를 찾을 수 없습니다"라고 답하세요.
컨텍스트:
{context}
질문: {question}
답변:""")
def format_docs(docs):
return "\n\n---\n\n".join(
f"[출처: {doc.metadata.get('source', '없음')}, "
f"페이지: {doc.metadata.get('page', '-')}]\n{doc.page_content}"
for doc in docs
)
rag_chain = (
{"context": retriever | RunnableLambda(format_docs), "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
answer = rag_chain.invoke("연차 휴가 신청 방법은?")
print(answer)
5-3. Semantic Cache — LLM 비용 절감
동일하거나 의미적으로 유사한 질문이 반복될 때마다 LLM API를 호출하는 것은 비용 낭비다. Semantic Cache는 이전 질문-답변 쌍을 Atlas에 저장하고, 새 질문이 이미 처리된 질문과 충분히 유사하면 LLM 호출 없이 캐시에서 응답을 반환한다.
from langchain_mongodb.cache import MongoDBAtlasSemanticCache
from langchain.globals import set_llm_cache
cache = MongoDBAtlasSemanticCache(
connection_string=ATLAS_URI,
database_name="cache_db",
collection_name="llm_cache",
index_name="cache_vector_index",
embedding=embeddings,
score_threshold=0.95 # 95% 이상 유사도이면 캐시 응답 반환
)
set_llm_cache(cache)
# 첫 번째 호출: LLM 실행
response1 = llm.invoke("연차 휴가 신청 방법은?")
# 두 번째 호출: 의미 유사 → 캐시에서 응답 반환 (LLM 미호출)
response2 = llm.invoke("연차 신청 절차를 알고 싶어요")
score_threshold를 높게 설정할수록 캐시 적중률은 떨어지지만 응답 품질은 높아진다. 프로덕션에서는 질문 분포를 분석해 0.85-0.95 사이에서 조정한다.
6. AI 에이전트 메모리 — LangGraph + Atlas
6-1. 에이전트 메모리의 두 층위
단순 RAG를 넘어 다단계 작업을 자율적으로 수행하는 AI 에이전트를 만들려면 "대화의 흐름(단기 메모리)"과 "사용자에 대한 지식(장기 메모리)"을 분리해서 관리해야 한다.
LangGraph Checkpointer는 현재 진행 중인 대화의 상태 스냅샷을 MongoDB에 저장한다. 같은 thread_id로 이어지는 모든 대화가 일관된 문맥을 유지하며, 중간에 사람이 개입하거나 이전 체크포인트로 롤백하는 워크플로우도 지원한다.
LangGraph Store는 사용자 단위의 장기 기억을 관리한다. Vector Search와 결합하면 "과거에 사용자가 관심 가졌던 내용 중 현재 질문과 가장 유사한 것"을 의미 검색으로 찾아 에이전트 컨텍스트에 주입할 수 있다.
6-2. LangGraph + Atlas 에이전트 구현
# pip install langgraph-checkpoint-mongodb langgraph-store-mongodb
# 패키지명은 LangGraph 버전에 따라 달라질 수 있으므로 PyPI 최신 릴리즈 확인 필요
from langgraph.checkpoint.mongodb import MongoDBSaver
from langgraph.store.mongodb import MongoDBStore
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from typing import TypedDict, Annotated
from langchain_core.messages import AnyMessage
import operator
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], operator.add]
# 단기 메모리: Checkpointer 설정
checkpointer = MongoDBSaver(
client,
db_name="agent_db",
checkpoint_collection_name="checkpoints",
writes_collection_name="checkpoint_writes"
)
# 장기 메모리: Store 설정
store = MongoDBStore(
client,
db_name="agent_db",
collection_name="agent_memories",
vector_store=vector_store # 유사 기억 검색을 위한 Vector Search 연결
)
llm = ChatOpenAI(model="gpt-4o")
def assistant(state: AgentState, config: dict, *, store: MongoDBStore):
user_id = config["configurable"]["user_id"]
# 장기 메모리에서 현재 질문과 유사한 과거 기억 검색
memories = store.search(
("memories", user_id),
query=state["messages"][-1].content
)
memory_context = "\n".join([m.value["text"] for m in memories])
system_prompt = (
"당신은 개인화된 AI 어시스턴트입니다.\n"
f"사용자 장기 기억:\n{memory_context}"
)
response = llm.invoke([
{"role": "system", "content": system_prompt},
*state["messages"]
])
return {"messages": [response]}
def save_memory(state: AgentState, config: dict, *, store: MongoDBStore):
user_id = config["configurable"]["user_id"]
last_exchange = (
f"사용자: {state['messages'][-2].content}\n"
f"에이전트: {state['messages'][-1].content}"
)
store.put(
("memories", user_id),
key=f"memory_{len(state['messages'])}",
value={"text": last_exchange}
)
return state
graph_builder = StateGraph(AgentState)
graph_builder.add_node("assistant", assistant)
graph_builder.add_node("save_memory", save_memory)
graph_builder.set_entry_point("assistant")
graph_builder.add_edge("assistant", "save_memory")
graph_builder.add_edge("save_memory", END)
graph = graph_builder.compile(checkpointer=checkpointer, store=store)
# 동일 thread_id로 이어지는 대화 = 단기 메모리(Checkpointer) 활용
config = {"configurable": {"thread_id": "session_001", "user_id": "user_123"}}
result = graph.invoke(
{"messages": [{"role": "user", "content": "지난번에 추천한 상품 기억해?"}]},
config
)
2025년 발표된 LangChain-MongoDB 파트너십으로 통합이 강화되었으나, MongoDBSaver와 MongoDBStore의 정확한 패키지명과 생성자 시그니처는 LangGraph MongoDB 통합 패키지의 최신 버전을 기준으로 확인한다.
7. Atlas Stream Processing — 실시간 AI 워크플로우
7-1. 실시간 처리가 필요한 이유
배치 기반 파이프라인은 결과가 항상 오래된 데이터를 반영한다. AI 추천, 이상 감지, 실시간 사기 탐지처럼 수초 단위의 반응이 필요한 워크플로우에는 스트림 처리가 필수다. Atlas Stream Processing은 Kafka 또는 MongoDB Change Stream을 소스로 받아 MongoDB 쿼리 언어로 파이프라인을 정의하고, 결과를 Atlas 컬렉션이나 외부 시스템으로 내보낸다.
7-2. Stream Processor 아키텍처
7-3. 실시간 이상 거래 탐지 파이프라인
// mongosh로 Stream Processor 생성
const pipeline = [
// 소스: Kafka 결제 이벤트 스트림
{
$source: {
connectionName: "kafka-payments",
topic: "payment-events"
}
},
// 스키마 검증 — 실패 시 DLQ(Dead Letter Queue)로 우회
{
$validate: {
validator: {
$jsonSchema: {
required: ["userId", "amount", "merchantId", "timestamp"],
properties: {
amount: { bsonType: "double", minimum: 0 }
}
}
},
validationAction: "errorAndContinue"
}
},
// 1분 Tumbling Window로 사용자별 거래 집계
{
$tumblingWindow: {
interval: { size: 1, unit: "minute" },
pipeline: [
{ $group: {
_id: "$userId",
txCount: { $count: {} },
totalAmount: { $sum: "$amount" }
}}
]
}
},
// 이상 조건: 1분에 5건 초과 또는 100만원 초과
{
$match: {
$or: [
{ txCount: { $gt: 5 } },
{ totalAmount: { $gt: 1000000 } }
]
}
},
// 싱크: Atlas 이상 거래 컬렉션에 기록
{
$merge: {
into: {
connectionName: "atlas-cluster",
db: "fraud",
coll: "suspicious_activity"
}
}
}
];
sp.createStreamProcessor("fraud_detection", pipeline);
sp.fraud_detection.start();
7-4. Session Window — 사용자 행동 세션 분석
Session Window는 일정 시간 동안 이벤트가 없으면 세션이 종료된 것으로 간주하는 윈도우 방식이다. 이커머스 방문 세션, IoT 센서 활동 구간처럼 자연적인 끊김이 있는 데이터 분석에 적합하다. 소스 기준 2025년 5월에 추가된 기능이며, 지원 범위와 문법은 공식 Atlas Stream Processing 문서에서 확인한다.
// 15분 이상 이벤트가 없으면 세션 종료로 처리
{
$sessionWindow: {
partitionBy: "$userId",
gap: { size: 15, unit: "minute" },
pipeline: [
{ $group: {
_id: "$userId",
pagesViewed: { $push: "$pageUrl" },
itemsAdded: { $addToSet: "$productId" },
cartAdds: { $sum: { $cond: ["$addedToCart", 1, 0] } },
sessionStart: { $min: "$timestamp" },
sessionEnd: { $max: "$timestamp" }
}},
{ $addFields: {
sessionDurationMins: {
$divide: [{ $subtract: ["$sessionEnd", "$sessionStart"] }, 60000]
}
}}
]
}
},
{
$merge: {
into: {
connectionName: "atlas",
db: "analytics",
coll: "user_sessions"
}
}
}
7-5. $iceberg 스테이지 — OLAP 연동
소스 작성 시점에 $iceberg 싱크 스테이지는 Private Preview 상태다. MongoDB 운영 데이터를 Apache Iceberg 형식으로 S3에 스트리밍해 Snowflake, Databricks 등 OLAP 시스템과 실시간 연동하는 것이 목표다. GA 여부, 지원 클라우드 리전, 과금 방식은 공식 발표를 기준으로 확인한다.
// MongoDB 운영 데이터를 S3 Iceberg 테이블로 스트리밍 (Private Preview 기준 예시)
[
{ $source: { connectionName: "atlas", db: "ecommerce", coll: "orders" } },
{ $match: { status: "completed" } },
{ $project: { userId: 1, amount: 1, createdAt: 1, category: 1 } },
{
$iceberg: {
connectionName: "s3-data-lake",
table: "completed_orders"
// GA 버전에서 partitionBy 등 추가 옵션 지정 예정
}
}
]
// Snowflake/Databricks에서 completed_orders 테이블을 직접 쿼리 가능
8. GraphRAG — 관계 중심 지식 검색
8-1. 벡터 RAG가 부족한 경우
벡터 RAG는 "의미적으로 유사한 문서"를 잘 찾지만, "A가 B에 소속되고 B는 C를 담당한다"는 식의 관계 기반 질문에는 약하다. GraphRAG는 문서를 지식 그래프(Knowledge Graph)로 변환해 엔티티 간 관계를 추적하며 더 정밀한 답변을 생성한다.
8-2. GraphRAG 구현 패턴
GraphRAG 구현은 크게 세 단계다. 문서에서 엔티티와 관계를 추출해 그래프를 구성하고, 그래프를 탐색하며 필요한 컨텍스트를 수집하고, 수집된 컨텍스트로 LLM이 답변을 생성한다.
# GraphRAG는 LangChain-MongoDB 통합에서 실험적 패턴임
# 아래는 개념 구조를 설명하기 위한 예시이며, 실제 API는 사용 라이브러리 버전에 따라 다름
from langchain_experimental.graph_transformers import LLMGraphTransformer
from langchain_community.document_loaders import TextLoader
# 1. 문서 로드
loader = TextLoader("company_knowledge.txt")
docs = loader.load()
# 2. LLM으로 문서에서 엔티티·관계 추출 → 그래프 문서로 변환
graph_transformer = LLMGraphTransformer(llm=llm)
graph_documents = graph_transformer.convert_to_graph_documents(docs)
# 3. MongoDB 컬렉션 기반 그래프 스토어에 저장
# 구체적인 저장 방법은 사용하는 라이브러리 버전의 API 문서를 참고
# graph_store.add_graph_documents(graph_documents)
# 4. 관계 기반 질문 처리
# result = qa_chain.invoke("A팀 소속 개발자가 참여한 프로젝트 목록은?")
GraphRAG는 지식 그래프 구성 비용이 높고 유지보수 복잡도도 크다. 일반적인 문서 검색에는 Vector RAG로 충분하다. 법률·의료·조직 구조처럼 관계 추적이 핵심인 도메인에서만 GraphRAG를 검토한다.
9. MongoDB Atlas 시리즈 최종 도입 결정 가이드
5편에 걸쳐 MongoDB Atlas의 인프라, 보안, 성능, 그리고 AI 기능까지 다뤘다. 마지막으로 "언제 Atlas를 써야 하는가"에 대한 실질적인 판단 기준을 정리한다.
Atlas가 적합한 경우
[Atlas 도입 적합 시나리오]
- 유연한 스키마: 자주 바뀌는 데이터 모델, 중첩 문서, 배열 필드가 많은 경우
- JSON 중심 데이터: 애플리케이션이 JSON/BSON 구조로 데이터를 주고받는 경우
- AI/ML 워크플로우: 벡터 검색, RAG, 에이전트 메모리, 실시간 스트리밍이 필요한 경우
- 멀티 클라우드 운영: AWS·GCP·Azure에서 일관된 API로 DB를 관리하고 싶은 경우
- 통합 비용 절감: 벡터 DB, 검색 엔진, 스트리밍을 별도로 운영하는 비용이 큰 경우
- 운영 부담 최소화: 관리형 DBaaS로 패치, 백업, 모니터링을 위임하고 싶은 경우
신중해야 할 경우
[Atlas 도입 전 확인 필요 시나리오]
- 복잡한 JOIN이 필수: 수십 개 테이블을 조인하는 RDBMS 중심 워크플로우
- 엄격한 ACID 요구: 다중 컬렉션 트랜잭션을 대량 처리해야 하는 경우
(MongoDB 4.x+ 지원하나 RDBMS 대비 성능 트레이드오프 존재)
- SQL 의존적 팀: BI 도구, ETL 파이프라인이 SQL에 깊이 의존하는 경우
- 특수 스트리밍 요구: Flink, Spark Streaming 수준의 복잡한 스트림 처리가 필요한 경우
- 기존 스택이 깊이 정착: 마이그레이션 비용이 Atlas 도입 혜택을 상회하는 경우
시리즈 5편 핵심 요약
| 편 | 핵심 주제 | 실무 적용 포인트 |
|---|---|---|
| Part 1 | Atlas 개념·구조·왜 쓰는가 | 3계층 아키텍처, 멀티 클라우드, Replica Set 동작 원리 |
| Part 2 | 클러스터 설계 전략 | Flex vs Dedicated, 티어 선택, 비용 최적화, 샤딩 판단 |
| Part 3 | 보안, 네트워크, 접근 제어 | IP Allowlist, Private Endpoint, RBAC, CMK 암호화, 감사 로그 |
| Part 4 | 성능 최적화 | ESR 법칙 인덱싱, explain() 분석, Auto-scaling 임계값 |
| Part 5 | AI 시대의 Atlas | Vector Search + Hybrid Search + RAG + 에이전트 메모리 + 스트림 처리 |
도입 결정 프레임워크
MongoDB Atlas는 2026년 현재 단순한 "호스팅 MongoDB"에서 AI-ready 데이터 플랫폼으로 진화했다. 하지만 모든 팀에 최적화된 솔루션은 없다. 팀의 데이터 형태, AI 워크플로우의 복잡도, 기존 스택과의 연동 비용을 냉정하게 평가한 후 도입을 결정하는 것이 이 시리즈가 전달하고자 한 핵심 메시지다.