"쓰기 성공"과 "읽기 가능" 사이 — Agent 기억의 신선도 갭
← 전체 목차 · 이전: 기억 오염과 회수 신뢰성 · 다음: Prompt는 변수 이스케이프를 해야 한다
사용자가 이번 달 매출 표를 방금 업로드했다. Agent에게 실적 요약을 시키자 계속 지난달 데이터로 답한다. 후단을 뒤져보면 파일 업로드는 성공했고, 벡터 저장소 로그에도 입고 완료라고 찍혀 있다. 그런데도 Agent는 최신 내용을 검색해내지 못한다 — "입고 성공"과 "검색 가능"은 서로 다른 사건이며, 그 사이에 인덱스 구축이라는 시간차가 끼어 있기 때문이다. 이 문서에서는 이 실패를 기억 유령 함정이라 부른다: 데이터는 저장소에 실제로 존재하고 로그도 초록불인데, Agent의 검색 시야에서는 아직 "살아나지" 않아 옛 내용이 여전히 "현재 지식"인 척 계속 불려나온다.
왜 향상된 검색 품질로는 못 고치나
이 실패는 리랭크·Top-K·임베딩 품질의 문제가 아니다. 검색 로직 자체는 정확히 작동했고, 다만 옛 버전의 세계를 정확히 찾아냈을 뿐이다. 그래서 이것은 검색 품질 문제가 아니라 일관성(consistency) 문제다 — "입고 완료"라는 신호와 "이 데이터가 지금 조회 가능하다"는 신호를 하나로 취급한 것이 근본 원인이다.
1층 — 기억을 시효 요구에 따라 분기한다
모든 데이터를 같은 강도로 관리하지 않는다. 일관성 수준을 데이터 자체의 속성으로 만들어, 검색 전에 이미 읽기 경로가 갈라지게 한다.
| 읽기 유형 | 해당 데이터 | 경로 | 예 |
|---|
| 강한 시효 읽기 | 사용자가 방금 올리거나 방금 상호작용으로 만든 데이터 | 짧은 컨텍스트 창에 강제 주입, 첫 조회는 벡터 검색을 거치지 않음 | 방금 올린 이번 달 표 → 다음 대화에 곧바로 컨텍스트로 실어 보냄 |
| 최종 일관성 읽기 | 과거 문서·범용 지식베이스 등 지연을 용인 가능한 데이터 | 정상적으로 벡터 검색 경로 | 작년도 업계 리포트 → 몇 시간 늦게 입고돼도 무방 |
2층 — 검색의 강등과 지연 감시 뒤로 빠지기
지연이 언제나 존재함을 인정하고, 검색에 세 가지 안전망을 둔다.
읽기 요청(사용자 업로드 시각 동반)
├─ 입고/인덱스 지연 > 임계값(예: 5초) ──→ 강등: 컨텍스트 주입으로 전환, 인덱스가 살아날 때까지 유지
├─ 검색 결과 버전 < 요청 버전 ──→ 원문 보완 또는 컨텍스트 전환
└─ 핫 파일 적중 ──→ 세션 내 캐시된 원문 조각 재사용, 재검색 생략
- 지연 감시 + 자동 강등: 입고·인덱스 구축 지연을 모니터링하다가 임계값을 넘으면 해당 데이터의 조회를 자동으로 컨텍스트 주입으로 되돌리고, 인덱스가 정상화될 때까지 유지한다. 강등에는 명확한 종료 조건이 있어야 한다 — 그러지 않으면 비싼 인덱스를 다시는 쓰지 않는 상태로 굳는다.
- 버전·타임스탬프 검증: 모든 지식 파일에 버전과 입고 시각을, 모든 읽기 요청에 사용자의 업로드 시각을 함께 싣는다. 검색 결과 버전이 요청보다 낡았으면 원문을 보완하거나 컨텍스트로 전환한다.
- 세션 캐시: 같은 세션 안에서 핫 파일이 반복 검색되는 낭비를 막기 위해 원문 조각을 세션 내에 잠깐 캐시한다.
3층 — 아키텍처로 실효 구간 자체를 줄인다
앞의 두 층이 "돌아가고" "받쳐준다"면, 세 번째 층은 실패가 생기는 시간 구간 자체를 좁힌다.
- 증분 실시간 인덱스 — 새 파일은 먼저 초 단위의 작은 인덱스를 만들고, 이후 전체 인덱스에 합류시켜 입고 유효 속도를 끌어올린다.
- 쓰기 후 지연(write-then-delay) — 핵심 파일 업로드 후 업무 스레드가 수백 밀리초 대기해 인덱스 구축 시간을 벌어준다. 만능은 아니며, 고빈도 업로드 시나리오에 한해 효과가 있다.
- 강제 컨텍스트 주입 스위치 — 핵심 업무 경로(예: 중요 고객 전용 조회)에는 새 파일을 항상 컨텍스트로 강제 주입하는 스위치를 둔다. Token을 더 쓰더라도 데이터 정확성을 우선한다는 명시적 취사선택이다.
핵심 통찰
- "입고 성공"은 "검색 가능"을 증명하지 않는다 — 두 신호가 모두 초록불이어도 그 사이에 인덱스 구축이라는 구간이 존재한다. 모니터링이 입고 신호만 보고 있으면 이 구간 전체가 관측 사각지대가 된다.
- 이 실패는 저장 문제가 아니라 일관성 문제로 분류해야 올바른 해법이 나온다 — "검색 로직에 문제가 있다"고 진단하면 리랭크·임베딩을 손대는 헛수고를 하게 된다. 정답은 "옛 버전의 세계를 정확히 찾아냈다"는 것을 알아채는 데 있다.
- 일관성 수준은 시스템 전역 설정이 아니라 데이터의 속성이어야 한다 — 방금 올린 표와 작년 리포트를 같은 읽기 경로에 태우는 것 자체가 설계 오류다. 전자는 몇 초도 못 견디고, 후자는 몇 시간 늦어도 무방하다. 한쪽 기준으로 통일하면 반드시 다른 쪽에서 사고가 나거나 비용이 폭발한다.
- "전량을 컨텍스트에 밀어 넣자"는 유혹적이지만 특권으로만 허용해야 한다 — 방금 업로드된 데이터, 핵심 업무 경로, 강등 기간 같은 한정된 범위에서만 쓸 수 있는 수단이다. 기본 전략으로 삼으면 Token 비용과 창 길이가 곧바로 감당 불가능해진다.
- 강등에는 반드시 퇴출 조건이 있어야 한다 — "지연 초과 시 컨텍스트 주입"이 영구 상태가 되면, 비용을 들여 구축한 인덱스를 다시는 쓰지 않는 시스템이 조용히 완성된다.
- 완벽한 해법이 없는 수단도 정직하게 범위를 밝히는 편이 낫다 — "업무 스레드 sleep"은 원시적이지만 고빈도 업로드에는 실제로 유효하다. 적용 범위를 숨기지 않고 말하는 것이 근거 없이 그럴듯한 방안보다 신뢰할 수 있다.
- 시간 시계열의 신선도 문제와는 트리거가 다르다 — 일시정지 후 재개 시의 신선도 검증(문서 53)은 "시간이 오래 지났으니 외부 세계가 변했을 것"을 전제로 재확인하는 것이고, 이 문서의 문제는 일시정지 없이 방금 쓴 데이터를 곧바로 읽으려 할 때 생기는 인덱스 지연이다. 트리거 조건과 임계값 설계가 다르므로 같은 신선도 검증 로직을 그대로 재사용할 수 없다.
엔지니어링 실전 Tips
- "입고 완료"와 "인덱스 생효"를 별개 이벤트로 취급할 것 — 장애 대응 시 두 시점을 각각 확인하고 그 사이 간격부터 살핀다.
- 지연 임계값은 하드코딩하지 말고 설정값으로 둘 것 — 벡터 저장소 종류와 파일 크기에 따라 실제 인덱스 구축 시간이 크게 달라진다.
- 강등 스위치는 핵심 업무 경로 단위로 걸 것 — 전역 스위치가 아니라 중요 고객 전용 조회 같은 고가치 경로에만 건다.
- 타임스탬프 검증은 양방향으로: 파일 측(버전·입고 시각)과 요청 측(사용자 업로드 시각) 둘 다 실어야 "검색 결과가 낡았다"는 결론을 낼 수 있다.
- 원문 보완과 컨텍스트 전환은 서로 다른 대응이다 — 전자는 검색 결과에 원문을 덧붙이는 것, 후자는 검색 자체를 포기하고 컨텍스트로 바꾸는 것. 파일 크기와 창 여유에 따라 선택지가 갈린다.
- 세션 캐시는 정확성이 아니라 중복 검색 비용을 줄이는 용도다 — 같은 세션 내 같은 파일의 반복 검색을 막는 것이지, 첫 검색의 정확성을 보장하는 수단이 아니다.
- 비용과 정확성의 취사선택을 미리 문서화할 것 — "Token을 더 써도 데이터 정확성을 우선한다"처럼 명시적으로 입장을 정해 두면, 강제 주입 스위치를 어디에 걸지 판단이 흔들리지 않는다.