Tech_News

Claude Code가 프롬프트도 읽기 전에 33k 토큰을 태우는 이유 — OpenCode와 실측 비교

TeEm0 2026. 7. 14. 09:00
728x90

월말에 Anthropic 사용량 대시보드를 열었다가 "우리가 이걸 이렇게 많이 썼나?" 싶었던 적 있으면 이 글이 도움이 될 거다. Systima에서 Claude Code와 OpenCode를 같은 모델·같은 머신·같은 태스크에 물려놓고, API 경계에서 오가는 요청 페이로드를 전부 뜯어본 실측 리포트를 냈다. 결론부터 말하면 Claude Code는 사용자가 프롬프트를 치기도 전에 약 33,000 토큰을 소비하고, OpenCode는 약 7,000 토큰이었다. 약 4.7배 차이다.

단순히 "Claude Code가 비싸다"로 끝날 얘기가 아니다. 이 오버헤드가 어디서 나오는지, 캐싱은 뭘 살려주고 뭘 못 살려주는지, 그리고 실무에서 어떤 셋업일 때 이게 재앙이 되는지를 알아야 도구를 제대로 고를 수 있다.

1. 왜 지금 이 얘기가 나오는가

AI 코딩 에이전트를 팀에 도입해본 사람이면 알 거다. 처음엔 "토큰? 얼마 안 나오겠지" 하다가, 여러 명이 하루종일 돌리기 시작하면 청구서가 예상 밖으로 튄다. 문제는 토큰 오버헤드가 곧 비용이자 지연시간이자 컨텍스트 예산이라는 점이다.

에이전트가 매 턴마다 보내는 건 여러분의 프롬프트만이 아니다. 시스템 프롬프트, 툴 스키마(도구 정의 JSON), 그리고 각종 주입된 스캐폴딩이 앞에 붙는다. 이 베이스라인은 매 요청마다 다시 전송되거나 캐시에서 다시 읽힌다. 즉 33k 토큰짜리 베이스라인이면, 200k 컨텍스트 윈도우의 약 1/6을 코드 한 줄 넣기도 전에 이미 잡아먹고 시작하는 셈이다.

특히 EU AI Act Article 12처럼 에이전트 동작을 로깅하고 설명할 수 있어야 하는 규제 환경이라면, "내 에이전트가 실제로 뭘 보내는가"를 소문이 아니라 데이터로 답할 수 있어야 한다. 이 리포트가 딱 그걸 한 거다.

2. 33k는 어디서 나오는가 — 시스템 프롬프트 해부

Systima는 하네스(harness, 여기선 Claude Code / OpenCode)와 모델 엔드포인트 사이에 로깅 프록시를 끼워넣었다. 구조는 이렇다.

harness (Claude Code / OpenCode)
    → logging proxy (요청 페이로드 + 응답 usage 캡처)
        → model endpoint

프록시는 두 가지를 기록한다. 하네스가 실제로 내보낸 JSON 페이로드(시스템 블록, 툴 스키마, 메시지)와, API가 반환한 usage 블록(input 토큰, cache write, cache read, output 토큰). 페이로드는 "무엇을 보냈나"의 원본 진실, usage는 "무엇이 과금됐나"의 원본 진실이다.

T1: "OK라고만 답해" — 순수 오버헤드 측정

가장 극단적인 테스트다. 프롬프트는 딱 22자, "Reply with exactly: OK". 여기에 각 하네스가 뭘 얹어 보냈는지 보자.

구성요소 Claude Code OpenCode
시스템 프롬프트 27,344자 (3블록) 9,324자 (1블록)
툴 스키마 27개 툴, 99,778자 10개 툴, 20,856자
첫 메시지 스캐폴딩 7,997자 (system-reminder 블록) 없음
실제 프롬프트 22자 22자
첫 턴 페이로드(보정치) 약 32,800 토큰 약 6,900 토큰

핵심은 두 하네스 모두 툴 스키마가 지배적이라는 점이다. Claude Code의 약 33k 중 약 24,000이 툴 정의고, OpenCode의 약 6,900 중 약 4,800이 툴 정의다.

