LOTS-OResearch Notes

2026-08-14 - Lydia Hallie - Claude Code 세션 토큰 효율

Source

TL;DR

  • 세션 비용은 토큰 하나의 가격과 세션이 보내는 토큰 수로 정해진다.
  • 토큰 하나의 가격은 모델, 입력인가 출력인가, 캐시 여부가 정한다.
  • 출력은 decode가 한 토큰씩 순차라 입력의 약 5배다.
  • 캐시는 요청의 prefix가 같을 때 적중하며 read는 입력의 0.1배, write는 최대 2배다.
  • 컨텍스트에 쌓인 토큰은 매 턴 다시 전송되므로 /clear·@-mention·subagent로 컨텍스트를 짧고 관련 있게 유지한다.

효율적으로 쓴다는 것은 토큰을 적게 쓰는 것이 아니다. 쓰는 토큰이 실제로 물어본 일에 들어가도록 만드는 것이다. 같은 수정도 세션 운용에 따라 토큰 수가 달라진다. 한 세션은 테스트와 대상 파일을 읽고 몇 턴 만에 끝낸다. 다른 세션은 저장소를 grep하며 열두 개 파일을 거쳐 같은 두 파일을 찾아낸다. 그 사이 필요 없는 열 개 파일까지 매 턴 다시 딸려 온다.

토큰 하나의 가격

토큰당 과금이지만 실제로 사는 것은 추론, 곧 GPU가 토큰을 처리하는 시간이다. 그 시간을 정하는 것이 셋이다. 어느 모델인가, 입력 토큰인가 출력 토큰인가, 캐시됐는가.

모델

큰 모델은 입력·출력 양쪽에서 더 많은 일을 하고 아래 모든 항목이 모델 단가에 곱해진다. 어려운 문제엔 큰 모델, 루틴엔 작은 모델을 쓴다. 어떤 모델이 어떤 일에 값하는지는 2026-07-07 - Lydia Hallie - Claude Code 모델·Effort 레벨 선택에서 다룬다.

입력과 출력

요청은 GPU를 두 단계로 지난다. prefill에서 모델이 시스템 프롬프트·CLAUDE.md·메시지와 그동안 대화에 쌓인 것을 읽는다. 이것이 입력 토큰이다. decode에서 thinking·tool call·사용자에게 갈 텍스트를 쓰고 한 번에 하나씩 나온다. 200토큰 응답은 모델을 200번 돌린 것이다. 토큰당 decode가 GPU를 훨씬 오래 잡아 출력이 입력의 약 5배로 매겨진다.

프롬프트 캐싱

요청이 서버가 방금 본 요청과 똑같은 토큰으로 시작하면 그 공통 앞부분의 상태가 같게 나온다. 서버는 그 부분을 지난번에서 그대로 두고 뒤에 새로 온 것만 prefill한다. 캐시에서 읽는 비용은 입력의 0.1배다. 계산 대신 상태를 불러오기 때문이다. 캐시에 쓰는 비용은 상태를 이후에도 들고 있어야 해서 입력보다 조금 더, 최대 2배다. write는 토큰당 한 번이고 0.1배 read는 그 뒤 매 턴 일어난다.

캐시는 요청의 맨 앞에서부터 맞아야 하고 요청은 늘 같은 순서로 나간다. 도구 정의, 그다음 시스템 프롬프트, 그다음 대화(CLAUDE.md가 앞)다. 이 prefix에서 무언가 바뀌면 그 뒤가 전부 다시 prefill된다. 대화 끝에 붙는 tool 결과가 이상적인 경우다. 뒤에 아무것도 없기 때문이다. 캐시를 깨는 것은 요청 앞쪽을 바꾸거나 캐시 key를 바꾸는 조작이다.

  • /model: 모델마다 캐시가 따로라 다음 턴에 대화 전체가 제값으로 다시 prefill된다. plan 모드를 드나들 때 모델이 바뀌는 opusplan도 여기 든다.
  • /effort: effort도 캐시 key의 일부다. 그래서 /model·/effort는 대화 중간에 바꾸면 확인을 묻는다.
  • fast mode: 역시 key의 일부이고 다시 prefill이 fast mode 가격으로 일어난다. 켤 거면 세션 시작에 켠다. 끄는 것은 캐시상 공짜다.
  • /compact: 대화가 짧은 것으로 교체돼 더 이상 맞지 않는다. 앞의 시스템 프롬프트는 살아남는다. 요약을 쓰는 비용은 옛 대화가 아직 캐시에 있을 때 싸다.
  • 시간: 캐시는 구독에서 1시간, API 키에서 5분 뒤 만료된다. 그 뒤 첫 턴은 전체를 다시 prefill한다. 옛 세션을 이어받으면 거의 항상 그렇다.

