LLM 에이전트에게 긴 작업을 맡기면, 모델은 추론하고 도구를 부르고 그 응답을 받는 일을 수백 번 반복한다. 이 과정에서 생기는 모든 텍스트 — 프롬프트, 모델이 쓴 메시지, 도구가 돌려준 결과 — 를 매번 처음부터 다시 계산하면 느리고 비싸다. 그래서 서빙 시스템은 KV 캐시를 쓴다. 앞서 읽은 내용을 다시 계산하지 않으려고 저장해 둔 중간 계산값이다. 문제는 작업이 길어질수록 이 캐시가 끝없이 불어난다는 데 있다. 칭화대 연구진의 측정으로는, 이 캐시를 읽는 비용이 전체 API 비용의 82.4%를 차지했다(Figure 14).
비용만 문제가 아니다. 모델이 한 번에 안정적으로 다룰 수 있는 토큰 수에는 한계가 있다. 참조할 캐시가 너무 많아지거나, 토큰이 몇 번째 자리인지 알려 주는 번호(위치 인코딩)가 너무 멀리까지 벌어지면 성능이 꺾인다. 작업 기록이 모델의 최대 입력 길이를 넘어서면 아예 실행이 멈춘다.
지금까지의 해법은 대화 기록 자체를 줄이는 것이었다. 오래된 메시지를 잘라내거나, 요약본으로 바꿔 끼운다. 그런데 여기엔 숨은 비용이 있다. 기록의 앞부분을 건드리는 순간, 그 뒤에 쌓여 있던 캐시가 전부 무효가 된다. 캐시는 "앞 토큰이 이러이러했다"를 전제로 만든 값이라, 앞이 바뀌면 뒤를 다시 계산해야 한다. 그래서 실무의 하네스(에이전트의 실행을 관리하는 프로그램)는 한계에 닿을 때까지 버티다가, 어느 순간 크게 요약·삭제하고 최근 몇 라운드만 남긴다. 최근 것만 남기면 중간의 쓸모 있는 정보가 날아가고, 많이 남기면 다시 계산할 양이 커진다. 비용과 정보 사이의 맞교환이다.
칭화대 연구진은 이 맞교환을 피했다. 대화 기록은 손대지 않고, 모델이 참조하는 캐시만 직접 버리는 방식이다. 그리고 놀랍게도, 요약하는 쪽보다 비용이 쌌고 정확도는 오히려 더 높았다.
연구진이 "캐시 엔지니어링"이라 부른 발상은 단순하다. 무엇을 기억에서 뺄지는 에이전트와 하네스가 정하고, 서버는 그 결정을 실제 캐시에서 실행한다. 지금까지의 캐시 관리가 토큰 위치나 어텐션 점수 같은 저수준 신호에 맡겨졌던 것과 달리, 결정권이 작업 맥락을 아는 쪽으로 올라온다.
이 문제를 다루는 기존 연구는 크게 셋이다. 텍스트 수준의 컨텍스트 엔지니어링(요약·트림), 캐시 수준의 압축·축출·재사용(저랭크 표현, 양자화, 토큰 위치나 어텐션 중요도 기반 축출, 위치 인코딩 조정을 통한 재사용), 서빙 시스템 수준의 캐시 공유·스케줄링(접두어 캐싱 등). 앞의 둘은 버리고 재사용하는 결정을 토큰 위치나 어텐션 점수 같은 저수준 신호에 맡겼고, 접두어 캐싱은 "같은 접두어 = 같은 캐시"라는 등식 위에 선다.
여기서 '버린다'의 뜻을 분명히 해야 한다. 캐시를 버려도 원문 기록은 남는다. 다만 다음 답변을 계산할 때 모델이 직접 참조하는 중간 계산값에서 일부를 빼는 것이다. 기록을 보관하는 것과, 모델이 그 내용에 바로 접근하는 것은 다른 일이다.
구체적으로 연산 두 개를 새로 정의한다.
reposition이 따로 필요한 이유가 있다. 자리 번호는 캐시를 비워도 작업을 따라 계속 커진다. drop으로 캐시를 아무리 줄여도 다음 토큰의 자리 번호는 리셋되지 않아, 캐시는 작은데 번호만 모델 한계까지 치솟는 일이 생긴다. reposition은 자리 번호를 캐시 크기에서 떼어내 이를 막는다.
RoPE(회전 위치 임베딩)는 토큰의 자리를 키와 쿼리를 일정 각도로 회전시켜 표현한다. 자리를 옮기려면 키의 회전 각도만 바꾸면 되고, 저장해 둔 값(value)은 회전 대상이 아니라 그대로 복사한다. 덕분에 숨은 상태를 다시 계산하지 않고 위치만 조정할 수 있다.
drop에는 한 가지 성질이 있다. 오래된 기억을 버려도, 남긴 캐시는 그 기억이 살아 있을 때 계산된 값이다(Figure 1). 버린 정보의 영향이 남은 캐시에 이미 배어 있다는 뜻이다.
어느 기억을 남길지는 데이터에서 나왔다. 어텐션 분포를 보니 오래된 토큰은 최근 토큰보다, 도구 응답은 같은 위치의 모델 추론 메시지보다 어텐션을 덜 받았다. 그래서 기본 정책은 "도구 응답 롤링 드롭"이다. 모든 추론과 최근 도구 응답은 남기고, 오래된 도구 응답 캐시부터 밀어낸다.
핵심부터. 세 모델과 네 벤치마크 평균에서, 이 도구 응답 롤링 드롭은 통상적인 임계값 요약 방식 대비 평균 비용을 27.7% 줄이고 벤치마크 점수를 평균 1.7점 높였다. 비용과 정확도 중 하나를 깎지 않고 둘 다 좋아졌다.
비교는 오히려 드롭에 불리하게 맞췄다. 베이스라인은 에이전트 하네스가 흔히 쓰는 요약 기반 방식 둘(Standard, 그리고 임계값만 48K로 낮춘 Text Engineering)이고, 드롭 쪽 비용은 캐시 적중 요율로 과금해 자리 번호를 다시 매기는 비용을 일부러 크게 잡았다. 모델 규모와 임계값, 요율 같은 세부는 아래 표와 심화 상자에 모았다.
| 구분 | 설정 |
|---|---|
| 모델 | MiniMax-M2.7(230B 전체, 10B 활성) · GPT-OSS-120B(높은 추론 강도) · MiroThinker-1.7-Mini(사고 모드) |
| 벤치마크 | BrowseComp-Plus(BCP) · xbench-DeepSearch-2510 · GAIA-Text(103-task 검증 부분집합) · SWE-Verified |
| 지표 | 성공률(pass rate) · 작업당 평균 API 비용(센트) |
• 요율: GPT-OSS-120B는 Groq 요율, MiniMax-M2.7은 공식 요율, MiroThinker-1.7-Mini는 베이스 모델 Qwen3-30B-A3B 요율.
• Standard 임계값: GPT-OSS-120B·MiniMax-M2.7 = 96K 토큰, MiroThinker-1.7-Mini = 192K 토큰. Text Engineering = 48K.
• AKV 정책: 최근 12개 도구 응답의 KV만 남기는 도구 응답 롤링 드롭, 임계값은 각 모델의 Standard와 동일.
• 서빙 효율 지표: 요청 지연, TTFT(첫 토큰까지 시간), TPOT(출력 토큰당 시간), 입출력 처리량.
• 서빙 실험: A800-80GB GPU 8장(prefill 4 + decode 4, 텐서 병렬 4), BF16.
세부는 GPT-OSS-120B를 BrowseComp-Plus 첫 100개 과제(과제당 4회 시도, 최대 100라운드)에 돌린 분석이 선명하다.
관측된 사실은 분명하다. 같은 비용대에서 드롭이 요약보다 점수가 높았다. 왜 그런지에 대한 저자의 설명은 가설에 가깝다. 요약은 중간 정보를 통째로 날리지만, 드롭은 남긴 캐시가 버린 정보의 영향을 품고 있다는 것이다. 성능 차이를 실험으로 분리해 확인한 결과는 아니다. 그래서 답이 도구 응답 안에 들어 있던 과제 — 과거의 숫자나 제약을 그대로 다시 꺼내 써야 하는 경우 — 에서도 이 이점이 유지되는지는 아직 열린 질문이다.
이 방식은 서빙 시스템의 오랜 가정 하나를 깬다. 보통은 앞 토큰이 같으면 캐시도 같다. 그래서 같은 접두어를 가진 요청끼리 캐시를 안전하게 나눠 쓸 수 있었다. 그런데 캐시 엔지니어링에서는 같은 텍스트라도 어느 시점에 무엇을 버렸느냐에 따라 캐시 값이 달라진다. Figure 5가 그 예다. 궤적 ①과 ②가 모두 B·C의 KV를 남기지만, ①은 C를 계산할 때 A가 살아 있었고 ②는 C를 계산하기 전에 A를 버렸다. 토큰 B·C는 같아도 C의 캐시 값은 다르다. 접두어만 봐서는 캐시를 올바로 재사용할 수 없고, 토큰 이력과 캐시 연산 이력을 함께 추적해야 한다. 논문은 이를 "역사 의존성(history dependence)"이라 부른다.
이 복잡성을 감당하려고 설계한 서빙 엔진이 AKV다. 원칙은 "무상태 인터페이스, 유상태 서빙"이다. 에이전트는 메시지와 캐시 연산 지시만 보내고, 꼬인 상태 관리는 서버가 안에서 떠안는다. 그 안에서 세 가지를 지킨다. 연산 이력이 다른 캐시를 잘못 재사용하지 않도록 확장 래딕스 트리로 drop 시점이 다른 가지를 구분하고, 아직 다른 요청이 쓸 수 있는 캐시를 함부로 비우지 않도록 drop 인식 축출로 회수 시점을 늦추며, 메모리가 빠듯해 캐시가 밀려났다 다시 필요해지면 세그먼트-배치 어텐션으로 한 번의 prefill에 복원한다. 그만큼 서빙 엔진이 떠안는 복잡성은 커졌다. 대신 AKV 서버를 붙이면 이 정책은 출력 처리량을 최대 1.2배로, P95 요청 지연을 1.5배 빠르게 했다.
기존 API 기반 서빙과 호환되도록 설계됐다. messages 필드가 전체 논리 토큰 시퀀스를 주고, 선택적 cache 필드가 drop·reposition을 "연산 적용 지점(operate-after)" 문법으로 지정한다. 에이전트는 어떤 KV가 서버에 남아 있는지 추적할 필요 없이 메시지와 연산 지시만 보내고, 상태 관리는 서버가 안에서 처리한다.
prefill은 앞 토큰 전체를 한 번에 계산해 캐시를 채우는 단계다. 보통의 인과적(causal) prefill은 "뒤 토큰이 앞 토큰을 본다"는 한 방향 규칙만 따라, 중간 일부를 버린 상태를 그대로 재현하지 못한다. 세그먼트-배치 어텐션은 쿼리를 drop 지점에서 토막 내, 각 토막이 자기 토큰과 "이전 토막의 살아 있는 캐시"에만 어텐션하게 한다. 어텐션만 토막으로 쪼개고, FFN(각 토큰을 독립적으로 변환하는 신경망 층)은 전체를 한 배치로 처리해 가중치를 다시 읽는 비용을 피한다.
캐시 연산은 프로그램처럼 조합할 수 있다. 그래서 에이전트가 자기 캐시 정책을 스스로 탐색하고 평가하고 고치는 재귀적 자기개선(RSI)이 가능하다. RSI가 찾아낸 정책은 평가에 쓰지 않은(held-out) 과제에서 전문가가 손으로 설계한 정책보다 비용을 7.1% 더 줄였다. 이 7.1%의 비교 대상은 전문가 설계 정책이지, 앞의 27.7%와 같은 기준이 아니다.
저자들이 꼽은 한계는 방금 본 역사 의존성 그 자체다. 접두어만 보면 되던 단순함이 깨지면서, 서버는 토큰과 연산 이력을 함께 추적해야 한다. 확장 래딕스 트리와 세그먼트-배치 어텐션이 이를 감당하도록 설계됐지만, 기존 SGLang 위에 올린 구현이라 재현과 비교에는 좋아도 아무 상용 API 뒤에 바로 끼울 수 있는 건 아니다.
더 조심할 곳은 드롭 정책이 어디서나 통하느냐다. "최근 12개 도구 응답 보존"은 어텐션이 도구 응답을 덜 본다는 관찰에서 나온 합리적 기본값이다. 하지만 도구 응답에 결정적 사실이 담기는 작업 — 검색 결과 자체가 답인 딥리서치 같은 — 에서는 드롭이 오히려 해로울 수 있다. 과거 도구 응답의 숫자나 제약을 그대로 회수해야 하는 과제가 바로 그 실패 지점이다. RSI가 정책을 과제에 맞춰 다시 탐색하는 장치로 함께 제시된 것도 이 때문으로 읽힌다. 또 비용을 요율표로 계산했기 때문에, GPU를 직접 돌리는 환경과 외부 API로 과금되는 환경에서 체감 이득은 달라질 수 있다.
온틀의 AI PM이 한 프로젝트를 몇 주 동안 맡는다고 하자. 매일 작업 보드를 조회하고, 문서를 읽고, 담당자에게 상태를 묻는다. 그 사이 작업 기록은 끝없이 길어진다. 반복 조회한 보드 목록이나 문서 전문은 오래된 것부터 캐시를 줄여도 큰 문제가 없어 보인다.
문제는 그 틈에 섞인 결정적 제약이다. 이를테면 "이 기능은 특정 고객사 요청으로 보류"라는 3주 전 회의의 한 줄. 온틀에서 이 연구를 검증한다면, 비용이 얼마나 줄었는지가 아니라 세 가지를 평가 항목으로 삼아야 한다. 첫째, 오래 묵은 보류 사유를 PM이 근거와 함께 그대로 다시 꺼내는가. 둘째, 그 보류가 이후 번복된 결정과 뒤섞이지 않고 구분되는가. 셋째, 이 정확도를 지키면서 비용이 실제로 얼마나 줄어드는가. 도구 응답을 덜 본다는 관찰이 "제약은 버려도 된다"는 뜻은 아니기 때문이다.
상용 API를 쓰는 입장이라면,
서빙 엔진을 직접 운영한다면,
논문은 둘을 대안으로 놓고 비교한다. 다만 drop·reposition이 텍스트 기록을 건드리지 않으므로, 개념적으로 텍스트 수준 처리와 배타적이지는 않다. 발췌 범위에서 둘을 결합해 측정한 결과는 확인되지 않아 단정은 피한다.
발췌 범위에서 모델 재학습을 요구한다는 언급은 없다. drop은 캐시 항목을 이후 어텐션에서 빼는 조작이고, reposition은 키를 다시 계산하지 않고 위치 번호만 옮기는 조작이다. 둘 다 추론 시점에 캐시를 다루는 연산이다.
공개돼 있다. 코드 저장소는 https://github.com/thu-nics/AKV 이고, 베이스 서빙 시스템은 SGLang이다.