본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 23. 14:21

에이전트 메모리: 7가지 유형, 그리고 그중 2가지는 메모리가 아니다

요약

LLM 에이전트의 메모리 구조를 7가지 유형으로 분류하고, 단순 대화 히스토리와 RAG를 넘어선 진정한 메모리의 개념을 설명합니다. CoALA 논문과 인지 과학 이론을 바탕으로 단기 및 장기 메모리의 차이를 분석합니다.

핵심 포인트

  • LLM은 상태를 유지하지 않는 순수 함수이며, 메모리는 모델 외부 레이어에서 구현됨
  • 대화 히스토리와 RAG는 7가지 메모리 유형 중 2가지에 불과함
  • 메모리의 핵심 기준은 컨텍스트 윈도우 내 존재 여부와 지속 시간임
  • 진정한 에이전트 지능은 과거의 실수를 규칙으로 전환하는 능력이 필요함

당신의 에이전트는 메모리 문제가 있는 것이 아닙니다. 에이전트는 7가지의 메모리를 가지고 있으며, 대부분의 팀은 그중 2가지만 구축했습니다.

모두가 그냥 지나치는 지점부터 시작해 봅시다: 모델 자체는 아무것도 기억하지 못합니다. LLM (Large Language Model)은 순수 함수 (pure function)입니다. 동일한 입력에는 동일한 출력이 나오며, 호출 사이에 상태 (state)가 유지되지 않습니다. ChatGPT와 대화할 때 메모리처럼 느껴지는 것은 모델을 감싸고 있는 레이어 (layer)이며, 매 요청마다 관련 히스토리 (history)를 다시 전송하는 것입니다. 모델은 당신의 마지막 메시지를 기억하고 있는 것이 아닙니다. 다른 무언가가 매 턴마다 모델에게 정보를 다시 전달하고 있으며, 그때마다 토큰 (tokens) 비용을 지불하고 있는 것입니다.

그 레이어가 바로 거의 모든 엔지니어링이 이루어지는 곳이며, 그 중 거의 대부분은 두 가지 패턴으로 수렴합니다: 잘라낼 때까지 계속 커지는 대화 히스토리 (conversation history), 그리고 RAG (Retrieval-Augmented Generation)라고 부르는 벡터 데이터베이스 (vector database)입니다. 이것들은 에이전트가 기억할 수 있는 7가지의 별개 요소 중 2가지입니다. 문제는 이 두 가지가 시간이 지나도 에이전트를 더 똑똑하게 만들지 못한다는 점입니다. 어제의 실수를 내일의 규칙으로 바꾸는, 즉 에이전트를 똑똑하게 만드는 유형은 전체 스택에서 가장 적게 구축되는 구성 요소입니다.

이것은 3부작 중 제1부입니다. 여기에서 저는 7가지 유형을 나열하고, 어떤 것들이 실제로 '메모리'라는 이름을 얻을 자격이 있는지 논할 것입니다. 이 분류 체계 (taxonomy)는 저의 것이 아닙니다: 이는 CoALA 논문 (Sumers et al., Princeton 2023)을 거쳐 인지 과학 (cognitive science)과 Tulving의 1972년 에피소드 기억 (episodic memory) 및 의미 기억 (semantic memory) 분리에서 유래되었습니다. 이어지는 내용은 무엇을 구축하고 무엇을 무시할지에 대한 의견을 담은 엔지니어 버전입니다.

유일하게 중요한 축: 얼마나 오래 지속되는가

잠시 7가지 라벨은 잊으십시오. 하나의 조직적인 질문이 있는데, 그것은 시간적인 것입니다. 이 메모리가 단일 턴을 위한 컨텍스트 윈도우 (context window) 내에 존재하는가, 아니면 세션(sessions)을 넘어 모델 외부에서 지속되는가?