모델·effort를 절대 바꾸지 말라는 뜻은 아니다. 바꾸기 싼 순간(세션 시작, /clear 직후)과 비싼 순간(긴 대화 중간)이 있다는 것이다.

세션이 보내는 토큰 수

한 번만 보내는 것은 없다. 대화에 들어간 것, 곧 Claude가 읽은 파일이나 실행한 명령의 출력은 그 뒤 매 턴 다시 보내진다. 캐시라 재전송은 싸지만 공짜는 아니고 모델이 매 턴 처리해야 하는 컨텍스트도 차지한다. 세션의 비용은 컨텍스트에 든 토큰 수, 그것이 머무는 턴 수, 동시에 돌리는 컨텍스트 수로 정해진다.

컨텍스트에 쌓이는 것

타이핑 전부터 도구 정의·시스템 프롬프트·CLAUDE.md가 들어 있다. /context로 확인해 필요 없는 것을 뺀다. CLAUDE.md는 구체 지시만 남기고 워크플로별 규칙은 스킬로 옮긴다. 세션에 필요 없는 MCP 서버는 /mcp로 끈다. 이후 쌓이는 것은 대부분 tool 결과다. "테스트가 실패한다"고만 하면 어느 테스트인지부터 찾느라 grep과 파일 몇 개가 붙고 그 결과가 오래 남는다. @utils.test.ts처럼 파일을 직접 붙이면 Read 호출도 아낀다. 3만 자를 넘는 큰 출력은 파일로 빠지고 미리보기와 경로만 남아 오히려 안전하다. 문제는 그 아래다. 400개 통과 테스트를 한 줄씩 찍는 러너는 한도 밑으로 들어와 남은 턴마다 400줄을 달고 다닌다.

머무는 턴 수

긴 세션 하나가 같은 일을 짧은 세션 여럿으로 나눈 것보다 비싸다. 40번째 턴이 앞의 39턴을 다시 읽기 때문이다. 새 작업엔 /clear, 같은 작업의 앞부분이 끝나면 /compact를 쓴다. 되돌리고 싶은 최근 턴만 잘라낼 땐 /compact보다 /rewind가 싸다. 앞부분은 그대로 캐시에 남는다.

서브에이전트

컨텍스트 밖으로 빼는 다른 방법은 다른 컨텍스트에서 일어나게 하는 것, 곧 subagent다. subagent는 자기 컨텍스트 창과 시스템 프롬프트·도구·CLAUDE.md를 갖되 내 대화는 안 가진다. 자기 턴을 돌리고 답만 돌려주며 나머지는 끝나면 버린다. 로그를 훑는 것처럼 안 남겨도 되는 출력이 많은 작업에서 값한다. 대신 메인 세션은 subagent가 보고하기로 한 것만 받는다.

적용 우선순위

원문은 비용이 큰 순서로 넷을 든다. /clear로 작업을 분리하기, 컨텍스트에 쌓이는 것을 줄이기, 모델·effort를 세션 시작에 정해 캐시를 지키기, 긴 출력을 subagent나 quiet flag로 걷어내기.

Open Questions

  • 배수(출력 5배, read 0.1배, write 2배)는 Claude 기준이다. 타 벤더는 [[1차 - 벤더 요금·정책 비교]]에서 대조한다.
  • 컨텍스트 상한(1M 등)과 auto-compact 임계는 모델·버전에 종속된다.

Connections