토큰 절약 팁을 모으다가, 로그를 열어 보고 순서를 바꿨습니다#

2026-10-25

램프가 비추는 나무 책상 위에서 작은 로봇이 끝없이 이어진 긴 두루마리를 힘겹게 밀고 있고, 사람의 손이 돋보기로 그 두루마리를 들여다보며, 로봇 옆에는 작게 접힌 메모 한 장이 놓여 있는 그림

팁은 넘쳐나는데, 무엇부터 해야 할까#

Claude Code와 Codex 같은 코딩 에이전트를 쓰는 사람들 사이에서 요즘 가장 자주 나오는 이야기 중 하나가 토큰 소비입니다. 구독 한도에 일찍 닿거나 API 비용이 예상보다 커지면서, 토큰을 아끼는 방법을 다룬 글이 쏟아지고 있습니다. 필자도 두 도구를 매일 쓰는 입장에서 이런 글들을 찾아 읽었습니다.

여러 글에 공통으로 나오는 팁은 대략 이렇습니다.

  • 관련 없는 작업 사이에는 /clear로 대화를 비운다
  • CLAUDE.md / AGENTS.md 같은 지침 파일을 짧게 유지한다
  • 일상 작업에는 더 저렴한 모델과 낮은 effort(추론에 쓰는 노력의 정도)를 쓴다
  • 쓰지 않는 MCP(Model Context Protocol, 에이전트에 외부 도구를 연결하는 규격) 서버를 끈다
  • 테스트 로그처럼 긴 출력은 걸러서 넣는다

틀린 말은 없습니다. 문제는 무엇부터 하느냐였습니다. 팁마다 “60–90% 절감”, “85% 절감” 같은 수치가 붙어 있었지만 대부분 서드파티 블로그나 도구 제작자의 측정이었고, 필자의 사용 패턴에서도 그럴지는 알 수 없었습니다. 그래서 적용하기 전에 두 도구가 로컬에 남기는 세션 로그를 직접 집계해 봤습니다.

결론부터 적으면 이렇습니다. 필자의 사용량을 키운 것은 소수의 아주 긴 세션이었습니다. 흔한 팁 중 일부는 필자에게 거의 효과가 없었고, 효과는 크지만 조건이 붙는 팁도 있었습니다. 이 글은 그 진단과, 그 결과로 세운 적용 계획의 기록입니다. 아직 적용 전이라 효과는 로그로 추정한 값입니다.

비용은 “컨텍스트 크기 × 호출 횟수"입니다#

에이전트는 요청을 보낼 때마다 대화 전체를 다시 보냅니다. 시스템 프롬프트, 지침 파일, 지금까지 주고받은 대화와 모든 도구 결과가 매번 실립니다. 에이전트가 파일을 하나 읽거나 명령을 하나 실행할 때마다 요청이 하나씩 늘어나므로, 비용은 대략 “그 시점의 컨텍스트 크기 × 호출 횟수"로 커집니다.

프롬프트 캐싱(이미 처리한 앞부분을 재사용하는 기능)이 이 부담을 크게 덜어 줍니다. 캐시에서 읽은 토큰은 기본 입력 단가의 일부만 받습니다. 다만 공짜는 아니어서, 대화가 길어지면 캐시 읽기도 함께 커집니다. 캐싱이 모델 안에서 무엇을 재사용하는지, 왜 히트율 자체는 목표가 아닌지는 이전 글에서 자세히 다뤘으므로, 여기서는 위의 등식 하나만 기억하면 충분합니다.

로그를 열어 보니#

Claude Code는 세션 기록을 ~/.claude/projects/ 아래에, Codex는 ~/.codex/sessions/ 아래에 JSONL(한 줄에 JSON 하나씩 담은 파일)로 남깁니다. 각 응답에는 그 요청에 쓰인 토큰 수가 입력, 캐시 읽기, 캐시 쓰기, 출력으로 나뉘어 기록되어 있어서, 짧은 스크립트로 집계할 수 있습니다. Claude Code라면 이 정도로 시작할 수 있습니다.

import collections, glob, json, os