단기 메모리(Short-term)는 컨텍스트 윈도우(context window)입니다. 빠르고 바로 그곳에 존재하지만, 세션(session)이 종료되면 증발합니다. 장기 메모리(Long-term)는 외부 저장소(external store)에 기록하고 나중에 다시 읽어오는 모든 것을 의미합니다. 7가지 유형 중 2가지는 그 중간에 걸쳐 있습니다. 저장소는 오래 지속되지만, 모델에 전달되는 내용은 정확히 한 번의 턴(turn)에만 사용되고 버려집니다. 한 가지 유형은 어떤 저장소에도 존재하지 않습니다. 모델의 가중치(weights) 안에 동결되어 있습니다.

전체 목록은 다음과 같으며, 이후 이에 대해 논하겠습니다.

#유형 (Type)수명 (Lives)한 줄 요약 (In one line)
1워킹 메모리 (Working)단기 (Short)현재 컨텍스트 윈도우 내의 모든 것
...

표를 지나 읽어보면 이 중 두 가지는 메모리처럼 작동하지 않는다는 것을 알게 될 것입니다. 그 부분이 흥미로운 지점입니다.

1. 워킹 메모리 (Working memory): 비용을 지불하는 곳

워킹 메모리는 컨텍스트 윈도우(context window)입니다: 시스템 프롬프트(system prompt), 대화 기록(conversation history), 도구 출력(tool outputs), 검색된 청크(retrieved chunks), 그리고 모델 자체의 실행 중인 추론(running reasoning)이 여기에 해당합니다. 이는 모델이 직접 볼 수 있는 유일한 메모리입니다. 이 목록에 있는 다른 모든 유형은 적절한 시점에 이곳으로 자신을 로드하기 위해 존재합니다.

이에 관한 세 가지 사실이 당신의 전체 아키텍처(architecture)를 결정합니다. 첫째, 경계가 정해져 있으므로 한계에 도달하면 데이터를 내보내거나(evict) 요약(summarize)해야 합니다. 둘째, 세션 종료 시 사라집니다. 셋째, 매 턴마다 비용을 다시 지불해야 합니다. 왜냐하면 매 호출(call)마다 전체 윈도우가 다시 전송되기 때문입니다.

마지막 사실이 바로 비용이 발생하는 지점이며, 이는 단순한 수학적 문제입니다. 전체 기록을 유지하는 50턴의 대화는 1턴의 내용을 50번 다시 전송합니다. 초기 컨텍스트는 한 번만 비싼 것이 아니라, 남은 턴마다 매번 비싸집니다. 이것이 "그냥 더 큰 컨텍스트 윈도우를 사용하면 된다"라는 말이 해결책이 아니라 신용카드와 같은 것인 이유입니다. 청구서가 도착하기 전까지는 작동하겠지만, 청구서는 대화 길이의 제곱에 비례하여 늘어납니다.

코드에 마법은 없으며, 단지 매 턴마다 전체 목록이 다시 전달될 뿐입니다:

# 매 턴마다 전체 윈도우가 다시 전송됩니다. 이것이 비용입니다.
history.append(user_msg)
reply = llm.invoke([system_prompt, *history])
...

프레임워크들은 지속성 상태 (persisted state)를 통해 이 문제를 덮어버립니다. 예를 들어, LangGraph 체크포인터 (checkpointer)는 스레드 (thread)를 저장하여 재시작 후에도 히스토리 (history)가 유지되도록 합니다. 하지만 지속성 (persistence)이 비용을 덜 지불하는 것과 동일한 것은 아닙니다. 호출할 때마다 여전히 전체 윈도우 (window)가 그대로 전달되기 때문입니다. 실제로 당신이 제어할 수 있는 것은 그 리스트에 무엇이 들어가는가이며, 이것이 바로 제거 (eviction)와 요약 (summarization)이 실질적인 조절 레버인 이유입니다.

작업 메모리 (Working memory)는 여기서 다른 모든 것들이 수렴하는 지점입니다. 이를 잘못 설정하면, 이후에 어떤 영리한 검색 (retrieval) 체계를 도입하더라도 당신을 구할 수 없습니다.

2, 3, 4: 분리할 가치가 있는 세 가지 장기 저장소

