AI Agent 구축 가이드: RAG, 벡터 검색, LangGraph 활용
AI Agent 구축 가이드: RAG, 벡터 검색, LangGraph 활용
소개
ChatGPT나 Claude 같은 LLM을 사용해보신 적이 있나요? “오늘 날씨가 어때?”라고 물으면 “저는 실시간 정보에 접근할 수 없습니다”라는 답변을 받은 경험이 있을 것입니다. 또는 회사의 내부 문서를 기반으로 질문하고 싶은데, LLM은 학습 시점의 정보만 알고 있어서 답변하지 못하는 경우도 있습니다.
AI Agent는 바로 이런 문제를 해결합니다.
AI Agent는 단순히 LLM을 호출하는 것을 넘어서, 자율적으로 도구를 사용하고, 실시간 정보를 검색하며, 복잡한 작업을 수행할 수 있는 지능형 시스템입니다. 마치 사람처럼 필요한 도구를 스스로 선택하고 사용하는 것이 가능합니다.
이 글을 읽으면:
- ✅ AI Agent의 핵심 개념과 구성 요소를 명확히 이해할 수 있습니다
- ✅ RAG, 벡터 검색, LangGraph 등 핵심 기술을 실무 관점에서 학습할 수 있습니다
- ✅ 실제 프로젝트에서 AI Agent를 구축할 수 있는 기반 지식을 얻을 수 있습니다
- ✅ MongoDB Atlas Vector Search를 활용한 실전 아키텍처를 이해할 수 있습니다
이 글에서 다루는 내용
이 글은 다음과 같이 구성되어 있습니다:
- AI Agent의 본질: 단순한 LLM 호출과 AI Agent의 차이점
- AI Agent의 구성 요소: LLM, Agent, Tools, Memory 등 핵심 컴포넌트
- 핵심 개념 이해하기: RAG, Embedding, Vector Search, LangGraph, Tools, Memory
- AI Agent의 일반적인 아키텍처 패턴: 실제 구축 시 참고할 아키텍처 패턴 각 섹션은 독립적으로 읽을 수 있지만, 순서대로 읽으면 더 깊이 이해할 수 있습니다.
AI Agent의 본질
단순한 LLM 호출 vs AI Agent
단순한 LLM 호출
사용자 질문 → LLM → 답변
이는 LLM이 학습한 시점의 정보만 알고 있고, 외부 시스템과의 상호작용이 불가능하며 대화 기록을 기억하지 못한다는 한계가 있습니다. 당연히 학습한 시점의 정보만 알고 있으므로 최신 정보나 특정 데이터베이스 정보에 접근이 불가능합니다.
AI Agent
사용자 질문 → Agent → [도구 사용] → LLM → 답변 ↓ [대화 기록 저장]
이에 비해, AI Agent는 외부 API, 데이터베이스, 함수 등을 호출하는 등 도구 사용이 가능하고 메모리를 통해 대화 기록을 저장하고 맥락을 유지할 수 있으며 마치 사람처럼 필요한 도구를 스스로 선택하고 사용하는 것이 가능합니다. 또한 새로운 도구를 쉽게 추가 가능하다는 특징 있습니다.
이런 차이점을 보면 AI Agent의 필요성은 명확합니다. 단순한 LLM 호출로는 해결할 수 없는 문제들을 AI Agent가 해결할 수 있기 때문입니다.
💡 실제 사용 사례: 고객 지원 챗봇이 회사의 최신 제품 정보를 검색하거나, 개발자 도우미가 코드베이스를 검색해 정확한 답변을 제공하는 것이 AI Agent의 대표적인 활용 예시입니다.
이제 AI Agent가 어떻게 구성되어 있는지 살펴보겠습니다.
AI Agent의 구성 요소
AI Agent는 다음과 같은 핵심 컴포넌트로 구성됩니다. 각 컴포넌트의 역할을 이해하면 전체 시스템이 어떻게 동작하는지 명확해집니다.
다이어그램 로딩 중...
핵심 개념 이해하기
이 섹션에서는 AI Agent를 구축하기 위해 필요한 6가지 핵심 개념을 학습합니다. 각 개념은 독립적으로 이해할 수 있도록 구성되어 있으며, 순서대로 읽으면 전체적인 이해가 가능합니다.
📚 학습 팁: 각 개념 뒤에 있는 다이어그램과 코드 예시를 함께 보면 더 쉽게 이해할 수 있습니다.
1. RAG (Retrieval-Augmented Generation)
개념
RAG는 AI Agent의 핵심 패턴 중 하나입니다. LLM의 한계를 보완하는 방법입니다.
문제 상황
LLM은 학습 시점의 정보만 알고있습니다. 이로 인해 최신 정보의 부족, 특정 도메인 지식 부족, 개인화된 데이터 접근 불가라는 한계가 있습니다.
해결책
RAG는 위의 한계들을 아래와 같은 방법으로 해결할 수 있습니다.
다이어그램 로딩 중...
작동 원리
RAG는 벡터 검색을 사용하여 관련 문서를 찾습니다. 벡터 검색을 사용하는 이유는 다음과 같습니다:
전통적인 키워드 검색의 한계:
-
“MongoDB 인덱스 생성 방법” → “MongoDB”, “인덱스”, “생성” 키워드만 매칭
-
의미가 비슷하지만 단어가 다른 경우 놓치게 되는 문제가 있습니다. 벡터 검색의 장점:
-
“MongoDB 인덱스 생성 방법” → 의미적으로 유사한 모든 문서 찾기
-
“인덱스를 만드는 방법”, “색인 생성” 등도 찾을 수 있음
2. Embedding (임베딩)
개념
Embedding은 텍스트를 숫자 벡터로 변환하는 과정입니다.
작동 원리
다이어그램 로딩 중...
특징
- 의미적으로 유사한 텍스트는 벡터 공간에서 가까운 위치
- 수학적 연산 가능 (유사도 계산)
- 고차원 공간에 의미를 매핑
3. Vector Search (벡터 검색)
개념
벡터 검색은 고차원 벡터 공간에서 유사한 벡터를 찾는 과정입니다.
작동 원리
다이어그램 로딩 중...
실제 적용: MongoDB Atlas Vector Search
MongoDB Atlas는 벡터 검색을 네이티브로 지원합니다. 별도의 벡터 데이터베이스(Pinecone, Weaviate 등)를 구축할 필요 없이 기존 MongoDB 인프라를 활용할 수 있어 실무에서 매우 유용합니다.
장점:
- ✅ 별도의 벡터 데이터베이스 불필요: 기존 MongoDB 인프라만으로 충분
- ✅ 강력한 쿼리 기능과 결합: 일반 쿼리와 벡터 검색을 함께 사용 가능
- ✅ 비용 효율적: 추가 인프라 구축 및 관리 비용 절감
- ✅ 데이터 일관성: 하나의 데이터베이스에서 모든 데이터 관리 작동 방식:
MongoDB Atlas의 $vectorSearch 연산자를 사용하면 다음과 같이 벡터 검색을 수행할 수 있습니다:
{ $vectorSearch: { index: "vector_index", // 벡터 인덱스 이름 path: "embedding", // 벡터가 저장된 필드 queryVector: [0.1, 0.2, ...], // 검색할 벡터 (질문을 임베딩한 결과) numCandidates: 150, // 후보 개수 (정확도와 성능의 균형) limit: 5 // 반환할 결과 수 } }
💡 실무 팁: numCandidates는 검색 정확도와 성능의 트레이드오프입니다. 값이 클수록 정확하지만 느리고, 작을수록 빠르지만 덜 정확합니다. 보통 100-200 사이를 권장합니다.
4. LangGraph - Agent의 뇌
개념
LangGraph는 복잡한 AI Agent를 구축하기 위한 프레임워크입니다. LangChain의 단순한 체인 방식의 한계를 극복하고, 상태 관리와 복잡한 워크플로우를 효율적으로 처리할 수 있게 해줍니다.
LangGraph를 선택하는 이유
단순한 체인 방식의 한계:
다이어그램 로딩 중...
단순한 체인 방식은 다음과 같은 한계가 있습니다:
- ❌ 조건부 분기가 어려움: 도구가 필요한지 여부에 따라 다른 흐름을 만들기 어려움
- ❌ 상태 관리 복잡: 대화 기록이나 중간 결과를 관리하기 복잡
- ❌ 반복 실행 제한: 도구 사용 후 다시 LLM을 호출하는 순환이 어려움
- ❌ 에러 처리 부족: 중간 단계에서 실패했을 때 복구하기 어려움 LangGraph의 해결책:
LangGraph는 상태 그래프(State Graph) 패턴을 사용하여 위의 문제들을 해결합니다:
다이어그램 로딩 중...
LangGraph의 장점:
- ✅ 유연한 조건부 분기: 조건에 따라 다른 노드로 이동 가능
- ✅ 명확한 상태 관리: 모든 노드가 공유하는 상태 객체로 일관성 유지
- ✅ 순환 실행 지원: 도구 사용 후 다시 Agent 노드로 돌아가기 쉬움
- ✅ 시각화 가능: 그래프 구조로 전체 워크플로우를 한눈에 파악
핵심 개념
1. State (상태)
상태는 모든 노드가 공유하는 데이터입니다. 각 노드는 상태를 읽고 수정할 수 있습니다.
interface GraphState { messages: BaseMessage[]; // 대화 기록 // 필요에 따라 다른 필드 추가 가능 // currentStep?: string; // toolResults?: any[]; }
💡 실무 팁: 상태는 불변성(immutability)을 유지하는 것이 좋습니다. 새로운 상태를 반환하는 방식으로 업데이트하면 디버깅과 체크포인트 저장이 쉬워집니다.
2. Node (노드)
노드는 하나의 작업 단위입니다. 각 노드는 상태를 받아서 새로운 상태를 반환합니다.
async function agentNode(state: GraphState) { // LLM 호출 (이전 대화 기록 포함) const result = await llm.invoke(state.messages); // 기존 메시지에 새 메시지 추가 (불변성 유지) return { messages: [...state.messages, result], }; }
💡 실무 팁: 노드 함수는 순수 함수(pure function)처럼 작성하는 것이 좋습니다. 같은 입력에 대해 항상 같은 출력을 반환하면 테스트와 디버깅이 쉬워집니다.
3. Edge (엣지)
엣지는 노드 간의 흐름을 정의합니다. 단순히 한 노드에서 다른 노드로 이동하는 경로를 지정합니다.
graph.addEdge(START, "agent"); // 시작 → Agent 노드 graph.addEdge("tools", "agent"); // Tools 노드 → Agent 노드 (순환)
💡 실무 팁: Tools 노드에서 Agent 노드로 돌아가는 엣지를 추가하면, 도구 실행 후 LLM이 결과를 분석하고 다음 단계를 결정할 수 있습니다.
4. Conditional Edge (조건부 엣지)
조건에 따라 다른 노드로 이동할 수 있습니다. 이는 AI Agent의 핵심 기능 중 하나입니다.
// 도구가 필요한지 여부에 따라 분기 graph.addConditionalEdges("agent", routeTools, { tools: "tools", // 도구가 필요하면 Tools 노드로 [END]: END, // 도구가 필요 없으면 종료 }); // routeTools 함수는 상태를 분석하여 다음 노드를 결정 function routeTools(state: GraphState) { const lastMessage = state.messages[state.messages.length - 1]; return lastMessage.tool_calls?.length > 0 ? "tools" : END; }
💡 실무 팁: 조건부 엣지의 라우팅 함수는 간단하고 명확하게 작성하는 것이 좋습니다. 복잡한 로직은 별도 함수로 분리하면 테스트하기 쉽습니다.
실행 흐름
다이어그램 로딩 중...
5. Tools (도구) - Agent의 손과 발
개념
Tools는 Agent가 외부 세계와 상호작용하는 방법입니다.
역할
다이어그램 로딩 중...
설계 원칙
도구를 잘 설계하면 Agent가 더 정확하고 유용한 작업을 수행할 수 있습니다. 다음 3가지 원칙을 지키면 효과적인 도구를 만들 수 있습니다.
1. 명확한 설명
LLM이 언제 이 도구를 사용해야 하는지 이해할 수 있어야 합니다. 모호한 설명은 잘못된 도구 선택으로 이어질 수 있습니다.
description: "Retrieve relevant documents for a user query using vector search. " + "Use this tool when the user asks about information that might be in " + "the knowledge base or documentation.";
❌ 나쁜 예: “문서를 검색합니다”
✅ 좋은 예: “벡터 검색을 사용하여 사용자 질문과 관련된 문서를 찾습니다. 회사의 문서나 지식 베이스에 대한 질문에 사용하세요.”
2. 구조화된 입력
Zod 스키마로 입력을 명확히 정의하면 LLM이 올바른 형식으로 도구를 호출할 수 있습니다.
schema: z.object({ user_query: z .string() .describe( "The user's query to search for. Should be a clear question or topic." ), max_results: z .number() .optional() .describe("Maximum number of results to return. Default is 5."), });
💡 실무 팁: 선택적 필드에는 기본값을 제공하고, 필수 필드는 명확히 구분하는 것이 좋습니다.
3. 일관된 출력
항상 문자열을 반환하여 LLM이 쉽게 처리할 수 있게 합니다. JSON이나 객체를 반환하면 LLM이 파싱하는 과정에서 오류가 발생할 수 있습니다.
func: async ({ user_query, max_results = 5 }) => { const results = await searchDocuments(user_query, { limit: max_results }); // 구조화된 정보를 문자열로 변환 return results .map((doc, idx) => `${idx + 1}. ${doc.title}\n${doc.content}`) .join("\n\n"); };
💡 실무 팁: 출력 형식을 일관되게 유지하면 LLM이 결과를 더 잘 이해할 수 있습니다. 예를 들어, 항상 번호를 매기거나 마크다운 형식을 사용하는 것이 좋습니다.
6. Memory (메모리) - 대화 기록 관리
개념
Memory는 Agent가 이전 대화를 기억하게 해주는 시스템입니다.
Memory가 필요한 이유
Memory 없이:
다이어그램 로딩 중...
Memory 있으면:
다이어그램 로딩 중...
Checkpointer 패턴
LangGraph의 Checkpointer는 각 노드 실행 후 상태를 저장합니다.
다이어그램 로딩 중...
Thread ID의 역할:
Thread ID는 각 대화 세션을 구분하는 고유 식별자입니다:
- ✅ 같은 Thread ID = 같은 대화 기록 (이전 대화를 기억함)
- ✅ 다른 Thread ID = 독립적인 대화 (새로운 대화 시작)
💡 실무 팁: Thread ID는 보통 사용자 ID와 세션 ID를 조합하여 생성합니다. 예를 들어 user_123_session_456 형식을 사용하면 사용자별, 세션별로 대화를 관리할 수 있습니다.
AI Agent의 일반적인 아키텍처 패턴
AI Agent 시스템은 일반적으로 다음과 같은 레이어로 구성됩니다:
추상적 아키텍처
다이어그램 로딩 중...
일반적인 실행 흐름
- 사용자 입력: 질문이나 요청
- Agent 분석: LLM이 입력을 분석하고 필요한 도구 결정
- 도구 실행: 선택된 도구가 외부 시스템과 상호작용
- 결과 통합: 도구 결과를 받아서 LLM이 최종 답변 생성
- 상태 저장: 대화 기록을 메모리에 저장
마무리
이 글에서는 AI Agent의 핵심 개념과 아키텍처를 살펴보았습니다.
핵심 요약
지금까지 다룬 내용을 요약하면:
- AI Agent는 LLM의 한계를 극복하는 시스템입니다
- 실시간 정보 접근, 외부 시스템 연동, 대화 기록 관리가 가능합니다
- 6가지 핵심 개념이 AI Agent의 기반입니다
- RAG, Embedding, Vector Search, LangGraph, Tools, Memory
- MongoDB Atlas Vector Search를 활용하면 별도의 벡터 DB 없이도 구현 가능합니다
- LangGraph는 복잡한 Agent 워크플로우를 효율적으로 관리합니다
다음 단계
이제 이론을 바탕으로 실제 프로젝트를 시작할 준비가 되었습니다. 다음 글에서는:
- 🚀 실제 프로젝트에서 AI Agent 구축하기
- 🔧 LangGraph를 사용한 Agent 구현
- 💾 MongoDB를 활용한 벡터 검색 및 메모리 구현
- 🎯 실전 예제와 베스트 프랙티스 를 다루겠습니다.
💬 질문이나 피드백이 있으시면 댓글로 남겨주세요!
🔖 이 글이 도움이 되었다면 공유해주시면 감사하겠습니다.