Claude Code 세션에서 가치를 최대한 끌어내기
TMThttps://claude.com/blog/maximizing-the-value-of-your-claude-code-sessions
핵심 요약
- 작업이 바뀔 때마다
/clear를 실행합니다. 앞선 작업의 관련 없는 맥락이 모델로 다시 전송되지 않으므로 토큰 사용량을 줄일 수 있습니다. - 모델과 사고 수준(effort level)은 시작하기 전에 정합니다. 대화 중간에 둘 중 하나를 바꾸면 프롬프트 캐시가 깨져서 토큰 비용이 올라갈 수 있습니다.
- 파일은 이름을 적는 대신 @로 멘션합니다. 파일이 메시지에 바로 첨부되므로 Read 호출을 아낄 수 있고, Claude가 파일을 직접 찾아야 하는 상황이라면 검색까지 아낄 수 있습니다.
- 출력이 많은 명령에는 조용한 플래그를 붙이거나 서브에이전트에서 실행합니다. 명령 출력도 파일과 똑같이 대화에 추가되고, 세션이 끝날 때까지 그 자리에 남습니다.
- 새 세션에서
/context를 한 번 실행합니다.CLAUDE.md나 MCP 도구 정의처럼 무엇이 올라와 있는지 보여 주므로 불필요한 것을 걷어낼 수 있습니다. - 키보드에서 손을 떼기 전에
/compact를 실행합니다. 프롬프트 캐시는 한 시간이 지나면 만료되고, 대화를 요약하는 일은 캐시가 살아 있을 때 훨씬 저렴합니다.
가치를 최대한 끌어내기
얼마 전까지만 해도 코드를 작성하는 도구는 정액 요금이거나 무료였습니다. 그날 오후에 테스트를 하나 고쳤든 쉰 개를 고쳤든 편집기 비용은 같았고, 그래서 개별 작업에는 그 작업만의 가격이라는 것이 없었습니다.
Claude Code 같은 에이전틱 코딩 도구에서는 이야기가 다릅니다. 똑같이 끝낸 작업이라도 어떻게 쓰느냐에 따라 비용이 달라집니다.
어떤 세션에서는 Claude가 테스트와 그 테스트가 검사하는 파일을 읽고, 수정하고, 몇 번의 턴 만에 끝냅니다. 다른 세션에서는 저장소를 먼저 grep으로 훑고, 결국 같은 두 파일에 도달하기까지 열 개가 넘는 파일을 읽습니다. 그리고 그 턴마다 아침부터 대화에 쌓인 나머지 내용까지 전부 함께 끌고 갑니다.
곡선은 설명을 위한 예시일 뿐이며, 실제 벤치마크 데이터가 아닙니다.
같은 수정인데도 거기에 쓴 토큰의 양은 다르고, 그동안 모델은 필요하지도 않은 열 개의 파일까지 계속 신경 써야 했습니다.
토큰을 효율적으로 쓴다는 것은 전체 사용량을 줄이라는 뜻이 아닙니다. 실제로 쓰는 토큰이 내가 정말 요청한 일에 쓰이도록 만든다는 뜻입니다.
그러면 먼저 토큰 한 개의 가격이 무엇으로 정해지는지 살펴보고, 그다음 한 세션이 토큰을 몇 개나 보내게 되는지를 정하는 요인을 보겠습니다. 그 과정에서 세션을 어떻게 운영해야 하는지도 함께 짚어 보겠습니다.
토큰 한 개의 가격은 무엇으로 정해지는가
요금은 토큰 단위로 청구되지만, 실제로 지불하는 대상은 추론입니다. 즉 GPU(또는 TPU, 아니면 그 모델이 돌아가는 어떤 하드웨어든)가 내 토큰에 모델을 돌리는 데 걸리는 시간입니다.
토큰 하나가 그 시간을 얼마나 잡아먹는지는 세 가지가 결정합니다. 어떤 모델을 쓰는지, 그 토큰이 들어가는 입력 토큰인지 나오는 출력 토큰인지, 그리고 캐시에 있었는지입니다.
모델
큰 모델은 입력 토큰과 출력 토큰 모두에 더 많은 연산을 합니다. 어떤 작업에 어떤 모델이 값어치를 하는지는 그 자체로 하나의 주제이고, Claude Code에서 모델과 사고 수준 고르기에서 다뤘습니다.
이 글에서는 앞으로 다룰 모든 내용에 모델 가격이 곱해진다는 점만 알면 됩니다. 문제가 정말 어렵거나 모호할 때는 큰 모델을 쓰고, 늘 하던 종류의 일이라면 작은 모델을 씁니다.
곡선은 설명을 위한 예시일 뿐이며, 실제 벤치마크 데이터가 아닙니다.
입력 토큰과 출력 토큰
요청 하나는 GPU를 두 단계로 통과하는데, 두 단계의 비용은 다릅니다.
먼저 프리필(prefill) 단계에서 모델은 요청과 맥락을 읽습니다. 시스템 프롬프트, CLAUDE.md, 내가 보낸 메시지, 그리고 그 이후 대화에 추가된 모든 것, 즉 Claude가 읽은 파일과 실행한 명령의 출력입니다. 이것이 입력 토큰입니다.
그다음 디코드(decode) 단계에서 출력 토큰을 씁니다. 모델의 사고, 모델이 하는 도구 호출, 그리고 화면에 보이는 텍스트입니다. 이 과정은 한 번에 토큰 하나씩 진행되므로, 200토큰짜리 응답은 모델을 200번 연달아 돌린 결과입니다. 토큰 하나를 기준으로 보면 디코드가 GPU를 훨씬 오래 붙잡아 두고, 그래서 출력 가격은 입력의 약 5배로 책정됩니다.
한 세션의 출력 토큰 상당수는 사고 토큰이고, 모델이 턴마다 얼마나 생각하는지는 사고 수준이 조절합니다. 모델과 마찬가지로 /effort로 고른 수준은 다음 세션의 기본값으로도 남아 있습니다.
팁: 새 세션에서
/model과/effort를 한 번 실행해 지금 무엇을 쓰고 있는지 확인합니다. 둘 다 지난번에 고른 값을 기억하고 있으니, 그 선택은 의식적으로 내리는 것이 좋습니다.
팁: 세션이 단순 반복 작업이 될 것이 이미 분명하다면
MAX_THINKING_TOKENS=0 claude로 그 세션에서만 사고를 끌 수 있습니다(Fable 5는 예외)./effort low보다 한 단계 아래입니다.
프롬프트 캐싱
어떤 요청이 서버가 방금 처리한 요청과 완전히 똑같은 토큰으로 시작하면, 그 공통된 앞부분의 상태도 똑같이 나옵니다. 그래서 서버는 지난번 상태를 그대로 두고 그 뒤에 오는 부분만 프리필하면 됩니다. 이것을 프롬프트 캐싱이라고 합니다.
캐시에서 읽는 비용은 입력 가격의 10분의 1입니다. 서버가 상태를 계산하는 대신 불러오기만 하기 때문입니다. 캐시에 토큰을 쓰는 비용은 평소 입력보다 조금 비싸서 최대 2배까지 올라갑니다. 서버가 그 상태를 이후에도 붙들고 있어야 하기 때문입니다. 하지만 쓰기는 토큰당 한 번뿐이고, 10분의 1 가격의 읽기는 그 뒤 모든 턴에서 일어납니다.
Claude Code는 요청마다 프롬프트 캐시를 알아서 관리하므로 따로 켤 것은 없습니다. 다만 캐시를 깨뜨릴 수는 있으니, 비용이 튀는 상황을 피하는 방법을 알아 두는 것이 중요합니다.
"utils.test.ts에서 실패하는 테스트를 고쳐 줘"라고 입력했다고 해 봅시다. Claude Code가 이때 보내는 것은 다음과 같습니다.
- Claude Code가 시스템 프롬프트(도구 정의 포함),
CLAUDE.md, 내 메시지를 모아 첫 요청을 만들어 보냅니다(입력 토큰). 캐시에는 아직 아무것도 없으니 전부 프리필되고 캐시에 기록됩니다. - 모델은 보지도 못한 테스트를 고칠 수 없으니, 잠깐 생각한 뒤
utils.test.ts에 대한 Read 호출로 응답합니다(출력 토큰). Claude Code는 파일을 읽어 대화에 덧붙이고 전체를 다시 보냅니다(입력 토큰). 이번에는 1번 요청의 내용이 모두 10분의 1 가격으로 캐시에서 읽히고, 정가로 프리필되는 것은 새로 생긴 부분, 즉 Read 호출과 파일뿐입니다. - 이제 모델은 테스트 대상 파일을 원합니다(출력). 또 Read를 하고, 또 대화에 덧붙이고, 전체를 다시 전송합니다. 1번과 2번 요청은 캐시에서 읽히고, 두 번째 파일은 정가로 나갑니다(입력).
- 모델이 Edit으로 응답합니다(출력). Claude Code가 수정을 적용하고 결과를 덧붙인 뒤 전체를 다시 보냅니다. 이야기는 똑같습니다. Edit과 그 결과는 새로운 부분이고, 그 앞의 모든 것은 캐시 읽기입니다(입력).
- 모델이
npm test를 실행합니다(출력). Claude Code는 테스트 출력을 덧붙여 전체를 다시 보내는데, 새로운 부분은 테스트 출력뿐입니다(입력). - 테스트가 통과하고, 모델은 짧은 요약으로 응답합니다(출력). 도구 호출이 없으니 덧붙일 것도 없고 6번 요청도 없습니다. 여기서 끝입니다.
작은 수정 하나에 요청이 다섯 번 나갔고, 그 요청마다 그 시점까지의 대화 전체가 담겨 있었습니다. 보통 한 턴은 한쪽으로 크게 기울어 있습니다. 들어가는 것은 수만 토큰인데 나오는 것은 수백 토큰입니다. 하지만 정가로 프리필되는 것은 그 턴에서 새로 생긴 부분뿐입니다.
턴당 청구서는 이것이 전부입니다. 지나온 대화에는 캐시 읽기 가격, 새로 생긴 부분에는 정가 입력 가격, 응답에는 출력 가격이 붙습니다.
구독 요금제에서도 마찬가지입니다. 이 가격이 직접 보이지는 않지만, 사용 한도를 깎아 내리는 것은 바로 이 요청들입니다.
캐시는 요청의 맨 처음부터 순서대로 일치해야 하고, 요청은 항상 같은 순서로 나갑니다. 도구 정의, 그다음 시스템 프롬프트, 그다음 대화이고, CLAUDE.md가 대화의 맨 앞에 붙습니다.
그 앞부분에서 무엇이든 바뀌면 그 뒤의 모든 것이 다시 프리필됩니다. 대화 끝에 도구 결과가 덧붙는 경우가 가장 이상적입니다. 그 뒤에는 아무것도 없기 때문입니다. 캐시를 버리게 만드는 것은 요청의 앞쪽을 바꾸는 일, 또는 캐시의 키를 바꾸는 일입니다.
/model: 모델마다 캐시가 따로 있으므로, 다음 턴에 대화 전체가 정가로 다시 프리필됩니다. (계획 모드에 들어가고 나올 때마다 모델을 바꾸는 opusplan도 여기에 해당합니다.)/effort: 사고 수준도 캐시 키의 일부이므로 사정이 같습니다./model과/effort둘 다 대화 중간에 바꾸려 하면 확인을 요구하는 이유가 이것입니다.- 패스트 모드: 이것도 키의 일부이고, 다시 프리필하는 비용이 패스트 모드 가격으로 매겨집니다. 그러니 켤 생각이라면 처음에 켜는 것이 좋습니다. (다시 끄는 것은 캐시 측면에서 공짜입니다.)
/compact: 대화가 더 짧은 대화로 교체되므로 그 안의 어떤 것도 더는 일치하지 않습니다. 그 앞의 시스템 프롬프트는 살아남습니다. 요약을 쓰는 일 자체는 예전 대화가 아직 캐시에 남아 있는 한 저렴합니다. 그래서 오래 쉬고 난 뒤보다 쉬기 전에 하는 쪽이 훨씬 저렴합니다.- 시간: 턴마다 시계가 다시 돌아가지만, 캐시는 구독 요금제에서 한 시간, API 키에서는 5분이 지나면 만료됩니다(
ENABLE_PROMPT_CACHING_1H=1로 한 시간으로 늘릴 수 있습니다). 그보다 늦게 돌아오면 다음 턴에서 대화 전체를 다시 프리필합니다. 예전 세션을 이어서 여는 경우도 거의 항상 그렇습니다. 그때쯤이면 캐시는 보통 사라졌고, 시스템 프롬프트는 어차피 실행 시점에 다시 만들어집니다.
그렇다고 모델이나 사고 수준을 절대 바꾸지 말라는 뜻은 아닙니다. 바꾸기에 저렴한 순간과 비싼 순간이 있다는 뜻입니다. 세션을 시작할 때나 /clear 직후는 저렴하고, 긴 대화 중간은 비쌉니다.
팁: 최근 몇 턴이 남겨 두고 싶지 않은 방향으로 흘렀다면,
/compact를 실행하는 대신 그 직전으로/rewind합니다. 되돌리기는 끝에 붙은 그 턴들만 잘라내므로, 그 앞의 모든 것은 여전히 캐시에 남아 있고 비용이 들지 않습니다. 압축은 대화 전체를 다시 쓰기 때문에 항상 비용이 듭니다.
한 세션이 보내는 토큰 수는 무엇으로 정해지는가
여기서 알아야 할 핵심은 무엇도 한 번만 전송되지 않는다는 점입니다. 대화에 들어온 모든 것, 즉 Claude가 읽은 파일이나 실행한 명령의 출력은 그 뒤의 모든 턴에서, 세션이 끝날 때까지 다시 전송됩니다.
캐시에 있으니 다시 보내는 비용은 저렴하지만, 저렴하다는 것이 공짜라는 뜻은 아닙니다. 게다가 모델이 매 턴 그 내용을 피해 가며 생각해야 하는 맥락 공간까지 차지합니다.
세션의 비용 모델은 사실 이것으로 끝입니다. 맥락에 토큰이 얼마나 쌓이는지, 그 토큰이 몇 턴 동안 거기 머무는지, 그리고 동시에 몇 개의 맥락을 돌리고 있는지입니다.
맥락에 무엇이 쌓이는가
맥락에 있는 것 중 일부는 아무것도 입력하기 전부터 이미 자리를 잡고 있습니다. 도구 정의, 시스템 프롬프트, CLAUDE.md, 그리고 시작할 때 함께 올라오는 나머지 것들입니다.
팁: 새 세션에서
/context를 실행해 아무것도 입력하지 않은 상태에 무엇이 들어 있는지 확인합니다.CLAUDE.md에는 구체적인 지시만 남기고, 특정 작업 흐름에만 필요한 지시는 스킬로 옮깁니다. 스킬은 쓸 때만 불려 옵니다. 이번 세션에 필요 없는 MCP 서버가 있다면/mcp로 끕니다.
세션 도중에 추가되는 나머지는 거의 전부 도구 결과입니다. Claude가 읽는 파일과 실행하는 명령의 출력입니다.
Claude가 얼마나 많이 읽는지는 대체로 스스로 알아내야 하는 양에 달려 있습니다. "테스트가 실패한다"고만 말하면 먼저 어떤 테스트인지 찾아야 합니다. grep을 한두 번 돌리고, 어느 파일이 관련 있는지 보려고 몇 개를 열어 봅니다. 그리고 그 결과 전부는 더 이상 도움이 되지 않게 된 뒤에도 한참 동안 맥락에 남습니다.
"utils.test.ts에서 실패하는 테스트를 고쳐 줘"라고 하면 찾는 단계를 건너뛰고 파일을 읽는 Read 호출 한 번만 듭니다. "@utils.test.ts에서 실패하는 테스트를 고쳐 줘"라고 하면 그 Read 호출조차 들지 않습니다.
팁: 파일을 가리킬 때는 경로를 입력하는 대신 @로 멘션합니다. Claude Code가 무엇이든 전송하기 전에 파일을 메시지에 첨부하므로, 파일은 첫 요청부터 들어가 있고 그 파일을 위한 Read 호출도 없습니다. 파일 자체가 맥락에서 차지하는 자리는 어느 쪽이든 같으니, 한 대화에서 한 번만 멘션하면 됩니다. 파일은 그 자리에 계속 남아 있고, 나중 턴에서 다시 @로 멘션하면 보통 사본이 하나 더 붙습니다.
맥락을 채우는 또 하나는 Claude가 실행하는 명령의 출력입니다. 테스트나 빌드, git log를 실행할 때마다 그 출력은 읽은 파일과 똑같이 대화에 덧붙고, 같은 턴 수만큼 그 자리에 남습니다.
아주 큰 출력은 사실 괜찮습니다. 3만 자를 넘으면 Claude Code가 출력을 파일에 쓰고 대화에는 짧은 미리 보기와 경로만 넣습니다(바꾸고 싶다면 BASH_MAX_OUTPUT_LENGTH를 쓰면 됩니다).
문제는 그 아래에 있는 것들입니다. 통과한 테스트 400개를 한 줄씩 찍는 테스트 러너는 그 한도 아래로 들어오고, 그 400줄은 이제 남은 모든 턴의 일부가 됩니다.
Claude가 플래그와 tail로 알아서 처리해 주는 경우도 많습니다. Claude에게 맡기고 싶지 않다면, 출력이 많은 명령을 실행 전에 고쳐 써서 중요한 줄만 돌아오게 하는 작은 훅이 문서에 실려 있습니다.
팁: 하루 종일 실행하는 명령 두세 개를 조용한 플래그까지 붙여, 직접 입력할 때와 같은 형태로
CLAUDE.md에 적어 둡니다("테스트 파일 하나만 실행할 때는npx vitest run <file> --reporter=dot"). 작은 추가지만, 그 뒤 모든 세션에서 턴 한 번과 수백 줄의 출력을 아낍니다.
몇 턴 동안 남아 있는가
긴 세션 하나는 같은 일을 짧은 세션 몇 개로 나눠서 하는 것보다 비쌉니다. 그것도 생각보다 훨씬 비쌉니다. 40번째 턴은 그 앞의 39턴을 다시 읽는 셈이기 때문입니다. 세션의 맥락은 짧고 관련 있는 것만 남기는 것이 좋으니, 한 작업의 맥락을 다음 작업으로 끌고 가지 않습니다. 새로운 일을 시작할 때는 /clear, 같은 작업의 앞부분이 끝났을 때는 /compact를 씁니다.
팁: 나중에 세션을 다시 열고 싶다면
/clear전에/rename을 해 둡니다./compact를 할 때는 무엇을 남길지 알려 주고, 남길 것이 늘 같다면CLAUDE.md에 "Compact instructions" 항목을 넣습니다. 100만 토큰 모델을 쓰면서 자동 압축 안전망을 예전 위치로 되돌리고 싶다면/autocompact 200k로 되돌릴 수 있습니다(Claude Code v2.1.221 이상 필요).
내가 입력하지 않는 동안 일어나는 턴도 눈여겨봅니다. /loop은 그것을 설정한 세션에서 온전한 턴으로 실행되며, 매번 그 대화 전체를 함께 끌고 갑니다. 마지막 턴에서 한 시간이 넘었다면 캐시 미스까지 겹칩니다. 다른 터미널에서 새 세션을 열고 거기서 루프를 돌리는 것이 좋습니다.
서브에이전트
무언가를 내 맥락 밖에 두는 또 하나의 방법은 그 일을 다른 맥락에서 일어나게 하는 것인데, 서브에이전트가 바로 그 용도입니다. 서브에이전트는 자기만의 맥락 창을 받습니다. 자기 시스템 프롬프트와 도구, 그리고 내 CLAUDE.md는 들어가지만 내 대화는 들어가지 않습니다. 서브에이전트는 자기 턴을 돌리고, 메인 세션으로 돌아오는 것은 그 답변뿐입니다. 나머지는 일이 끝나면 버려집니다.
내 대화를 물려받지 못하는 데서 오는 단점도 있습니다. 서브에이전트는 메인 세션에 이미 있던 내용을 다시 읽어야 할 때가 있고, 그러는 동안 자기 턴 비용을 냅니다. 작은 일에는 그저 부담일 뿐입니다.
값어치를 하는 경우는 로그를 훑는 일처럼 남겨 둘 필요 없는 출력이 많이 나오는 작업입니다. 그런 일에는 Claude가 알아서 서브에이전트를 꺼내 쓰는 경우가 많고, 그러지 않을 때는 직접 요청할 수 있습니다("이 로그는 서브에이전트에서 훑어 줘"). 다만 메인 세션이 돌려받는 것은 서브에이전트가 보고하기로 고른 내용뿐이라는 점은 기억해 둡니다.
팁: 출력이 많은 작업을 반복해서 넘기고 있다면,
model: haiku(또는sonnet)를 지정한 전용 서브에이전트 정의를 만들어 둡니다. 그러지 않으면 메인 세션이 돌고 있는 모델에서 그대로 실행됩니다.
무엇부터 봐야 하는가
지금까지 다룬 것 중에서 눈여겨볼 만한 것은 네 가지이고, 비용이 큰 순서에 가깝게 정리하면 다음과 같습니다.