이 세 가지는 시스템의 핵심이며, 이들은 서로 다른 질문에 답하기 때문에 별도로 유지하는 것이 유용한 전략입니다.

**의미론적 메모리 (Semantic memory)**는 '무엇을 아는가 (know-what)'에 해당합니다. 즉, 학습 시점과 무관하게 유지되는 안정적인 사실과 선호도입니다. 예를 들어, 어떤 사용자가 엔터프라이즈 (Enterprise) 플랜을 사용 중이며 전화보다 이메일을 선호한다는 사실, 혹은 어떤 고객이 중등도 위험 프로필을 가진 비거주 인도인 (NRI)이며 구조화 상품에는 손을 대지 않는다는 사실 등이 있습니다. 당신은 이를 매번 다시 도출할 필요 없이 모든 대화에 적용합니다. 이는 정형화된 필드를 위한 구조화된 저장소 (structured store)와 모호한 회상을 위한 벡터 저장소 (vector store)를 결합하여 구축하며, 프로필을 점진적으로 업데이트합니다.

여기서의 실패 모드는 검색 (retrieval)이 아닙니다. 바로 진실성 (truth)입니다. 단일 사용자에게 오래된 정보는 단순한 번거로움에 불과합니다. 하지만 여러 에이전트 (agent)가 동일한 프로필에 기록을 남기는 엔터프라이즈 규모에서는, '진실의 원천 (source-of-truth)' 충돌이 어려운 문제가 됩니다. 즉, 두 에이전트가 동일한 사실에 대해 서로 모순되는 버전을 보유하고 있고 이를 중재할 장치가 없는 상황입니다. 이것은 메모리의 탈을 쓰고 있는 데이터 거버넌스 (data-governance) 문제이며, 실제로 운영 환경에서 문제를 일으키는 핵심 요소입니다.

**일화적 메모리 (Episodic memory)**는 특정 과거 사건의 로그입니다. 전체 실행 과정, 에이전트가 내린 결정, 그리고 그것이 효과적이었는지 여부를 기록합니다. 사기 탐지 에이전트는 각 사례(감지된 패턴, 권장 사항, 그리고 그것이 실제 사기였는지 혹은 오탐 (false positive)이었는지 여부)를 기록한 다음, 유사한 시그니처 (signature)가 나타나면 가장 일치하는 사례를 불러옵니다. 이것이 사례 기반 추론 (case-based reasoning)입니다. 에이전트가 동일한 실수를 반복하지 않게 만드는 방법이 바로 이것입니다.

**절차적 메모리(Procedural memory)**는 '방법을 아는 것(know-how)'입니다. 즉, 워크플로우, 도구 사용 패턴, 그리고 무언가를 수행하는 규칙들입니다. 클레임 에이전트의 흐름은 절차적입니다: 정책을 검증하고, 피해 사진을 평가하며, 사기 신호를 확인하고, 지급액 범위를 계산한 후, 특정 임계값 이상일 경우 승인을 위해 라우팅합니다. 이 중 일부는 메타-컨트롤러 역할을 하는 조정된 시스템 프롬프트에 존재하고, 일부는 외부 의사 결정 규칙 저장소에 존재합니다. 규칙의 경우, 구조화된 키 조회(key lookup)가 모호한 검색(fuzzy search)보다 항상 우수합니다. 코사인 유사도(cosine similarity)로

그 루프, 즉 통합(consolidation)은 전체 시스템에서 가장 가치 있는 단계이자 가장 적게 구현되는 단계입니다. 거의 모든 이들이 에피소드(episodes)를 기록합니다. 하지만 거의 아무도 이를 지속 가능한 규칙(durable rules)으로 되돌려 루프를 완성하지 않습니다. 이는 일기를 쓰는 에이전트와 학습하는 에이전트의 차이이며, 이것이 바로 2부의 주제입니다.

5. 검색(Retrieval)은 메모리 유형이 아니다

