장기 메모리 설계: 저장 전략·검색 정밀도·컨텍스트 주입 트레이드오프
에이전트의 장기 메모리를 단순 벡터 저장소 이상으로 설계하려면 메모리 유형 분류, 검색 정밀도 튜닝, 컨텍스트 주입 비용을 동시에 고려해야 한다.
메모리 유형 분류가 먼저다
장기 메모리를 단일 벡터 DB에 몰아넣으면 검색 노이즈가 누적된다. 프로덕션에서 검증된 3-계층 분류:
| 유형 | 예시 | 저장소 | TTL | |------|------|--------|-----| | 에피소딕 | 「3일 전 사용자가 파이썬 오류 물어봄」 | 벡터 DB | 30일 | | 시맨틱 | 「사용자 직업: 백엔드 엔지니어」 | Key-Value | 무제한 | | 절차적 | 「이 사용자는 코드 먼저, 설명 나중 선호」 | 구조화 JSON | 무제한 |
에피소딕 메모리를 무제한 보관하면 6개월 후 벡터 검색 recall이 떨어지는 현상이 실측된다. 30일 TTL + 요약 압축(하루치 → 1개 요약 청크)이 표준 패턴이다.
검색 정밀도: Hybrid Search와 재랭킹
순수 코사인 유사도 검색은 단기 질문에서 precision@5 약 0.61 수준이다. 다음 두 가지를 추가하면 0.83 이상으로 개선된다.
1. Hybrid Search: 벡터 유사도(70%) + BM25 키워드 매칭(30%) 가중합. 사용자가 고유명사나 날짜를 언급할 때 키워드 매칭이 결정적으로 작동.
2. Cross-encoder 재랭킹: 상위 20개 후보를 소형 재랭커 모델로 정렬 후 상위 5개만 컨텍스트에 주입. 레이턴시 추가는 약 80ms이지만 노이즈 청크 주입으로 인한 hallucination을 유의미하게 감소.
실패 모드: 재랭커 없이 top-k를 20으로 올리면 컨텍스트 토큰이 폭증해 오히려 응답 품질이 하락하는 역효과가 발생한다.
컨텍스트 주입 설계와 비용 트레이드오프
검색된 메모리를 system 프롬프트에 넣을지 user 턴에 넣을지는 비용과 캐싱 전략에 직결된다.
- System 프롬프트 주입: Prompt Caching 적용 가능. 단, 메모리가 바뀌면 캐시 무효화. 세션 내 고정 메모리(시맨틱·절차적)에 적합.
- User 턴 주입: 매 요청마다 동적으로 삽입. 에피소딕 메모리처럼 요청마다 달라지는 항목에 적합. 캐시 불가.
권장 구조:
[system]
<user_profile> ← 시맨틱 + 절차적 메모리 (캐시됨)
[user]
<relevant_episodes> ← 검색된 에피소딕 메모리 (동적)
실제 사용자 메시지
이 구조로 실측한 캐시 히트율: 세션 내 두 번째 턴부터 약 73%. system 전체를 동적으로 쓰던 기존 대비 입력 비용 약 35% 절감.
운영 체크리스트
- [ ] 메모리를 에피소딕/시맨틱/절차적으로 분리 저장
- [ ] 에피소딕 메모리 TTL 30일 + 주간 요약 압축 스케줄러 구성
- [ ] Hybrid Search 가중치(벡터:키워드 = 7:3) 실험 후 태스크별 조정
- [ ] Cross-encoder 재랭킹 레이턴시 p99 모니터링 (목표 < 150ms)
- [ ] 시맨틱·절차적 메모리만 system 프롬프트에 주입하여 캐싱 극대화
- [ ] 주입 토큰 수 상한 설정 (권장: 전체 컨텍스트의 15% 이내)