레시피 목록

토큰 아끼는 법을 검색하다가, 내가 얼마 쓰는지도 모른다는 걸 깨달았다

2026년 8월 12일 7분 읽기
AI오픈소스

요즘 유튜브와 기술블로그를 보면 AI 토큰 이야기가 빠지질 않습니다. "컨텍스트를 아껴라", "프롬프트를 짧게 써라", "서브에이전트로 분리해라". 그런 글들을 읽으면서 저도 토큰을 얼마나 사용하고 있는지 궁금해졌습니다.

이번 글은 Claude Code 사용량 추적기 tokkaebi를 만들며 알게 된 것들을 정리합니다. 도구 소개보다는, 만들면서 마주친 데이터의 함정과 그걸 파헤치는 과정이 중심입니다.

  1. 내 사용량은 이미 내 컴퓨터에 있었다
  2. 로그를 그대로 더하면 2.4배 뻥튀기된다
  3. 캐시 읽기 2억 8천만 토큰의 정체 — 프롬프트 캐싱 딥다이브
  4. 줄이기 전에, 먼저 측정

1. 내 사용량은 이미 내 컴퓨터에 있었다

처음에는 사용량을 어디서 구해야 하나 막막했습니다. Anthropic 콘솔? 훅을 심어서 직접 기록? 그런데 알고 보니 데이터는 이미 전부 제 컴퓨터에 있었습니다.

Claude Code는 모든 세션을 ~/.claude/projects/ 아래에 JSONL 파일로 남깁니다. 한 줄이 하나의 이벤트고, 그중 어시스턴트 응답 줄에는 이런 정보가 들어 있습니다.

json
{
  "type": "assistant",
  "timestamp": "2026-08-11T10:45:15.370Z",
  "cwd": "/Users/me/dev/my-project",
  "gitBranch": "feat/login",
  "message": {
    "model": "claude-fable-5",
    "usage": {
      "input_tokens": 2,
      "output_tokens": 1938,
      "cache_read_input_tokens": 16177,
      "cache_creation_input_tokens": 19488
    }
  }
}

모델명, 토큰 4종, 시각, 심지어 어떤 프로젝트의 어떤 git 브랜치에서 작업했는지까지 다 있습니다. 제 머신을 뒤져보니 파일 265개, 총 135MB. 한 달 반치 기록이 고스란히 쌓여 있었습니다.

처음엔 간단한 생각으로 모든 응답을 읽어서 usage를 합산하면 끝 아닌가 했습니다.

하지만 끝이 아니었습니다.

2. 로그를 그대로 더하면 2.4배 뻥튀기된다

구현 전에 실제 로그를 전수조사하다가 이상한 걸 발견했습니다. 어시스턴트 레코드가 17,229건인데, 요청 ID(requestId)를 중복 제거하면 7,246건밖에 안 되는 겁니다.

같은 요청 ID를 가진 레코드들을 나란히 놓고 보니 이유가 보였습니다.

code
uuid 333c...  내용: [thinking 블록]   usage: input 2, output 1424, ...
uuid 119a...  내용: [tool_use 블록]   usage: input 2, output 1424, ...   ← 완전히 동일
uuid 6ea8...  내용: [text 블록]       usage: input 2, output 1424, ...   ← 완전히 동일

Claude의 응답 하나는 여러 조각(생각, 도구 호출, 본문 텍스트)으로 이루어지는데, Claude Code는 이걸 조각마다 한 줄씩 기록합니다. 문제는 각 줄에 응답 전체의 usage가 통째로 복사됩니다. 즉, 10조각짜리 응답이면 같은 토큰 수가 10번 적혀 있는 겁니다.

로그에 적힌 숫자를 그대로 믿고 더하면, 실제보다 약 2.4배 많이 쓴 것으로 계산됩니다.

해결은 요청 ID 기준으로 첫 레코드만 세는 것입니다. 그리고 정말 제대로 셌는지 확인하려고, 제 파서를 전혀 거치지 않는 독립 검증을 붙였습니다. jq로 원본 로그에서 직접 고유 요청 수를 세서 DB의 레코드 수와 비교하는 거죠.

bash
$ find ~/.claude/projects -name '*.jsonl' | xargs cat \
    | jq -r 'select(.type=="assistant") | .requestId' | sort -u | wc -l
7360

$ sqlite3 ~/.tokkaebi/data.db "SELECT COUNT(*) FROM usage_records;"
7360

3. 캐시 읽기 2억 8천만 토큰의 정체 — 프롬프트 캐싱 딥다이브

파서를 완성하고 처음 하루치 사용량을 출력했을 때, 처음엔 숫자에 오류가 있는 줄 알았습니다.

