에이전트 메모리를 1년간 구축해 본 결과, '전부 저장하고 RAG 돌리기'는 잘못된 기본값이라는 확신이 들었다
After a year building agent memory, I'm convinced "save everything + RAG it" is the wrong default
핵심 요약
단순한 RAG 기반 메모리 시스템의 한계를 지적하며, 엔티티 중심의 지식 그래프 모델로 전환해야 한다는 개발자의 경험 공유.
- 메모리 한계 — 단순 텍스트 저장 방식은 정보의 갱신이나 모순 해결이 불가능함
- 지식 그래프 — 엔티티와 사실 관계를 구조화하여 맥락을 유지하는 방식이 효과적임
- 데이터 갱신 — 새로운 정보가 들어올 때 기존 사실을 업데이트하는 모델링이 필수적임
- 실무적 고민 — 사실의 덮어쓰기와 보존 사이의 균형을 맞추는 것이 가장 어려운 과제임
에이전트 메모리를 다루는 기본 방식은 대충 이래. 사용자가 하는 말을 죄다 저장하고, 임베딩 돌린 다음에, 질문 들어오면 가장 비슷한 덩어리들을 컨텍스트로 불러오는 거지. 그냥 검색창 달린 대화 기록장 수준이야. 만들기 쉽고 데모용으론 딱인데, 막상 실전에서 돌려보면 금방 밑천 드러나지.
문제는 검색 품질이 아니야. 과거 메시지 뭉치에는 이런 개념이 아예 없다는 게 문제지:
- 억제(Suppression): 3월에 했던 말이 6월에 뒤집혔어. 근데 두 덩어리 다 그대로 남아있고 똑같이 검색돼. 모델은 둘 다 가져와서 아무거나 고르는데, 보통 구닥다리 정보를 집어오지.
- 정체성(Identity): "그 사람", "그 클라이언트", "그 프로젝트"가 대화마다 제각각인데, 이게 사실 같은 대상을 가리킨다는 걸 모름.
- 메시지 간의 연관성: 한 대화에서 약속한 걸 다른 대화에서 이행했는데, 시스템은 그냥 서로 상관없는 두 덩어리로만 인식함.
이런 의미들은 메시지 사이에 녹아있는 건데, 원본 기록을 그대로 저장하는 순간 그 정보들은 다 날아가 버려. 임베딩을 더 좋게 하거나 리랭킹을 해봐야 소용없어. 애초에 정보가 인코딩된 적이 없으니까.
내가 써보니까 메모리를 로그가 아니라 사용자의 세계를 모델링하는 방식으로 다루는 게 훨씬 낫더라:
- 문장이 아니라 엔티티(사람, 프로젝트, 약속 등)를 핵심 단위로 저장함.
- 각 사실에 출처, 신뢰도, 타임스탬프를 붙임.
- 새로운 정보가 들어오면 옛날 정보 옆에 쌓는 게 아니라, 모델을 업데이트함.
- 검색은 "텍스트 검색해서 운에 맡기는 방식"이 아니라, "이미 조각들이 어떻게 연결되어 있는지 아는 구조에서 필요한 부분만 읽어오는 방식"으로 바뀜.
한마디로 사용자 중심의 가벼운 시계열 지식 그래프를 만드는 거야. 벡터 검색은 그중 하나의 경로일 뿐이고.
물론 처음엔 손이 많이 가. 엔티티 식별도 해야 하고, 덮어쓰기 규칙도 정해야 하고, 뭐가 영구적인 사실이고 뭐가 일회성 잡담인지 구분도 해야 하니까. 나도 아직 구체적인 경계는 다듬는 중이야. 지금 제일 골치 아픈 건, "업데이트"할 때 옛날 사실을 덮어쓸지, 아니면 시간 흐름에 따른 변화로 보고 둘 다 남겨둘지 결정하는 거임.
다들 세션 넘나드는 장기 메모리 어떻게 처리하는지 궁금하네:
- 그냥 순수하게 히스토리 기반 벡터 검색 써? 아니면 그래프? 아니면 하이브리드?
- 옛날 정보나 뒤집힌 사실들이 다시 튀어나오는 건 어떻게 막아?
- 뭐가 영구 메모리로 남을지, 아니면 그냥 사라지게 둘지 정하는 깔끔한 휴리스틱 같은 거 있어?