total = collections.Counter()
for path in glob.glob(os.path.expanduser("~/.claude/projects/*/*.jsonl")):
    for line in open(path):
        try:
            record = json.loads(line)
        except json.JSONDecodeError:
            continue
        if record.get("type") != "assistant":
            continue
        usage = (record.get("message") or {}).get("usage") or {}
        for key in ("cache_read_input_tokens", "cache_creation_input_tokens", "output_tokens"):
            total[key] += usage.get(key) or 0

print(total)

Codex는 token_count 이벤트에 세션 누적 사용량이 담겨 있으므로, 세션마다 마지막 값을 읽으면 됩니다. 필자는 두 저장소를 봤습니다. 이 블로그 저장소(글쓰기 중심)와 코딩 비중이 높은 업무용 저장소입니다. 세 가지가 눈에 띄었습니다.

첫째, 소수의 긴 세션이 사용량 대부분을 차지했습니다. 블로그 저장소에서는 최근 24개 세션 중 하나가 전체 캐시 읽기의 약 3분의 1을 차지했습니다. 그 세션은 API 호출이 300번을 넘었고 컨텍스트가 60만 토큰대까지 커졌습니다. Codex도 같았습니다. Codex 사용량은 대부분 업무용 저장소에서 나왔는데, 그중 세션 하나가 전체 입력 토큰의 절반을 넘겼고 호출 횟수는 1,000번을 넘었습니다.

둘째, 업무용 저장소에서는 대화가 늘 컸습니다. Claude Code 기준으로 호출당 컨텍스트의 중앙값이 34만 토큰이었고, 상위 10%는 64만 토큰을 넘었으며, 최대 90만 토큰에 이르렀습니다. 100만 토큰 컨텍스트를 쓰는 모델은 기본 설정에서 약 96.7만 토큰이 되어야 자동 압축을 합니다. 필자는 대화가 그 근처까지 자라도록 내버려 두고 있었던 셈입니다.

셋째, 비용 구성이 저장소마다 달랐습니다. 토큰 종류마다 단가가 다르므로 Opus 5.5의 API 정가로 환산해 비중을 봤습니다. 필자는 구독으로 쓰고 있어서 실제 청구액과는 다르고, 한도를 어디에 쓰고 있는지 상대적인 크기를 가늠하는 용도입니다. 캐시 쓰기는 구독의 메인 대화에 적용되는 1시간 캐시 단가로 계산했습니다.

저장소캐시 읽기캐시 쓰기출력(추론 포함)
블로그(글쓰기 중심)약 21%약 50%약 29%
업무용(코딩 중심)약 50%약 31%약 19%

업무용 저장소는 대화가 크니 캐시 읽기가 절반을 차지했습니다. 블로그 저장소는 대화가 상대적으로 짧은 대신 캐시 쓰기 비중이 컸는데, 새로 들어오는 내용이 많았기 때문으로 보입니다. 이 저장소에서는 브라우저 스크린샷과 이미지 파일 읽기가 80번 넘게 있었고, 자리를 비웠다가 돌아와 큰 세션을 다시 이어간 일도 많았습니다. 캐시는 일정 시간 쓰지 않으면 만료되고, 만료 후 첫 요청은 대화 전체를 다시 캐시에 씁니다.

팁을 필자의 로그에 대 보니#

effort를 낮춰도 Codex에서는 거의 줄지 않습니다#

여러 글이 일상 작업에는 reasoning effort를 낮추라고 권하고, 40–60%를 절감한다는 수치를 붙이기도 합니다. 그런데 필자의 Codex 로그에서 출력과 추론 토큰을 합친 양은 입력 토큰의 0.5%에도 못 미쳤습니다. 입력의 대부분은 캐시에서 읽은 대화였습니다. 출력 단가가 캐시 입력보다 수십 배 비싸다는 점을 감안해도, 추론 토큰을 절반으로 줄여서 얻는 몫은 전체의 한 자릿수 퍼센트로 추정됩니다. effort가 의미 있는 곳은 출력 비중이 큰 작업이고, 필자의 Codex 사용은 그렇지 않았습니다.

Sonnet으로 바꾸면 절반이지만, 품질이라는 조건이 붙습니다#

모델 교체는 계산이 단순합니다. 공식 가격표에서 Sonnet 5.5는 기본 입력, 캐시 쓰기, 캐시 읽기, 출력 모든 항목이 Opus 5.5의 정확히 절반입니다. 두 모델 모두 캐시 읽기를 기본 입력 단가의 0.05배로 매기므로, 대화가 길어 캐시 읽기 비중이 큰 업무용 저장소에서도 절반이라는 비율은 그대로입니다.