왜 Claude Code가 이렇게 무거운가? 27개 툴이 코딩 코어만이 아니라 백그라운드 에이전트/오케스트레이션 스위트 전체를 포함하기 때문이다. CronCreate, Monitor, Task 패밀리, worktree 관리, 푸시 알림까지 다 들어있다. 게다가 첫 유저 메시지 앞에 세 개의 리마인더 블록(위임용 에이전트 카탈로그, 사용 가능 스킬 카탈로그, 유저 컨텍스트)이 주입된다.

반면 OpenCode는 거의 미니멀하다. "You are OpenCode, the best coding agent on the planet"으로 시작하는 시스템 블록 하나, 클래식한 코딩 툴 10개, 그리고 여러분의 프롬프트가 유일한 유저 콘텐츠다.

툴을 다 꺼도 여전히 3배

툴을 빼고 시스템 프롬프트 자체만 비교하면, Claude Code는 26,891자(약 6.5k 토큰), OpenCode는 8,811자(약 2.0k 토큰)다. 툴을 전부 제거해도 Claude Code의 명령어 세트가 3배 이상 크다. 나머지는 톤 규칙, 안전 가이드, 태스크 관리 지침, 환경 설명 같은 "행동 강령"이다.

직접 확인하고 싶다면 툴을 끄고 돌려볼 수 있다.

# Claude Code에서 툴 비활성화
claude --tools

# OpenCode에서 툴 비활성화 (설정)
# opencode 설정 JSON에
{ "tools": { "*": false } }

3. 캐싱은 어디까지 살려주나 — 여기가 진짜 함정

"어차피 프롬프트 캐싱 걸리니까 괜찮은 거 아니야?"라고 생각하기 쉽다. 여기가 실무에서 제일 많이 착각하는 지점이다.

OpenCode는 캡처된 모든 실행에서 요청 프리픽스가 바이트 단위로 동일했다. 세션당 한 번 캐시에 쓰고, 이후엔 몇 푼짜리 cache read로 다시 읽는다. 이상적인 캐시 활용이다.

반면 Claude Code는 세션 중간에 수만 토큰의 prompt-cache 토큰을 다시 썼다. 같은 태스크에서 OpenCode보다 최대 54배 많은 cache write를 기록했다. cache write는 프리미엄 가격으로 과금된다. 대시보드 숫자가 치솟는 주범이 바로 이거다.

왜 다시 쓰는가: Claude Code는 대화가 진행되면서 system-reminder 블록을 추가로 주입한다. 첫 턴엔 3개, 첫 툴 라운드트립엔 4개로 늘어난다. 스캐폴딩이 턴 수에 따라 자라니까, 프리픽스가 바뀌고 캐시가 깨지는 것으로 보인다.

중요한 사실 하나. 세 가지는 캐시 할인과 무관하게 무조건 스케일한다.

  • 첫 턴의 cache write (프리미엄 과금)
  • 매 턴의 cache read (싸긴 하지만 0은 아님)
  • 컨텍스트 윈도우 소비 — 이건 어떤 캐시 할인으로도 줄지 않는다

세 번째가 핵심이다. 33k 베이스라인은 매 턴이 200k 윈도우의 1/6 지점에서 시작한다는 뜻이고, 캐싱이 아무리 잘 돼도 이 컨텍스트 압박은 절대 안 줄어든다.

모델을 바꾸면 그림이 달라진다

Systima가 T1을 Claude Fable 5로 재실행했더니 격차가 줄었다. 이유가 흥미롭다. Claude Code의 시스템 프롬프트는 모델 조건부다. Sonnet에는 27,787자를 보냈지만 Fable에는 10,526자만 보냈고, 툴 스키마도 99,778자에서 82,283자로 줄었다. 같은 27개 툴인데 doctrine이 훨씬 적다. OpenCode 페이로드는 두 모델에서 바이트 단위로 동일했다.