여기서 저는 인기 없는 입장을 취하려 합니다. RAG는 메모리의 한 종류가 아닙니다. 그것은 전달 메커니즘(delivery mechanism)입니다.

메커니즘은 익숙합니다: 쿼리(query)를 임베딩(embed)하고, 벡터 스토어(vector store)에서 유사도 검색(similarity search)을 실행하며, 상위 k개(top-k)의 청크(chunks)를 컨텍스트(context)에 주입하고, 모델이 이를 바탕으로 근거 있는(grounded) 답변을 하도록 하는 것입니다. 규정 준수 봇(compliance bot)은 RBI 및 SEBI 규정을 벡터 스토어에 보관하고, KYC 질문에 필요한 몇 개의 구절만을 가져옵니다. 유용하긴 합니다. 하지만 그곳에 무엇이 저장되어 있는지 주목하십시오: 의미론적 사실(semantic facts)과 에피소드적 사건(episodic events)입니다. 검색(Retrieval)은 이것들이 스토어에서 작업 메모리(working memory)로 이동하는 방식입니다. 그것은 물이 아니라 파이프입니다.

이것이 중요한 이유는 이 둘을 혼동하는 것이 바로 너무 많은 에이전트가 "단순히 벡터 DB일 뿐"인 상태로 멈춰버리는 정확한 이유이기 때문입니다. 일단 검색을 배관(plumbing)으로 인식하고 나면, 진짜 질문들이 떠오릅니다: 무엇을 저장할 가치가 있는가, 어떻게 일관성을 유지할 것인가, 그리고 유사도(similarity)가 완전히 잘못된 액세스 패턴이 되는 시점은 언제인가? 규칙(rules)이나 정확한 조회(exact lookups)의 경우 대개 그렇습니다. 유사도는 정답과 유사한 값을 읽어 들임으로써 기꺼이 잘못된 임계값(threshold)을 제공할 것이기 때문입니다.

그리고 덧붙이자면: 유사도는 관련성(relevance)이 아닙니다. 귀하의 쿼리 임베딩에 대해 가장 높은 점수를 받은 청크는 벡터 공간에서 가장 가까운 것이지, 질문에 답하는 것과 동일하지는 않습니다. 이 두 가지 사이의 간극이 바로 "RAG가 환각(hallucination)을 일으킨다"는 대부분의 버그 보고가 실제로 발생하는 지점입니다.

6. 파라메트릭 메모리(Parametric memory): 모델 그 자체인 지식

파라메트릭 메모리(Parametric memory)는 학습(training) 시점에 가중치(weights)에 구워진(baked) 모든 것입니다: 문법, 산술, 광범위한 세상 지식, 파리가 프랑스의 수도라는 사실 같은 것들 말입니다. 모델은 이것을 참조하지 않습니다. 모델이 곧 이것입니다. 검색 단계가 필요 없으며, 항상 사용 가능하고, 즉각적입니다.

그것이 바로 변화하는 모든 것들에 대해 이것이 함정이 되는 정확한 이유입니다. 가중치(Weights)는 학습 실행(Training runs) 사이에 동결됩니다. 가중치는 불투명하며, 확신에 차서 틀릴 수 있고, 학습 중단 시점(Cutoff) 이후의 일에 대해서는 아무것도 알지 못합니다. 따라서 설계 경계는 명확합니다. 일반적인 추론(Reasoning)과 언어는 파라메트릭(Parametric) 메모리로 가고, 휘발성이 있거나, 독점적이거나, 최신 정보인 것은 외부 저장소(External store)로 갑니다.

구체적으로 말하자면: "LTV(Loan-to-value, 담보인정비율)"이 무엇인지 아는 것은 파라메트릭(Parametric)이며, 이에 대해서는 모델을 신뢰해야 합니다. 현재의 기준 금리나 특정 은행의 상품 규정은 반드시 당신이 제어하는 저장소에서 가져와야 합니다. 변하지 않는 것은 내장(Bake in)시키고, 변하는 것은 검색(Retrieve)하세요. 이 둘을 혼동하는 것이 에이전트가 작년 이자율을 아주 자신 있게 인용하게 되는 원인입니다.

