대화를 기억하는 챗봇 만들기 — LangChain Memory 이해하기
· LLM은 기본적으로 이전 대화를 기억하지 못합니다 — 매 요청이 백지 상태예요.
· LangChain의 Memory는 지난 대화를 저장해 다음 프롬프트에 넣어주는 장치입니다.
· 전체 저장·요약 저장·최근 N개 저장 등 상황에 맞는 방식을 고르는 게 핵심이에요.
챗봇을 처음 만들면 누구나 한 번쯤 당황합니다. 방금 "내 이름은 승일이야"라고 알려줬는데, 바로 다음 질문에서 "제 이름이 뭐라고요?" 하면 모델이 깨끗하게 잊어버리는 거죠. 버그가 아니라 원래 그렇습니다. 오늘은 이 문제를 해결하는 LangChain Memory를 정리합니다.
🧠 LLM은 왜 대화를 못 기억할까
LLM은 매 요청을 완전히 독립적으로 처리합니다. 우리가 보기엔 대화가 이어지는 것 같지만, 모델 입장에선 매번 처음 보는 질문이에요. 이전에 무슨 말을 주고받았는지에 대한 기억 장치가 애초에 없습니다.
그래서 "기억"은 모델이 하는 게 아니라, 우리가 지난 대화를 다시 프롬프트에 넣어줘야 생기는 겁니다.
💡 Memory의 기본 아이디어
LangChain의 Memory가 하는 일은 의외로 단순합니다. 지난 대화를 저장해 두었다가, 다음 요청 때 프롬프트에 자동으로 붙여주는 것. 즉 "대화 기록을 관리하는 서랍" 역할이에요. 새 질문이 오면 서랍에서 이전 대화를 꺼내 함께 모델에 전달합니다.
문제는 대화가 길어질수록 이 기록도 계속 쌓인다는 점입니다. 토큰에는 한계가 있으니, 무엇을 얼마나 기억할지 전략이 필요해집니다.
🗂️ 대표적인 Memory 3가지
정답은 없고 상황에 맞게 고릅니다. 짧은 Q&A면 ①, 긴 상담 챗봇이면 ②+③을 섞는 식이죠.
💻 코드로 감 잡기
버전·라이브러리마다 이름은 달라지지만, 개념 뼈대는 이렇습니다.
# 대화 기록 서랍을 하나 만든다 (최근 N턴 유지 방식)
memory = ConversationWindowMemory(k=5)
def chat(user_input):
history = memory.load() # 지난 대화 꺼내기
prompt = f"{history}\n사용자: {user_input}"
reply = llm.generate(prompt)
memory.save(user_input, reply) # 이번 대화 저장
return reply
포인트는 load(꺼내서 프롬프트에 붙이고) → save(이번 대화도 저장)의 반복입니다. Memory는 이 과정을 자동으로 해주는 도구예요.
🔧 실무 팁
- 토큰 관리가 우선 — 전체 저장은 편하지만 비용·한계에 금방 부딪힘. 기본은 Window나 Summary.
- 사용자별로 분리 — 여러 명이 쓰는 서비스면 대화 기록을 사용자(세션) 단위로 나눠 저장.
- 영구 저장이 필요하면 — 서버 재시작에도 남기려면 DB·Redis 같은 외부 저장소에 연결.
- 요약 남용 주의 — 요약 Memory는 편하지만 중요한 숫자·고유명사가 뭉개질 수 있으니 확인 필요.
❓ 자주 묻는 질문 (FAQ)
Q. Memory를 쓰면 모델이 진짜로 학습하나요?
A. 아니요. 모델 자체는 그대로예요. 지난 대화를 프롬프트에 다시 넣어주는 것뿐이라, 대화창을 닫으면(또는 서랍을 비우면) 잊습니다.
Q. 대화가 아주 길어지면요?
A. 전체 저장은 토큰 한계에 걸립니다. 최근 N턴만 유지하거나, 오래된 부분을 요약해 압축하는 방식으로 넘깁니다.
Q. RAG와는 뭐가 다른가요?
A. Memory는 '이 대화의 흐름'을 기억하는 것이고, RAG는 '외부 문서 지식'을 찾아오는 것이에요. 목적이 다르며, 둘을 함께 쓰기도 합니다.
마무리
정리하면, LLM은 원래 대화를 기억하지 못하고 Memory가 그 기억을 대신 관리해 줍니다. 핵심은 "무엇을, 얼마나 기억할지"를 상황에 맞게 고르는 것 — 짧으면 통째로, 길면 최근 것만 혹은 요약으로. 다음 편에서는 이 대화 기록에 외부 지식까지 붙이는 Retriever 이야기로 이어가 보겠습니다.
댓글
댓글 쓰기