code
모델            입력    출력      캐시 읽기    캐시 쓰기    비용
claude-fable-5   372   216,724   28,468,974   1,203,107   $62.36

입력이 372 토큰인데 캐시 읽기가 2,846만? 비율로 따지면 캐시 읽기가 입력의 7만 배가 넘습니다. 처음엔 제 파서가 또 뭘 잘못 세는 줄 알았는데, 파고들어 보니 이게 정상이었습니다.

LLM API는 매번 처음 만나는 사이다

LLM API는 대화를 기억하지 않습니다. 서버에 "지난번에 하던 얘기 이어서"라는 개념이 없죠. 그래서 우리는 세션을 사용하되, 대화가 이어지는 것처럼 보이려면, 클라이언트가 매 요청마다 지금까지의 대화 전체를 처음부터 다시 보내야 합니다.

Claude Code로 한 시간쯤 작업했다 가정했을때. 매 턴마다 서버로 다음이 날라갑니다.

  • 시스템 프롬프트 (Claude Code의 동작 규칙 — 수만 토큰)
  • 도구 정의 (파일 읽기, 편집, 터미널 실행… 각각의 명세)
  • 지금까지의 대화 전부 — 내가 한 말, Claude의 답, 그리고 Claude가 읽은 파일 내용과 터미널 출력까지 전부

마지막 항목이 제일 중요합니다. Claude가 코드 파일을 하나 읽을 때마다 그 내용이 대화 기록에 쌓이고, 이후 모든 턴마다 다시 전송됩니다. 한 시간짜리 세션이면 매 턴의 입력이 수십만 토큰까지 불어나는 게 보통입니다.

이걸 매번 정가로 계산하면 어떻게 될까요? 제 하루 기록으로 셈해보면, 캐시로 처리된 2,846만 토큰이 전부 정가 입력이었을 경우 하루 $305가 나옵니다. 한 달이면 9천 달러. 말도 안 되는 가격이죠.

서버가 "앞부분"을 기억해주는 거래

그래서 프롬프트 캐싱이 있습니다. 아이디어는 단순한 거래입니다.

"방금 처리한 프롬프트의 앞부분을 서버가 잠시 보관해줄게. 다음 요청에서 앞부분이 완전히 똑같으면, 그 부분은 다시 처리하지 않고 이어서 갈게. 대신 보관비를 조금 받고, 재사용할 때는 정가의 10%만 받을게."

여기서 중요한 건 "앞부분(prefix)"이라는 조건입니다. 캐시는 프롬프트의 앞에서부터 바이트 단위로 정확히 일치하는 구간에만 적용됩니다. 대화는 항상 뒤에만 붙으니까 이 구조와 완벽하게 맞물립니다.

code
1번째 요청:  [시스템 프롬프트][도구 정의][대화 A]
                                              → 전체를 처리하고 캐시에 저장 (쓰기)

2번째 요청:  [시스템 프롬프트][도구 정의][대화 A][대화 B]
             └────────── 캐시에서 읽음 (10%) ─────────┘└─ 새로 처리 ─┘

3번째 요청:  [시스템 프롬프트][도구 정의][대화 A][대화 B][대화 C]
             └────────────── 캐시에서 읽음 (10%) ──────────────┘└─ 새로 처리 ─┘

이제 아까 그 이상한 숫자가 읽힙니다. 하루 동안 입력 372 / 캐시 읽기 2,846만이라는 건:

  • 정가로 새로 처리한 토큰은 딱 372개 — 매 턴 내가 새로 친 메시지 정도
  • 나머지 2,846만 토큰은 전부 "누적된 대화의 재전송분" — 캐시가 받아냄

턴이 거듭될수록 대화가 길어지니 캐시 읽기는 눈덩이처럼 커집니다. 그러니까 캐시 읽기 항목은 "뭔가 이상한 숫자"가 아니라, 캐시가 없었다면 정가로 청구됐을 트래픽을 보여주는 항목인 겁니다.

한 가지 주의점도 있습니다. 앞부분이 1바이트라도 달라지면 그 지점부터의 캐시는 전부 무효가 됩니다. 예를 들어 시스템 프롬프트에 현재 시각 같은 걸 박아 넣으면 매 요청의 앞부분이 달라져서 캐시가 한 번도 안 먹습니다. LLM 응용을 직접 만들 때 "변하는 값은 프롬프트 뒤쪽에" 배치하라는 이유가 이것입니다.

5분 캐시와 1시간 캐시 — 보관비의 차이

그럼 "캐시 쓰기"는 뭘까요? 서버에 보관을 맡기는 비용, 즉 보관비입니다. 그리고 보관 기간에 따라 요금이 다릅니다.

