왜 메모리를 두 계층으로 나누는가

에이전트가 대화 맥락을 유지하려면 최근 발화를 빠르게 읽고 쓰는 저장소와 수백만 건의 지식을 검색하는 저장소가 함께 필요합니다. 이 둘을 하나로 합치면 지연 요구와 정합성 요구가 충돌합니다. Cloudflare Workers KV는 읽기 지연이 수 밀리초대인 키-값 캐시이고, Vectorize는 인덱스당 최대 1,000만 벡터를 검색하는 벡터 데이터베이스입니다. 두 저장소의 일관성 모델 차이를 초기에 합의해야 장애 대응이 쉬워집니다.

KV가 감수하는 60초의 대가

Cloudflare 공식 문서는 KV 쓰기가 같은 엣지 위치에서는 즉시 보이지만, 다른 지역에는 최대 60초 또는 get() 호출의 cacheTtl 값만큼 지연된 뒤 반영된다고 명시합니다. 더 까다로운 점은 "키 없음"이라는 부정 조회 결과도 그대로 캐시된다는 것으로, 방금 만든 키를 다른 리전에서 곧바로 조회하면 존재하지 않는 값으로 응답받을 수 있습니다.

Vectorize 인덱스의 규모와 한계

Vectorize는 인덱스당 최대 1,000만 벡터, 벡터당 최대 1,536차원(32비트)까지 지원하며, 메타데이터 필터는 인덱스당 10개, 벡터당 10KiB까지입니다. 문자열 메타데이터는 앞 64바이트까지만 필터링되므로 짧은 값을 앞쪽에 배치합니다. 인덱스 데이터는 스냅숏 단위로 불변이라 R2·Cloudflare 캐시 조회가 특히 빠릅니다.

현장 적용 가이드: 캐시와 벡터 인덱스를 함께 운영하는 법

설계 착수 전에 목표 지표부터 숫자로 고정합니다. 벡터 검색 p95 150ms 이내, 컨텍스트 캐시 히트율 80% 이상, 오래된 캐시로 인한 재질문 발생률 5% 이하가 기준선입니다. 세션 컨텍스트는 KV에 최근 2~3턴만 저장하고 전체 대화 이력은 D1·R2에 남겨 KV 값 크기와 60초 전파 지연의 영향 범위를 줄입니다.

가장 흔한 실패는 방금 갱신한 문서를 다른 리전 요청이 부정 조회 캐시 때문에 없는 것으로 처리하는 경우입니다. 쓰기 직후 같은 경로에서는 KV 대신 원본(D1·외부 API)을 우선 조회하는 우회 분기를 두고, 60초가 지난 뒤에만 캐시 경로로 전환합니다.

두 번째 실패는 임베딩 모델 교체로 기존 Vectorize 인덱스 차원과 새 임베딩 차원이 어긋나 삽입이 전량 실패하는 경우입니다. 인덱스 이름에 임베딩 버전을 포함시켜 두면 문제가 생겨도 이전 인덱스로 즉시 되돌릴 수 있고, 메타데이터 필터도 10개 한도 안에서 실제로 쓰는 필드만 선별해야 재구축을 반복하지 않습니다.

세 번째 실패는 유사도 점수가 낮은 문서까지 컨텍스트에 밀어 넣어 환각을 유발하는 경우입니다. 임계값 미만 결과는 폐기하고, 남은 결과가 0건이면 "근거 부족" 안내로 답변을 안전하게 축약하는 분기를 둬야 합니다.

배포 전에는 KV 쓰기 직후 다른 리전 즉시 조회, 임베딩 버전 불일치 삽입, 메타데이터 필터 10개 초과라는 세 시나리오를 재현해 통과시킵니다. 로그에는 캐시 히트 여부, 조회 지연, 반환 벡터의 유사도 점수 분포, 사용한 인덱스 버전을 표준 필드로 남겨야 리전별 지연 편차를 바로 확인할 수 있습니다.

사용자 발화나 문서 원문이 메타데이터에 그대로 저장되지 않도록 필터링용 값만 추출해 저장하고 본문은 권한 검사를 거친 뒤 별도 스토리지에서 조회해 PII 노출 범위를 좁힙니다. 임베딩 교체·스키마 변경·캐시 정책 변경은 회귀 위험이 다르므로 이력을 분리해 남기고, 주간 단위로 부정 조회 오응답 건수와 임계값 미달 폐기 건수를 집계해 cacheTtl·임계값 조정 근거로 삼습니다.

한눈에 보는 적용 포인트

세션 컨텍스트는 KV에, 지식 검색은 Vectorize에 맡기되 두 저장소의 지연·한계를 숫자로 파악한 뒤 설계해야 합니다. 부정 조회 캐시와 임베딩 차원 불일치는 우회 분기와 버전 관리로 막고, 유사도 임계값 미만 결과는 안전 축약으로 처리하면 p95 150ms·캐시 히트율 80%라는 목표를 지키면서 에이전트가 오래된 답을 내놓는 상황을 줄일 수 있습니다.

참고 링크

How KV works — Cloudflare Workers KV docs

Limits — Cloudflare Vectorize docs