모델(100만 토큰당, 2026-10 기준)기본 입력캐시 쓰기(1시간)캐시 읽기출력
Opus 5.5$4$8$0.20$20
Sonnet 5.5$2$4$0.10$10

같은 일을 같은 토큰으로 해낸다면, Sonnet 5.5로 바꿀 때 비용은 절반이 됩니다. 문제는 “같은 토큰으로 해낸다면"이라는 조건입니다. 작은 모델이 더 많은 턴을 쓰거나, 틀린 결과를 Opus가 다시 고쳐야 한다면 절감은 줄어듭니다. 모델 교체는 효과가 크지만 품질이라는 변수도 함께 움직이는 수단입니다.

팀 기능의 “7배"는 조건이 붙은 숫자였습니다#

Claude Code에는 여러 Claude 세션이 팀처럼 협업하는 실험 기능인 에이전트 팀이 있습니다. 공식 문서는 팀원이 plan 모드(실행하기 전에 계획부터 세우는 모드)로 돌면 일반 세션보다 약 7배 토큰을 쓴다고 설명합니다. 필자는 이 기능 플래그를 켜 두고 있었지만, 로그상 사용량을 키운 원인은 아니었습니다. 업무용 저장소의 서브에이전트 실행 324건 중 팀과 관련된 것은 2건뿐이었습니다. 7배는 팀이 실제로 구성되어 plan 모드로 돌 때의 이야기이고, 플래그를 켜 둔 것만으로 사용량이 늘지는 않습니다.

그래도 플래그는 끄기로 했습니다. 문서에 따르면 플래그가 켜진 상태에서 Claude가 서브에이전트에 이름을 붙여 실행하면, 요청하지 않아도 그것이 팀원으로 뜹니다. 둘의 차이는 이렇습니다.

항목서브에이전트팀원
수명일 하나를 끝내면 요약을 돌려주고 종료종료 요청을 받을 때까지 유지
소통메인에게만 결과 보고팀원끼리 직접 메시지, 공유 작업 목록
토큰메인 대화에는 요약 한 번만 추가메시지를 받을 때마다 자기 대화 전체를 다시 전송

필자의 작업은 대부분 범위가 분명한 위임이라 서브에이전트로 충분합니다. 팀은 여러 관점이 서로 반박해야 답이 나오는 일이 생길 때만 켜기로 했습니다.

브라우저 검증이 메인 대화에 쌓이고 있었습니다#

업무용 저장소에서는 에이전트가 로그인된 브라우저를 조작해 화면을 확인하는 일이 많습니다. 집계해 보니 브라우저 도구 호출 659번이 전부 메인 대화에서 일어났고, 서브에이전트에서는 한 번도 없었습니다. 이미지 160여 장이 메인 대화에 들어갔는데, 이미지는 한 번 들어오면 세션이 끝날 때까지 모든 요청에 실립니다.

하네스(에이전트에게 주는 규칙과 도구 구성)를 확인해 보니, 브라우저 작업을 서브에이전트에 맡기라는 규칙이 어디에도 없었습니다. “출력이 많은 작업은 서브에이전트에 위임하라"는 팁은 알고 있었지만, 필자의 하네스가 실제로 그렇게 동작하는지는 확인해 본 적이 없었습니다.

그래서 세운 순서#

순서는 “품질 위험이 낮고 효과가 큰 것부터"로 정했습니다.

1. 끝낸 세션은 그 자리에서 압축해 두기#

흔한 팁은 작업이 끝나면 /clear로 대화를 비우라는 것입니다. 필자는 조금 다르게 일합니다. 끝난 세션은 그대로 두고 새 일은 새 세션에서 시작합니다. 끝났다고 판단한 작업에 후속 작업이 생기는 일이 잦기 때문입니다. 열어 두기만 한 세션은 요청을 보내지 않으므로 토큰을 쓰지 않고, 비용 면에서 /clear와 새 세션은 같습니다.

