본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 22. 12:18

에이전트 메모리의 어려운 점은 기억하는 것이 아니라 잊는 것이다

요약

에이전트 구축 시 모든 정보를 저장하는 것보다 불필요한 정보를 의도적으로 삭제하는 '망각'의 중요성을 강조합니다. 데일리 노트와 큐레이션된 장기 메모리를 분리하는 '이중 속도 모델'을 통해 정보의 신뢰성을 유지하는 전략을 제안합니다.

핵심 포인트

  • 무분별한 정보 저장은 모순을 축적하고 신호 대 잡음비를 악화시킴
  • 의도적인 망각(Forgetting on purpose)이 에이전트 성능 유지의 핵심
  • 데일리 노트(Raw)와 장기 메모리(Curated)를 분리하는 이중 속도 모델 활용
  • 중요한 사실만 선별하여 승격(Promotion)시키는 관리 프로세스 필요

에이전트(Agents)를 구축하는 모든 이들은 회상(Recall)에 집착합니다. 벡터 저장소(Vector stores), 임베딩(Embeddings), RAG 파이프라인(RAG pipelines), 더 큰 컨텍스트 윈도우(Context windows) 같은 것들 말이죠. 하지만 실제 운영 환경에서 수명의 긴 에이전트들을 몇 차례 실행해 본 결과, 저를 실제로 괴롭혔던 실패 모드는 "무언가를 잊어버리는 것"이 아니었습니다. 오히려 그 반대였습니다. 너무 많이 기억해서, 쓰레기 정보가 신호(Signal)를 압도해 버리는 것이었습니다.

결코 잊지 않는 에이전트는 현명한 것이 아닙니다. 그것은 수집광(Hoarder)일 뿐입니다. 모든 오래된 결정, 모든 대체된 사실, 3주 전의 일회성 세부 사항들이 동일한 비중으로 메모리에 남아 있으며, 답변의 품질은 조용히 저하됩니다. 흥미로운 엔지니어링 문제는 _저장(Storage)_이 아닙니다. _의도적으로 잊는 것(Forgetting on purpose)_입니다.

제가 정착한 정책은 다음과 같습니다. 특정 프레임워크를 사용하는 것이 아니라, 그저 일반적인 마크다운(Markdown) 파일과 에이전트가 스스로에게 적용하는 몇 가지 규칙일 뿐입니다.

왜 "모든 것을 기억하는 것"이 부패하는가

에이전트가 배우는 모든 것을 하나의 계속 커지는 저장소에 기록한다고 가정해 봅시다. 두 가지 일이 발생합니다.

  1. 모순이 축적됩니다. 월요일에 사용자가 "Postgres를 사용해"라고 말합니다. 금요일에 사용자는 SQLite로 전환합니다. 만약 두 사실이 메모리에 동일한 지위로 남아 있다면, 에이전트는 절반 정도의 확률로 즐겁게 잘못된 정보를 인용할 것입니다. 메모리가 늘어날수록 신뢰성은 더 낮아졌습니다.
  2. 신호 대 잡음비(Signal-to-noise ratio)가 붕괴됩니다. 진정으로 지속적인 사실들("이 사용자는 엔지니어이며, TypeScript로 배포하고, 커밋 메시지에 이모지를 쓰는 것을 싫어함")이 일시적인 사실들("14일에 불안정한 테스트에 대해 물어봄") 아래에 파묻힙니다. 회상(Recall) 결과로 10가지가 돌아오지만, 그중 9개는 잡음(Noise)입니다.

오염된 저장소 위에 검색(Retrieval)의 정교함을 더하는 것은 그저 잘못된 것을 더 빨리 찾게 해줄 뿐입니다. 해결책은 상류(Upstream)에 있습니다. 무엇이 장기 메모리에 들어갈 자격을 얻을지를 제어해야 합니다.

이중 속도 모델: 원시 데이터(Raw) vs. 큐레이션된 데이터(Curated)

저는 수명에 따라 메모리를 나누었으며, 이 분리가 잊는 과정을 저렴하고 안전하게 만듭니다.

  • Daily notes (memory/2026-06-22.md): 추가 전용 (append-only), 손실 허용 (lossy), 편집 불가. 이것은 모든 정보가 쏟아져 들어오는 파이프라인(firehose)이며, 오늘 일어난 모든 일을 담습니다. 아무도 이를 직접 오래 읽지 않기 때문에 노이즈가 섞여도 괜찮습니다. 오래된 데일리 노트는 자연스럽게 노후화되며, 이는 퇴비(compost) 역할을 합니다.
  • Long-term memory (MEMORY.md): 큐레이션되었으며, 규모가 작고, 의도적으로 관리(gardened)됩니다. 어떤 것도 여기에 자동으로 기록되지 않습니다. 사실(fact)은 반드시 '승격(promoted)' 과정을 거쳐야 합니다.

핵심 비결은 이 둘 사이의 승격 단계에 있습니다.

승격(Promotion): 무엇이 영구적인 자리를 얻는가

