8장 에이전트 메모리와 지식, RAG 기반 검색·인덱싱 개념 정리
다시 보는 AI Agents in Action개요
에이전트나 챗봇이 똑똑하게 보이려면 두 가지가 특히 중요합니다. 바로 "메모리(memory)"와 "지식(knowledge)"입니다. 메모리는 사용자의 이전 발언, 선호, 과거 작업 기록처럼 대화와 상호작용 중에 생겨나는 정보이고, 지식은 매뉴얼·문서·위키·PDF 같은 비교적 고정된 참고 정보입니다. 이 둘을 잘 활용하면 같은 LLM(언어 모델)이라도 훨씬 자연스럽고 일관된 답변을 만들 수 있습니다.

RAG(Retrieval Augmented Generation, 검색 증강 생성)는 이런 메모리와 지식을 실제로 활용하게 만드는 핵심 패턴입니다. 문서를 미리 쪼개고(청크), 벡터로 변환(임베딩)해 벡터 데이터베이스에 저장해 두었다가, 질문이 들어오면 의미가 비슷한 조각을 찾아 프롬프트에 함께 넣어주는 구조입니다. 이 과정에서 시맨틱 검색(의미 기반 검색)과 벡터 유사도 검색이 중요한 역할을 합니다.
이 노트에서는 메모리와 지식의 개념, 프롬프트 증강 전략, RAG의 두 단계 구조, 대화 히스토리 메모리 패턴, 시맨틱 검색과 벡터 유사도 검색까지를 하나의 흐름으로 정리합니다. 코드 없이 개념 위주로 이해하는 데 초점을 맞추었습니다.
에이전트에서 메모리와 지식의 역할과 차이
메모리란 무엇인가?
에이전트의 메모리는 "대화·행동의 역사(history)"를 저장하고 다시 꺼내 쓰는 기능입니다. 사용자가 지난번에 무엇을 물어봤는지, 어떤 설정을 선호하는지, 이전 작업이 어디까지 진행됐는지 같은 정보가 여기에 포함됩니다. 이 정보는 대부분 비정형 텍스트 형태로 저장되고, 시간이 지나면서 계속 추가·갱신됩니다.
예를 들어 사용자가 "나는 다크 모드를 좋아해"라고 말했을 때, 에이전트가 이후에도 자동으로 다크 모드 설정을 추천해 준다면, 그건 메모리를 활용하는 사례입니다. 메모리는 "사용자별 맞춤성"과 "대화의 연속성"을 만들어주는 핵심 요소입니다.
지식이란 무엇인가?
지식은 상대적으로 "고정된 참고 정보"에 가깝습니다. 제품 매뉴얼, API 문서, 회사 내 위키, PDF 리포트, 연구 논문, FAQ, 정책 문서 등이 모두 여기에 포함됩니다. 이 정보는 사용자의 행동 때문에 매 분·매 시간 바뀌지는 않고, 필요할 때마다 검색해서 참고하는 "지식 베이스(knowledge base)" 역할을 합니다.
중요한 점은, 지식은 메모리와 달리 "사용자별"이라기보다 "시스템 전체가 공유하는 참고 자료"라는 점입니다. 한 사용자가 API 문서를 읽었다고 해서 그 문서의 내용이 바뀌지 않는 것처럼, 지식은 보통 다수의 사용자와 에이전트가 함께 쓰는 공용 자산입니다.
메모리와 지식의 차이 및 공통점
요약하면, 메모리는 "시간에 따라 축적되고 사용자/세션마다 다른 정보", 지식은 "비교적 고정적이고 시스템 차원에서 공유되는 정보"입니다. 그러나 둘 다 "프롬프트를 더 풍부하게 만들기 위한 컨텍스트"라는 공통 목적을 가집니다.
에이전트는 질문을 받을 때,
우선 최근 대화나 사용자 이력을 메모리에서 꺼내고
필요한 경우 관련 문서를 지식 베이스에서 검색해서 가져와
이 둘을 묶어 프롬프트에 첨부한 뒤
최종적으로 LLM에 넘겨 답변을 생성하는 식으로 동작할 수 있습니다.
즉, 메모리와 지식 모두 "프롬프트 증강을 위한 재료"라고 볼 수 있고, 그 재료를 찾는 공통 메커니즘이 바로 "retrieval(검색)"입니다.
프롬프트 증강과 외부 도구·참고 텍스트 활용 전략
프롬프트 증강(prompt augmentation)은 LLM에게 단순히 질문만 던지는 것이 아니라, LLM이 이해에 도움이 될 만한 다양한 컨텍스트를 함께 제공하는 전략입니다. 컨텍스트는 크게 세 가지 출처에서 옵니다.
메모리 기반 컨텍스트
직전·과거 대화 내용
사용자 선호, 프로필, 작업 이력
이전에 생성한 요약이나 중간 결과 등
지식 기반 컨텍스트 (참고 텍스트)
관련 문서의 일부분(청크)
정책/가이드라인 발췌
매뉴얼, 위키, FAQ에서 찾은 문단
외부 도구 호출 결과
데이터베이스 조회 결과
API 호출 응답(JSON 등)
검색 엔진, 사내 시스템에서 가져온 최신 데이터
프롬프트 설계 시에는 다음과 같은 방식으로 이들을 섞어 사용할 수 있습니다.
"메모리 + 지식" : 최근 대화 요약 + 관련 문서 조각을 같이 넣어, 개인화된 답변을 하되 근거는 문서에서 찾습니다.
"도구 + 지식" : 최신 재고 정보를 API로 가져오고, 반품 정책은 문서에서 가져와 함께 설명합니다.
"메모리만 활용" : 순수 상담/코칭형 에이전트에서 사용자의 과거 대화 맥락을 중심으로 답변합니다.
프롬프트 증강의 핵심은 "LLM이 직접 기억하지 못하는 정보"를 외부에서 찾아 프롬프트에 첨부하는 것이며, 이때 정보를 찾는 핵심 엔진이 바로 RAG입니다.
RAG(검색 증강 생성)의 기본 개념과 동작 흐름
RAG는 "검색(Retrieval) + 생성(Generation)"을 결합한 구조입니다. LLM이 가진 일반적인 언어 능력에, 외부 지식 베이스 검색 결과를 붙여 넣어 보다 정확하고 문서 기반의 답변을 만들도록 하는 패턴입니다.
기본 흐름은 다음과 같습니다.
사용자가 질문(쿼리)을 보낸다.
시스템이 이 질문을 벡터(의미를 담은 숫자 배열)로 바꾼다.
벡터 데이터베이스에서 이 벡터와 비슷한 의미를 가진 문서 조각(청크)을 찾는다.
찾아낸 청크들을 프롬프트의 "참고 자료"로 함께 넣는다.
LLM이 질문 + 참고 자료를 보고 최종 답변을 생성한다.
핵심은 "문서를 미리 벡터로 인덱싱해 두었다가, 나중에 질문 벡터와의 유사도 검색을 통해 관련 조각을 찾는다"는 점입니다. 따라서 RAG를 제대로 이해하려면, 문서 인덱싱 단계(오프라인/준비 단계)와 질의-응답 단계(온라인/질문 처리 단계)를 나누어 보는 것이 좋습니다.
RAG의 1단계: 문서 로딩·청크 분할·임베딩·벡터DB 저장
RAG의 첫 번째 단계는 "준비 단계(인덱싱 단계)"로, 문서를 검색 가능한 형태로 바꾸어 저장하는 과정입니다. 일반적으로 다음 순서를 따릅니다.
1. 문서 로딩 (Document Loading)
우선 다양한 형식의 문서를 불러옵니다.
PDF, Word, Markdown, HTML 등
데이터베이스 레코드, 노션/위키 페이지
로그, 이메일, 채팅 기록 등
이 단계의 목표는 "원본을 모두 텍스트 형태로 추출"하는 것입니다. 예를 들어 PDF에서 텍스트를 파싱하고, HTML에서 태그를 제거해 본문만 가져옵니다.
2. 청크 분할 (Chunking)
LLM은 한 번에 처리할 수 있는 토큰 수가 제한되어 있습니다. 따라서 긴 문서를 작은 텍스트 블록(청크)으로 나누어야 합니다. 청크 전략은 매우 중요합니다.
고정 길이 청크: 예) 500-1000자, 혹은 200-500 토큰 단위로 나누기
문단/제목 기준 청크: 자연스러운 의미 단위(섹션, 문단)마다 끊기
슬라이딩 윈도우: 청크 사이에 일부 겹치는 부분을 두어 문맥 단절을 줄이기
청크가 너무 크면 LLM에 보낼 수 없고, 너무 작으면 의미가 잘려 답변 품질이 떨어질 수 있습니다. 실제로는 길이와 의미 단위를 함께 고려한 설계가 필요합니다.
3. 임베딩 (Embedding)
각 청크를 "벡터"로 변환하는 과정입니다. 임베딩 모델은 텍스트를 고정 길이의 숫자 배열로 바꾸어 주는데, 이 벡터는 텍스트의 의미를 반영하도록 학습되어 있습니다.
비슷한 의미의 문장 → 비슷한 벡터(가까운 위치)
다른 의미의 문장 → 멀리 떨어진 벡터
이렇게 변환된 벡터는 이후 "유사도 검색"의 기반이 됩니다.
4. 벡터 데이터베이스 저장 (Vector DB)
임베딩한 벡터와 원본 텍스트(청크), 메타데이터(문서 제목, 섹션, 날짜 등)를 함께 벡터 데이터베이스에 저장합니다.
예:
벡터 → {원본 텍스트, 출처 문서 ID, 페이지 번호, 태그...}
벡터 DB는 이후 "어떤 쿼리 벡터와 가장 가까운 벡터들을 빠르게 찾아주는" 역할을 합니다. 이로써 준비 단계가 끝나고, 문서는 언제든 시맨틱 검색으로 조회할 수 있는 상태가 됩니다.
RAG의 2단계: 질의 임베딩·벡터 검색·프롬프트 증강·생성
두 번째 단계는 실제 사용자가 질문을 보냈을 때 이루어지는 "온라인 질의 처리 단계"입니다.
질의 임베딩(Query Embedding) 사용자의 질문을 임베딩 모델에 넣어 벡터로 변환합니다. 이 벡터는 질문의 의미를 표현합니다.
벡터 유사도 검색(Vector Similarity Search)
질의 벡터와 벡터 DB에 저장된 모든 문서 청크 벡터 사이의 "거리/유사도"를 계산합니다.
코사인 유사도(cosine similarity), 유클리드 거리 등 다양한 지표를 사용할 수 있으나, 코사인 유사도가 자주 쓰입니다.
유사도가 높은 상위 k개(예: 3~10개) 청크를 검색 결과로 가져옵니다.
프롬프트 증강(Prompt Augmentation)
검색된 청크들을 하나의 "참고 자료 섹션"으로 묶습니다.
시스템 프롬프트/지시와 함께 사용자 질문, 참고 자료를 하나의 프롬프트로 구성합니다. 예:
"아래 참고 자료를 근거로 질문에 답하세요. 추론 근거를 참고 자료에서 찾으세요."
뒤에 문서 청크들을 나열
LLM 생성(Generation)
LLM은 증강된 프롬프트를 기반으로 답변을 생성합니다.
모델은 기본 언어 능력 + 제공된 문서 내용만을 근거로 답변하려고 시도하므로, "환각(근거 없는 지어내기)"을 줄이고 문서 기반 답변을 만들 수 있습니다.
요약하면, 1단계에서 문서를 인덱싱해 "언제든 불러올 수 있게" 만들어 두고, 2단계에서 질문에 맞는 조각을 찾아 프롬프트에 넣어 "문서 기반 답변"을 생성하는 것이 RAG의 전체 흐름입니다.
대화 히스토리를 활용한 메모리 저장과 벡터 검색 패턴
메모리 역시 RAG와 동일한 패턴을 사용할 수 있습니다. 차이는 "무엇을 인덱싱하느냐"뿐입니다. 문서 대신 "대화 기록"을 인덱싱하면, 그것이 곧 에이전트의 장기 메모리가 됩니다.
1. 메모리 저장 패턴
대화가 진행될 때마다, 또는 일정 간격으로 "대화 요약"이나 "중요 발언"을 뽑습니다.
예: "사용자는 다크 모드를 선호한다.", "사용자는 지난번에 A 기능 설정 방법을 질문했다."
이 텍스트들을 청크 단위로 정리하고, 임베딩하여 벡터 DB에 저장합니다.
메타데이터로 사용자 ID, 날짜, 대화 세션 ID 등을 함께 저장해 두면 필터링에 유용합니다.
이렇게 하면, 문서 대신 "사용자의 과거 발언"이 벡터 DB에 축적되며, 에이전트가 나중에 이를 검색해서 사용할 수 있습니다.
2. 메모리 검색 패턴
사용자가 새로 질문을 할 때, 시스템은 두 가지 검색을 동시에 할 수 있습니다.
메모리 검색
질문을 임베딩한 뒤, "해당 사용자"의 메모리 벡터들 중에서 의미상 가까운 항목들을 찾습니다.
예: "어두운 화면으로 보여줘" → 이전에 "다크 모드를 좋아한다"는 메모리가 시맨틱하게 연관되어 검색될 수 있음.
지식 검색(RAG)
동일한 질문 벡터로, 문서(지식 베이스) 벡터 DB를 검색하여 관련 문서 청크를 찾습니다.
찾아낸 메모리와 지식 정보를 함께 프롬프트에 넣으면, "사용자 맞춤 + 문서 기반"이라는 두 가지 장점을 동시에 얻을 수 있습니다.
시맨틱 검색(의미 기반 검색)의 개념과 문서 인덱싱 방식
전통적인 검색 시스템(예: 단순 키워드 검색)은 주로 "문자열 일치"에 초점을 맞춥니다. 사용자가 입력한 단어가 문서에 얼마나 자주, 어디에 등장하는지를 기준으로 점수를 매깁니다. TF-IDF 같은 방식이 대표적입니다.
시맨틱 검색(semantic search)은 여기서 한 단계 더 나아가 "단어가 달라도 의미가 비슷하면 관련 문서로 간주하는 검색"입니다.
키워드 검색 예: "푸른 하늘"을 검색하면 실제로 "푸른", "하늘"이라는 단어가 포함된 문서에만 높은 점수를 줌.
시맨틱 검색 예: "푸른 하늘"을 검색하면 "맑고 파란 하늘", "오늘은 하늘이 매우 파랗다" 같은 표현이 들어간 문서도 잘 찾아냄.
이 차이를 만들기 위해 시맨틱 검색에서는 "문서 인덱싱 방식"이 달라집니다.
전통 인덱스(역색인, inverted index)
단어 → 이 단어가 등장한 문서 리스트
검색 시 단어 일치 기반으로 후보 문서를 모으고, TF-IDF 등으로 점수화
벡터 인덱스(시맨틱 인덱스)
문서(또는 문서 조각)를 임베딩 → 벡터로 저장
검색 시 "질문을 임베딩한 벡터와 가장 가까운 벡터"를 찾음
단어가 정확히 같지 않아도, 의미가 비슷하면 벡터가 가깝게 위치
실전에서는 두 방식을 혼합하기도 합니다. 예를 들어, 키워드 필터로 대략적인 후보를 줄이고, 그 안에서 벡터 유사도로 정렬하는 방식 등이 있습니다.
벡터 유사도 검색을 활용한 의미 기반 검색의 토대
벡터 유사도 검색(vector similarity search)은 시맨틱 검색의 수학적 기반입니다. 임베딩이 텍스트를 숫자 벡터로 변환한다면, 유사도 검색은 이 벡터들 사이의 "가까움"을 정의하고 계산하는 단계입니다.
1. 벡터와 임베딩
텍스트 임베딩을 통해 우리는 "문장 하나 = n차원 벡터(예: 768, 1024차원)"라는 표현을 얻습니다. 이 벡터 공간에서, 의미가 비슷한 문장은 서로 가까운 방향·위치에 놓이도록 임베딩 모델이 학습되어 있습니다.
"강아지가 뛰어논다"와 "개가 달린다" → 가까운 벡터
"강아지가 뛰어논다"와 "오늘 주식 시장이 폭락했다" → 멀리 떨어진 벡터
2. TF-IDF와 코사인 유사도
고전적인 텍스트 표현 방식인 TF-IDF 역시 각 문서를 "단어 빈도 기반 벡터"로 표현합니다. 여기서도 문서 벡터 간 유사도를 측정할 때 자주 쓰이는 방법이 코사인 유사도(cosine similarity)입니다.
코사인 유사도는 "두 벡터 사이 각도의 코사인 값"을 유사도의 척도로 사용합니다.
값 범위는 일반적으로 -1 ~ 1이며,
1에 가까울수록 두 벡터(문서)가 매우 비슷
0이면 서로 직교(관련 없음)
-1이면 방향이 반대
임베딩 기반에서도 코사인 유사도가 널리 사용됩니다. 벡터 길이(규모)보다 "방향(의미)"에 초점을 맞출 수 있기 때문입니다.
3. 벡터 유사도 검색 과정
벡터 유사도 검색은 다음처럼 정리할 수 있습니다.
모든 문서(또는 청크)를 벡터로 변환해 DB에 저장한다.
사용자 쿼리를 벡터로 변환한다.
쿼리 벡터와 DB에 있는 모든 벡터 간 거리/유사도를 계산한다.
가장 가까운 상위 k개 벡터에 해당하는 문서 조각을 검색 결과로 반환한다.
벡터가 많아질수록 모든 벡터와 직접 비교하는 것은 비용이 크기 때문에, 실전에서는 HNSW, IVF 같은 근사 최근접 탐색(ANN) 기법을 사용하는 벡터 데이터베이스를 활용해 검색 속도를 높입니다.
정리
메모리는 대화·작업 히스토리, 사용자 선호처럼 "시간에 따라 쌓이고 사용자마다 다른 정보"이며, 지식은 매뉴얼·위키·문서처럼 "비교적 고정된 참고 정보"입니다.
두 요소 모두 궁극적으로는 프롬프트를 풍부하게 만드는 컨텍스트로 사용되며, 이 컨텍스트를 찾는 공통 메커니즘이 retrieval(검색)입니다.
RAG는 문서를 로딩 → 청크 분할 → 임베딩 → 벡터 DB 저장으로 준비한 뒤, 질의 시 질의 임베딩 → 벡터 유사도 검색 → 프롬프트 증강 → LLM 생성의 흐름으로 동작합니다.
메모리도 같은 패턴을 사용해 "문서 대신 대화 기록"을 벡터로 저장·검색함으로써, 에이전트에 장기 기억을 부여할 수 있습니다.
시맨틱 검색은 "단어 일치"가 아니라 "의미 유사성"에 기반한 검색이며, 이를 위해 문서와 쿼리를 벡터로 표현하고, 벡터 유사도(코사인 유사도 등)를 사용합니다.
이 모든 것의 토대가 바로 벡터 유사도 검색이며, 이를 중심으로 메모리와 지식을 통합한 에이전트 시스템이 구축됩니다.