7. 미래 기억 (Prospective memory): 벡터 DB로는 흉내 낼 수 없는 것

마지막 유형은 위의 모든 것들과 아키텍처적으로 다른 유형입니다. 미래 기억(Prospective memory)은 나중에 행동할 것을 기억하는 것입니다. 즉, 에이전트가 형성했지만 아직 실행하지 않은 의도(Intentions)를 의미합니다. "매월 1일에 포트폴리오 리뷰를 보내라.", "이 고객의 SIP(Systematic Investment Plan, 정기 적립식 투자 계획)가 실패하면 관계 관리자에게 알림을 보내라.", "지난 3월에 결정된 대로, 9월에 이 정기 예금(FD) 만기를 검토하라."와 같은 것들입니다.

유사도 검색(Similarity search)으로는 이것을 구축할 수 없으며, 그것이 핵심입니다. 임베딩(Embed)할 쿼리(Query) 자체가 존재하지 않기 때문입니다. 이것은 작업 큐(Task queue), 스케줄러(Scheduler), 그리고 시계(Clock)나 이벤트(Event)라는 트리거(Trigger)에 의해 작동하는 목표 추적기(Goal trackers)입니다. 만약 당신의 에이전트가 다음 주 월요일에 무언가를 해야 한다면, 아무리 검색 튜닝(Retrieval tuning)을 해도 이를 달성할 수 없습니다. 당신에게는 월요일에 깨어날 무언가가 필요합니다.

# 벡터 저장소가 아닌 스케줄러입니다.
scheduler.add_job(send_portfolio_review, "cron", day=1, args=[client.id])
scheduler.add_job(review_fd_maturity, "date", run_date="2026-09-01", args=[fd.id])
...

APScheduler는 프로세스 내부(In-process) 케이스를 다룹니다. 의도가 크래시(Crash) 상황에서도 살아남아야 한다면 Celery나 Temporal을 사용하세요. 어떤 방식이든 트리거는 시계나 이벤트이지, 결코 쿼리가 아닙니다.

이것은 챗봇과 시계(horizon)를 가진 에이전트를 구분 짓는 유형입니다. 이를 건너뛴다면 당신의 에이전트는 눈앞에 놓인 메시지에 반응할 수만 있을 것입니다. 하지만 이를 구축한다면 에이전트는 스스로의 미래를 계획할 수 있으며, 이것이 바로 "에이전트적(agentic)"이라는 말이 실제로 의미하는 대부분의 핵심입니다.

실제 도구에서 각 유형이 위치하는 곳

분류 체계에서 의존성(dependencies)으로 가는 지름길을 원하신다면, 현재 각 유형이 대략 어디에 위치하는지는 다음과 같습니다.

유형필요한 것활용할 도구
Working (작업 메모리)지속되는 스레드 상태 (Persisted thread state), 제거 (eviction) 및 요약 (summary)LangGraph 체크포인터 (checkpointers), 사용 중인 프레임워크의 스레드 상태
...

이 중 어느 것도 단독으로는 하중을 견디는 핵심 요소(load-bearing)가 아닙니다. 아키텍처는 이 일곱 개의 상자와 그 상자들이 서로 지식을 전달하는 방식입니다. 라이브러리는 단지 그 상자들을 채울 뿐입니다.

결론: 실제로 무엇을 구축해야 하는가

에이전트를 시작하면서 어디에 비용을 투자해야 할지 알고 싶다면, 제가 권장하는 순서는 다음과 같습니다.

작업 메모리(working memory)부터 시작하고, 이를 편의 기능이 아닌 예산(budget)으로 취급하세요. 이는 복리로 쌓이는 유일한 비용이므로, 그 위에 무언가 영리한 것을 구축하기 전에 제거(eviction) 및 요약(summarization) 전략을 먼저 확립하십시오. 다른 모든 것은 여기에 로드되며, 당신은 턴(turn)당 비용을 지불하게 됩니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0