남은 문제는 몇 시간 뒤 그 세션으로 돌아갈 때였습니다. 60만 토큰짜리 세션을 Opus 5.5 정가로 계산해 보면 차이가 큽니다.

  • 끝낸 직후, 캐시가 살아 있을 때 /compact: 캐시 읽기 약 0.12달러 + 요약 출력
  • 몇 시간 뒤 압축 없이 재개: 첫 요청에서 60만 토큰을 다시 캐시에 쓰는 데 약 4.8달러
  • 몇 시간 뒤 재개하면서 /compact: 요약 요청이 대화 전체를 캐시 없이 읽는 데 약 2.4달러 + 요약 출력

그래서 규칙을 이렇게 정했습니다. 작업을 끝내면 그 자리에서 /compact로 후속 작업에 필요한 것(변경한 파일, 결정 사항, 남은 이슈)만 남기고, 세션은 그대로 둡니다. AI 에이전트 시대의 컨텍스트 스위칭에서 정한, 떠나기 전에 재개 메모를 남기는 습관과도 잘 맞물립니다.

2. 자동 압축 임계값을 단계적으로 내리기#

Claude Code는 autoCompactWindow 설정으로 자동 압축이 일어나는 컨텍스트 크기를 정할 수 있습니다(10만–100만 토큰). 문제는 얼마로 두느냐였습니다. 100만 토큰 모델이 나오기 전의 기본값이던 20만 근처가 먼저 떠오르지만, 공식 문서는 권장값을 제시하지 않습니다. 웹에서도 100만 토큰 모델에 맞는 특정 숫자로 모인 의견은 찾지 못했고, 작업 단락마다 미리 압축하라는 조언이 주류였습니다.

그래서 로그로 시뮬레이션해 봤습니다. 실제 세션에서 컨텍스트가 늘어난 과정을 그대로 두고, 임계값을 넘는 순간 약 2.5만 토큰짜리 요약으로 줄어든다고 가정해 컨텍스트 총량을 다시 계산했습니다.

임계값업무용: 컨텍스트 총량업무용: 세션당 압축블로그: 컨텍스트 총량
70만−13%약 0.6회변화 없음
50만−27%약 2.4회−10%
40만−41%약 3.1회−10%
30만−50%약 5.7회−15%
20만−62%약 11.9회−26%

이 추정은 낙관적입니다. 압축 뒤 파일을 다시 읽는 비용, 압축 요청 자체의 비용, 세부 내용이 빠져서 생기는 재작업은 반영하지 않았습니다.

필자는 처음에 70만에서 시작해 조금씩 내릴 생각이었습니다. 그런데 표를 보니 70만을 넘는 호출은 전체의 7%뿐이어서, 효과도 작고 단계로서 얻는 정보도 적었습니다. 그래서 50만에서 시작해 1–2주 써 보고, 압축 뒤 맥락을 놓치는 일이 없으면 40만, 30만으로 내리기로 했습니다. 압축할 때 남길 것을 지침 파일의 # Compact instructions 섹션에 적어 두는 것도 함께 합니다. Codex에서는 model_auto_compact_token_limit이 같은 역할을 합니다.

3. 출력이 많은 실행 작업은 서브에이전트에게#

브라우저 검증, 테스트와 빌드 실행, 로그 분석처럼 결과만 필요하고 과정의 출력이 많은 작업은 서브에이전트로 넘깁니다. 서브에이전트는 자기 컨텍스트에서 일하고 요약만 돌려주므로 메인 대화가 커지지 않습니다. 에이전트 정의 파일에서 모델을 Sonnet으로 지정하면 단가도 절반이 됩니다. 판단 부담이 작은 작업이라 품질 위험도 낮습니다. 다만 서브에이전트는 빈 상태에서 시작하므로, 아주 짧은 작업을 맡기면 오히려 손해입니다.

4. 모델과 effort는 그다음, 시범 운영으로#

가장 고민한 것은 코딩 자체를 Sonnet에 맡길지였습니다. 단가는 절반이지만, 필자는 대화하면서 방향을 정하는 편이라 서브에이전트에 코딩을 넘기면 맥락을 전달하고 결과를 검토하는 비용이 붙습니다. 대안으로 Claude Code의 advisor 기능이 있습니다. Sonnet이 일상 작업을 하다가 계획 수립, 반복되는 오류, 완료 확인 같은 결정 지점에서만 Opus에 자문하는 방식입니다. 다만 자문할 때마다 Opus가 대화 전체를 캐시 없이 읽으므로, 대화 길이를 먼저 줄여야 성립합니다.