결과적으로 페이로드 기준 격차가 Sonnet에서 4.7배, Fable에서 약 3.3배로 좁혀졌다. 여전히 훨씬 무겁지만, 배수는 모델에 따라 다르다는 점을 기억하자.

4. 실무 관점 — 멀티플라이어와 흔한 함정

T1은 최선의 시나리오다. 현실 세션은 저렇게 린하게 시작해서 짧게 끝나지 않는다. 실무에서 얹히는 레이어들을 보자.

멀티플라이어 1: 지시 파일 (AGENTS.md / CLAUDE.md)

프로덕션 레포의 72KB 지시 파일을 워크스페이스에 넣고 T1을 재실행하니, 양쪽 다 요청당 20,000 토큰 이상이 추가됐다.

  • OpenCode: 13,152 → 33,336 토큰
  • Claude Code: 39,005 → 59,243 토큰

여기 첫 번째 함정. Claude Code 2.1.207은 AGENTS.md를 완전히 무시했다. CLAUDE.md로 이름을 바꿔야만 읽었고, 그것도 시스템 프롬프트가 아니라 첫 유저 메시지에 주입했다. OpenCode는 두 파일명을 다 읽고 시스템 프롬프트에 넣는다.

이게 왜 무서운가 하면, 무시된 지시 파일은 아무 에러도 안 낸다. 팀 컨벤션을 열심히 적어놨는데 에이전트가 조용히 무시하고 있는 상황을 상상해보라. 파일명을 잘못 쓰면 이런 식으로 조용히 아무 일도 안 일어난다.

# 실무 체크: 하네스가 어떤 파일명을 실제로 먹는지 확인
$ ls -la
-rw-r--r--  1 dev  staff  73728  AGENTS.md   # Claude Code가 무시함!

# 로그를 보면 지시 파일 관련 주입이 아예 없다
# (에러 메시지가 안 나오는 게 오히려 함정)

# 해결: CLAUDE.md로 심볼릭 링크 또는 리네임
$ ln -s AGENTS.md CLAUDE.md
$ ls -la
lrwxr-xr-x  1 dev  staff      9  CLAUDE.md -> AGENTS.md
-rw-r--r--  1 dev  staff  73728  AGENTS.md

멀티플라이어 2: MCP 서버

MCP 서버를 붙이면 스키마가 프롬프트에 추가된다. 스키마는 하네스 간 동일하니 세금도 거의 같다. 작은 서버당 요청당 약 1,000~1,400 토큰. 5개 서버를 붙였더니 Claude Code는 페이로드 기준 4,900 토큰, OpenCode는 metered 6,967 토큰이 늘었고, 툴 개수가 각각 27→69, 10→52로 불었다.

여기 두 번째 조용한 함정. Claude Code는 print 모드에서 프로젝트 스코프 .mcp.json을 조용히 무시했다. --mcp-config 플래그를 명시해야 읽었다. 서버가 붙어있다고 가정했는데 실제론 안 붙어있는 상황이 생긴다.

# .mcp.json이 있는데도 print 모드에서 서버가 안 잡히는 경우
$ claude -p "list available tools"
# → MCP 툴이 목록에 안 보임 (에러도 없음)

# 명시적으로 config를 넘겨야 함
$ claude -p "list available tools" --mcp-config .mcp.json
# → 이제 MCP 서버 툴이 스키마에 포함됨

공교육용 교훈은 하나다. 서버가 붙었다고 가정하지 말고 경계(API boundary)에서 검증하라. 프록시 로그든 툴 목록이든, 실제 페이로드를 눈으로 확인해야 한다.

멀티플라이어 3: 프레임워크 템플릿

BMAD 같은 스토리 기반 워크플로우 프레임워크는 슬래시 커맨드를 페르소나·프로토콜·체크리스트로 가득한 큰 템플릿으로 확장한다. 8,405자짜리 대표 템플릿을 T3 프롬프트로 넣어봤더니, 템플릿 자체는 약 2,100 토큰이지만 대화 히스토리에 들어가서 이후 모든 요청이 다시 실어 나른다. 9-요청 세션이면 9번 재전송된다. 프레임워크 세금 = 템플릿 크기 × 요청 수, 그리고 이건 위의 모든 것 위에 쌓인다.

