본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 03. 23:10

캐시 히트율 (Cache Hit Rate)의 진짜 의미를 알기 전까지, 나의 일일 토큰 소모량은 나를 갉아먹고 있었다

요약

DeepSeek API 사용 시 프롬프트 캐싱(Prompt Caching)을 최적화하여 토큰 비용을 획기적으로 절감한 경험담입니다. 정적 컨텍스트를 프롬프트 앞부분에 배치하는 구조적 개선을 통해 캐시 히트율을 높이는 방법을 다룹니다.

핵심 포인트

  • 프롬프트 구조화: 정적 블록(시스템 프롬프트, 도구 정의)을 가변적 입력보다 앞에 배치해야 함
  • 캐시 히트율의 중요성: 캐시 히트가 발생하면 토큰 비용을 최대 1/10 수준으로 절감 가능
  • 검증 자동화: pytest를 활용해 캐시 히트 지표가 임계값을 넘는지 테스트하는 과정 권장

2026년 4월 24일. 오늘 아침, 나는 스프레드시트와 원래는 저렴해야 했지만 왠지 모르게 6달러나 주고 마시게 된 커피 한 잔을 앞에 두고 앉아, 지난 3주 동안의 DeepSeek 청구서를 일별로 기록하기 시작했다.

상태는 심각했다. 정말이지 내 자신에게 화가 날 정도로 심각했다.

모델을 호출할 때마다 매번 API를 새로 호출하고 있었다. 모든 프롬프트 템플릿 (Prompt Template), 모든 시스템 메시지 (System Message). 내 스웜 (Swarm) 내의 모든 봇이 똑같은 상용구 (Boilerplate)를 반복해서 실행하며, 매번 전체 비용을 지불하고 있었다. 나는 다음 봇을 출시하고, 다음 경로를 만들고, 누군가가 실제로 돈을 지불할 만한 다음 작은 기능을 만드는 데 너무 집중한 나머지, 내 돈이 어디로 새어나가고 있는지는 전혀 살펴보지 못했다.

이 모든 일을 시작했을 때, 나에게는 노트북 한 대와 이메일 계정, 그리고 소셜 미디어뿐이었다. API 키 (API Key)가 무엇인지도 몰랐다. '토큰 (Token)'이라는 단어를 처음 봤을 때는 오락실 기계에 넣는 작은 동전 같은 것이라고 생각했다. 6주 전이라면, 누군가 나에게 캐시 히트율 (Cache Hit Rate)에 대해 물었을 때, 나는 그것이 Starbucks에서 아침 혼잡 시간 동안 측정하는 무언가라고 추측했을 것이다.

그래서 오늘 나는 화가 났다. 그리고 바로 작업을 시작했다.

DeepSeek에는 프롬프트 캐싱 (Prompt Caching) 기능이 있다. 문서에 내내 적혀 있었던 내용이다. 정적인 부분(시스템 프롬프트 (System Prompt), 도구 정의 (Tool Definitions), 길고 지루한 컨텍스트 (Context))이 먼저 오고, 가변적인 부분(호출마다 변하는 실제 사용자 입력)이 마지막에 오도록 프롬프트를 구조화하면 된다. 그러면 제공업체는 접두사 (Prefix)를 해싱 (Hash)한다. 만약 이것이 최근 호출과 일치하면, 해당 토큰들에 대해 비용의 아주 일부만 지불하면 된다. 때로는 10분의 1 수준이다.

나는 프롬프트를 정반대 순서로 작성해 오고 있었다. 가변적인 쓰레기들을 앞에 두고, 정적인 블록을 맨 아래에 두었다. 내 컬렉션에 있는 모든 봇의 캐시 히트율 (Cache Hit Rate)은 기본적으로 0이었다. 말 그대로 전혀 변하지 않는 콘텐츠에 대해 매 호출마다 전체 가격을 지불하고 있었던 것이다.

나는 프롬프트 빌더 (Prompt Builder)를 다시 작성했다. 27개의 모든 봇이 사용하는 단 하나의 함수다. 정적인 시스템 블록을 맨 앞에, 그다음 도구 스키마 (Tool Schemas), 그다음 엄격한 차단 지점이 있는 롤링 컨텍스트 윈도우 (Rolling Context Window), 그리고 맨 마지막에 사용자 턴 (User Turn)이 오도록 했다. 이 작업에는 약 3시간과 나 자신을 향한 수많은 욕설이 필요했다.

그다음 저는 pytest를 작성했습니다. 총 12개였습니다. 각각의 테스트는 서로 다른 봇으로부터 대표적인 호출을 발생시키고, 응답 메타데이터 (Response Metadata) 내의 캐시 히트 (Cache Hit) 지표가 특정 임계값 이상인지 확인합니다. 12개 중 11개는 86% 이상의 수치로 깨끗하게 통과했습니다. 12번째 테스트는 호출마다 컨텍스트 (Context)가 실제로 변하는 인텔 봇 (Intel Bot) 중 하나이기에, 이번 주말에 그 부분은 구조를 다르게 다시 짜볼 생각입니다.

새 버전을 오늘 발생한 트래픽에 적용하여 4시간 동안 실행하며 대시보드 (Dashboard) 상의 소모율 (Burn Rate)을 지켜보았습니다. 떨어졌습니다. 조금이 아니라 아주 많이요. 믿기지 않아서 페이지를 세 번이나 새로고침하게 되는 그런 수준의 하락이었습니다.

저는 아직 배우는 중입니다. 이 글을 읽는 시니어 개발자 (Senior Dev)라면 제가 캐시 키 (Cache Keys)를 구성한 방식에서만 열 가지의 아마추어 같은 실수를 찾아낼 것입니다. 일부 호출은 배치 (Batching) 처리를 해야 한다는 것도 알고 있습니다. 비용이 많이 드는 추론 (Reasoning) 단계 이전에 분류 (Classification) 단계를 위해 더 작은 모델을 사용해야 한다는 것도 알고 있습니다. 아마 제가 이름조차 들어보지 못한 최적화 (Optimization) 단계가 통째로 존재할지도 모릅니다.

하지만 오늘 저는 약 6시간의 집중적인 작업을 통해 분노에서 안도로 바뀌었고, 저는 매 순간 기꺼이 이런 거래를 할 것입니다.

이 이야기의 솔직한 버전은, 저에게 가장 많은 비용을 발생시키던 요소를 최적화하기 전에 이미 27개의 봇을 출시했다는 것입니다. 제가 작업한 순서가 바로 그랬습니다. 먼저 출시하고, 청구서를 확인하고, 패닉에 빠진 다음, 수정하는 것 말입니다. 제가 처음부터 똑똑하게 계획했다고 거짓말하지는 않겠습니다.

이 글을 쓰는 동안 누군가 세이프티 팩 (Safety Pack) 결제를 보냈습니다. 그것들은 마치 동전처럼 조금씩 쌓입니다. 이제는 제가 더 많이 챙길 수 있게 된 동전들 말이죠.

병렬로 수많은 LLM 호출을 실행하고 있는 다른 분들에게 묻고 싶습니다. 여러분이 6주 차가 아닌 1주 차에 발견했더라면 좋았을 최적화 (Optimization) 요소는 무엇인가요?

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0