항목단가 (입력 정가 대비)fable-5 기준 ($/100만 토큰)
입력 (정가)100%$10.00
캐시 읽기10%$1.00
캐시 쓰기 (5분 보관)125%$12.50
캐시 쓰기 (1시간 보관)200%$20.00

쓰기가 정가보다 비싼 게 눈에 띄죠. 캐시에 넣는 순간에는 오히려 손해입니다. 따라서 캐시를 자주 사용하는 환경이어야 경제적입니다. 쓰기는 한 번이지만 읽기는 재사용할 때마다 발생하니, 두세 턴만 이어져도 본전을 뽑고 그 뒤로는 전부 절감입니다.

5분과 1시간의 차이는 "대화 사이의 공백을 얼마나 버티느냐"입니다. 5분 캐시는 잠깐 자리를 비우면 증발하지만, 1시간 캐시는 코드를 읽고 고민하는 긴 공백에도 살아남습니다. 제 로그를 집계해보니 쓰기의 56%가 5분, 44%가 1시간 캐시였습니다. Claude Code가 상황에 따라 두 캐시를 섞어 쓰고 있다는 뜻인데, 로그의 usage에는 이 둘이 합산된 필드와 분리된 필드가 둘 다 들어 있어서, 모르고 두 필드를 다 더하면 쓰기 비용이 2배로 계산되는 함정도 있었습니다.

그래서, 얼마나 아꼈나

이제 절감액은 아래 식으로 계산할 수 있습니다.

code
캐시 절감 = 캐시읽기 × (정가 − 읽기단가) − 캐시쓰기 비용

제 최근 12주 데이터로 돌려보면:

code
$ tokkaebi cache

캐시 분석 · 최근 12주

  히트율      99.9%  (캐시 읽기 1,280,764,264 / 신규 입력 823,242)
  쓰기 비중   5분 56% · 1시간 44%
  순절감      $9,186.25  (읽기 절감 $9,456.04 − 쓰기 프리미엄 $269.78)

12주간 캐시로 흘려보낸 토큰이 12억 8천만 개. 캐시가 없었다면 약 9,500달러를 더 냈어야 했고, 보관비로 270달러를 지불한 대가로 9,186달러를 아꼈습니다. 제가 실제로 낸 비용의 몇 배를 캐시가 대신 막아주고 있던 셈입니다.

4. 줄이기 전에, 먼저 측정

완성된 tokkaebi는 이렇게 생겼습니다.

code
$ tokkaebi today

오늘 사용량 · 2026-08-11 (화) · $87.27

모델별
┌────────────────┬───────┬─────────┬────────────┬───────────┬────────┬──────────┐
│ 모델            │ 입력   │ 출력      │ 캐시 읽기    │ 캐시 쓰기   │ 비용    │          │
│ claude-fable-5 │ 2,316 │ 316,010 │ 44,645,376 │ 1,337,083 │ $86.88 │ ▮▮▮▮▮▮▮▮ │
│ claude-opus-5  │    28 │      35 │    329,533 │    36,817 │  $0.40 │ ▮▯▯▯▯▯▯▯ │
└────────────────┴───────┴─────────┴────────────┴───────────┴────────┴──────────┘

프로젝트 · 브랜치별
│ tokkaebi      │ main              │ ... │ $43.14 │ ▮▮▮▮▮▮▮▮ │
│ guksu-trading │ fix/ops-hardening │ ... │ $12.69 │ ▮▮▯▯▯▯▯▯ │

💰 캐시 절감  $390.21  — 캐시가 없었다면 오늘 $477.48
🧌 연속 사용  2일째
  • 어떤 프로젝트의 어떤 브랜치가 돈을 먹는지, 서브에이전트와 스킬별 비용까지 나옵니다
  • 요일×시간대 히트맵을 찍어보니 저는 새벽형이 아니라 목요일 오후형이더군요
  • 월 예산을 설정하면 "이 속도면 월말 $312" 같은 페이스 예측이 붙습니다
  • 데이터는 전부 로컬 SQLite에만 저장됩니다. 프롬프트 원문은 저장하지 않고, 외부 전송도 없습니다

설치는 한 줄입니다.

bash
npm install -g tokkaebi
tokkaebi today

훅이 아니라 원본 로그를 읽는 방식이라, 오늘 설치해도 설치 전 과거 기록까지 소급해서 집계됩니다. Claude Code는 기본 30일이 지난 로그를 지우는데, tokkaebi는 수집한 기록을 자체 DB에 보존하므로 꾸준히 쓰면 30일 너머의 이력도 남습니다.


코드는 다음에서 확인 가능합니다: github.com/Guksu/tokkaebi