멀티플라이어 4: 서브에이전트 — 여기서 총액이 폭발

이게 제일 무섭다. 작업을 서브에이전트 2개로 팬아웃했더니, 직접 하면 121,000 토큰이던 작은 태스크가 513,000 토큰으로 뛰었다. 서브에이전트마다 자기 부트스트랩 비용이 있고, 부모가 다시 그 트랜스크립트를 소비하기 때문이다. "병렬로 나누면 빠르겠지"라고 서브에이전트를 남발하면 토큰 청구서가 4배 넘게 튀는 걸 각오해야 한다.

반전: 멀티스텝에선 Claude Code가 더 쌀 수도 있다

모든 게 Claude Code 불리로만 흐르는 건 아니다. T3(write-run-test-fix 루프)에서는 예상이 뒤집혔다.

지표 Claude Code OpenCode
모델 요청 수 3 9 (+타이틀 콜 1)
툴 호출 방식 한 라운드트립에 병렬 배치 턴당 툴 1개
누적 metered input 약 121,000 토큰 약 132,000 토큰

Claude Code는 전체 작업(파일 쓰기 2개 + 스크립트 실행 2개)을 단일 병렬 툴 라운드트립으로 배치했다. OpenCode는 턴당 정확히 툴 하나씩 9번 돌았다. 베이스라인은 매 요청마다 재전송되므로 요청 수가 베이스라인을 곱한다. OpenCode는 약 7k 베이스라인을 9번 냈고, Claude Code는 약 33k를 3번 냈다. 결과적으로 총액이 수렴했다.

공식: 전체 작업 input ≈ 베이스라인 × 요청 수 + 대화 성장분. 큰 베이스라인 + 공격적 배칭 하네스와, 작은 베이스라인 + 직렬 하네스가 같은 지점에 착지할 수 있다. 미터는 높은 데서 시작하지만, 세션이 어떻게 전개되느냐가 누가 더 쓸지를 결정한다.

5. 정리 — 누가 언제 뭘 써야 하나

한 줄 요약: Claude Code는 시작 오버헤드가 크지만 툴 배칭이 강하고, OpenCode는 베이스라인이 가볍지만 턴마다 그 비용을 반복 지불한다.

  • 짧고 단순한 반복 작업이 많다면 (커밋 메시지, 소규모 리팩터, 단발성 질의): OpenCode가 유리하다. 33k를 매번 태울 이유가 없다.
  • 복잡한 멀티스텝 작업을 배치로 처리한다면: Claude Code의 병렬 배칭이 요청 수를 줄여 총액을 낮출 수 있다.
  • 컨텍스트 윈도우가 빡빡한 대형 코드베이스라면: 캐시 할인과 무관하게 33k가 윈도우를 잡아먹는다는 걸 기억하라. 여기선 베이스라인이 가벼운 쪽이 실질적으로 유리하다.
  • 규제 환경(EU AI Act 등)이라면: 로깅 프록시를 경계에 두고 실제 페이로드를 캡처하라. "무엇을 보내는가"를 데이터로 답할 수 있어야 한다.

그리고 도입 전 반드시 확인할 것 세 가지: ① 지시 파일 파일명을 하네스가 실제로 먹는지(AGENTS.md vs CLAUDE.md), ② MCP 서버가 경계에서 진짜 붙었는지, ③ 서브에이전트 팬아웃이 정말 필요한지(4배 폭발 각오). 이 셋만 챙겨도 예상 밖 청구서는 크게 줄어든다.

마지막으로, 이 모든 수치는 특정 버전(Claude Code 2.1.207, OpenCode 1.17.18, 2026년 7월 claude-sonnet-4-5 / claude-fable-5 기준)에서 나온 것이다. 하네스와 모델은 계속 바뀌므로, 여러분 환경에서는 직접 프록시를 끼워 측정하는 게 정답이다. 소문 말고 데이터로.

참고 자료

728x90