그래서 저장소 하나에서 1–2주 동안 두 방식을 시범 운영해 비교한 뒤 정하기로 했습니다. effort는 출력 비중이 작은 Codex에서는 그대로 두고, Claude Code에서는 글쓰기 저장소부터 Opus 5.5의 기본값인 medium으로 되돌리기로 했습니다. 필자는 effort를 high로 고정해 두고 있었는데, Opus 5.5의 기본값이 원래 medium이라는 것도 이번에 알았습니다.

5. 하지 않기로 한 것#

명령 출력을 줄여 주는 래퍼나 코드 구조를 질의하는 MCP 서버 같은 외부 도구도 여러 글에서 권했지만 보류했습니다. 보고된 효과가 대부분 단일 측정이거나 제작자의 수치였고, 위의 조치만으로 기준선이 얼마나 움직이는지 먼저 보고 싶었습니다. Codex의 컨텍스트 창을 강제로 늘리는 설정처럼 글마다 결과가 엇갈리는 것도 제외했습니다.

블로그 글을 그대로 따라 하기 어려운 이유도 하나 확인했습니다. Codex의 프로필(모델과 effort 같은 설정을 이름 붙여 묶어 두는 기능)은 공식 문서상 0.134.0부터 ~/.codex/<이름>.config.toml 파일을 읽는 방식으로 바뀌었는데, 상당수 글이 예전 문법을 싣고 있었습니다.

맺으며#

이번 조사에서 필자가 얻은 것은 새로운 팁이 아니었습니다. 팁 목록은 이미 충분했습니다. 필요한 것은 필자의 사용 패턴에서 각 팁이 얼마나 효과가 있는지 가늠할 숫자였고, 그 숫자는 로컬 로그에 이미 있었습니다. 같은 “effort 낮추기"도 Codex에서는 거의 효과가 없었고, 같은 “대화를 비워라"도 필자의 작업 방식에서는 “끝난 자리에서 압축해 두라"로 바뀌었습니다.

또 하나는 팁에 붙은 숫자와 설정 예시를 옮기기 전에 공식 문서로 확인해야 한다는 점입니다. 절감률은 대부분 조건이 붙은 단일 측정이었고, 팀 기능의 7배처럼 공식 수치도 조건을 빼고 읽으면 다른 뜻이 됩니다. Codex 프로필처럼 문법 자체가 바뀐 경우도 있었습니다.

아직은 계획 단계입니다. 이번 집계를 기준선으로 남겨 두었고, 적용하고 2주쯤 지나 같은 방법으로 다시 측정해 후속 글로 정리하겠습니다.

부록: 설정 예시#

Claude Code 사용자 설정(~/.claude/settings.json)입니다. 자동 압축 임계값과 팀 플래그만 담았습니다.

{
  "autoCompactWindow": 500000,
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "0"
  }
}

압축할 때 남길 내용은 프로젝트의 CLAUDE.md에 적어 둡니다.

# Compact instructions

압축할 때 작업 중인 파일 경로, 결정 사항, 남은 할 일, 브랜치와 PR 번호를 보존한다.

브라우저 검증을 맡길 서브에이전트는 .claude/agents/ 아래에 정의합니다. 도구 이름은 연결한 브라우저 MCP 서버에 맞게 바꿉니다.

---
name: browser-verifier
description: 브라우저 조작과 화면 검증 전담. 브라우저 확인이 필요하면 먼저 이 에이전트에 맡긴다.
model: sonnet
effort: medium
tools: mcp__<browser-server>__navigate_page, mcp__<browser-server>__take_snapshot, mcp__<browser-server>__take_screenshot
---

확인 항목별로 통과 / 실패와 근거를 텍스트로 요약해 보고한다.
스크린샷은 텍스트 스냅샷으로 판단할 수 없을 때만 찍는다.

Codex 설정(~/.codex/config.toml)입니다.

model_auto_compact_token_limit = 200000
tool_output_token_limit = 10000

[mcp_servers.<server-name>]
enabled_tools = ["<tool-a>", "<tool-b>"]

참고 자료#