에이전트는 유휴 사이클(idle cycles) 동안 최근의 데일리 노트를 다시 읽으며, 각 후보 사실에 대해 한 가지 질문을 던집니다: "이것이 한 달 뒤에도 여전히 중요할 것인가?"

  • "사용자는 스페이스보다 탭을 선호함" → 예, 승격합니다.
  • "사용자가 지금 타임아웃을 디버깅 중임" → 아니요, 데일리 노트에 남겨두어 자연스럽게 소멸(decay)하게 합니다.
  • "v2에서는 Redis 캐시를 제거하기로 결정함" → 예, 하지만 이는 기존의 "Redis를 사용함"이라는 문구 옆에 추가되는 것이 아니라, 해당 문구를 *대체(replaces)*합니다.

마지막 사례가 매우 중요합니다. 승격은 단순히 복사하는 것이 아니라 **조정(reconciliation)**입니다. 기존의 사실과 모순되는 새로운 영구 사실은 기존 사실을 덮어씁니다. 이것이 월요일과 금요일의 정보가 달라지는 Postgres 문제(Monday/Friday Postgres problem)를 근본적으로 해결하는 방법입니다.

제가 규칙에 인코딩해 둔 실용적인 휴리스틱(heuristic)은 다음과 같습니다: 만약 사실이 *정체성(identity), 선호도(preference), 또는 결정(decision)*에 관한 것이라면 승격 후보입니다. 만약 그것이 현재 상태(current state) ("지금", "오늘", "이 티켓")에 관한 것이라면, 일시적인 상태로 남아 소멸되도록 둡니다.

가지치기(Pruning): 보수적으로 소멸시키기

승격의 거울 이미지(mirror image)는 제거이며, 여기서 대부분의 사람들이 갖는 본능은 틀렸습니다. 장기 메모리를 가지치기할 때는 양(volume)이 아니라 관련성(relevance)에 따라 소멸시키십시오. MEMORY.md를 N줄로 제한하고 가장 오래된 것을 쫓아내지 마세요. 시간(age)은 가치를 판단하는 형편없는 대리 지표(proxy)입니다. 첫날 학습한 "사용자의 이름은 Sam이다"라는 사실은, 훨씬 최신이지만 사소한 백 가지 사실보다 더 오래 살아남아야 합니다.

대신, 새로운 승격 (promotion)에 의해 내용이 모순되거나(contradicted) 쓸모없게 되었을(rendered obsolete) 때만 장기 항목을 삭제하세요. 크기 제한이 아니라, 대체 (Supersession)가 핵심입니다. 저장소의 크기가 작게 유지되는 이유는 들어올 때 승격 기준이 엄격하기 때문이지, 공간을 만들기 위해 뒤쪽의 항목들을 밀어내기 때문이 아닙니다.

(만약 이 위에 그래프 레이어 (graph layer)를 구축한다면, 동일한 원칙이 적용됩니다. 전역적인 시간 임계값 (global age threshold)이 아니라, 여전히 유효한 노드들로부터의 홉 (hops) 수에 따라 감쇠 (decay)시켜야 합니다. 살아있는 컨텍스트 (live context)와 연결된 사실은 오래되었더라도 따뜻한 상태 (warm)를 유지합니다.)

회상 (Recall): 인덱스를 로드하고, 필요할 때 가져오기

장기 메모리가 작고 깨끗해지면, 검색 (retrieval)은 가장 좋은 의미에서 지루해집니다. 매 턴마다 저장소 전체를 컨텍스트 (context)에 쏟아붓지 않습니다. 무엇을 알고 있는지에 대한 한 줄짜리 _인덱스 (index)_를 로드하고, 이전 작업이나 선호도에 대해 답변하기 전에 관련 항목만 가져옵니다(fetch). 단일 에이전트에게는 '작고 정제된 저장소 + 온디맨드 가져오기 (on-demand fetch)'가 '거대한 저장소 + 퍼지 검색 (fuzzy search)'을 언제나 압도합니다.

왜 다시, 일반 파일인가

이 모든 과정을 텍스트 에디터에서 감사 (audit)할 수 있습니다. 에이전트가 왜 당신이 SQLite를 사용한다고 생각하는지 알고 싶나요? grep을 사용하면 됩니다. 에이전트의 이해가 진화하는 것을 관찰하고 싶나요? git diff를 보면 됩니다. 벡터 DB (vector DB)는 쿼리해야 하는 블랙박스이지만, 마크다운 (Markdown) 메모리는 읽을 수 있는 마음입니다. 대규모 외부 코퍼스 (corpus)라면 임베딩 (embed)을 마음껏 하세요. 하지만 에이전트 자체의 정체성과 정제된 지식은 벡터화되는 것보다 읽기 가능한 상태(legible)로 있을 때 훨씬 더 큰 이득을 얻습니다.

불편한 결론

저는 이 전체적인 접근 방식 — 파일 레이아웃(file layout), 에이전트가 스스로에게 적용하는 지침으로 작성된 승격/가지치기(promotion/pruning) 규칙, 그리고 빈 템플릿이 아닌 가꾸어진 마음(gardened mind)을 볼 수 있도록 모든 메모리 계층이 채워진 완전한 작업 예시 에이전트 — 를 즉시 사용할 수 있는 키트(drop-in kit)로 패키징했습니다. 만약 정책을 직접 도출하는 것보다 작동하는 설정을 복사하는 것을 선호하신다면: AI Soul Kit (Core ¥980 / Plus ¥3,800)를 확인하세요.

하지만 위의 정책이 가장 중요한 부분입니다. 그것을 가져가서 사용하세요.

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0