LLM WikiAccess-protected knowledge portal
← 스터디 홈
13편 · 약 18분

Claude Adaptive Thinking: 토큰 예산을 버리고 복잡도를 스스로 판단하는 추론 API

고정 예산이 만드는 비효율

Extended thinking을 처음 도입할 때 개발자는 budget_tokens를 결정해야 했다. "복잡한 쿼리에는 16,000, 단순 질문에는 4,000" 식으로 요청 유형을 나눠 서로 다른 예산을 적용하거나, 안전하게 큰 값 하나로 통일하는 방식이 흔했다. 전자는 유형 분류 로직을 따로 관리해야 했고, 후자는 쉬운 요청에도 불필요하게 긴 추론을 기다리는 비용을 냈다.

2026년 2월 Claude Sonnet 4.6과 함께 공개된 Adaptive Thinking은 이 결정 자체를 모델에 위임한다. 개발자는 복잡도를 분류하는 대신 "어느 정도 깊이로 생각해야 하는 작업인가"를 effort 레벨로만 지정하고, 모델이 요청마다 실제로 생각할지·얼마나 생각할지를 스스로 결정한다.

이 변화는 API 파라미터 하나가 바뀐 것이 아니다. Claude 4 최신 모델 라인업 전반에서 budget_tokens 방식이 deprecated되고 있고, Fable 5·Mythos 5처럼 adaptive thinking이 항상 켜지는 모델이 등장했다.


세 가지 thinking 모드와 모델별 지원 범위

Claude Thinking 모드 지형도 (2026-07) adaptive thinking: {type: "adaptive"} effort로 깊이 조절 인터리빙 자동 활성화 권장 방식 (신규 모델 전용) enabled (manual) thinking: {type: "enabled", budget_tokens: N} Opus 4.6 / Sonnet 4.6에서 deprecated 구형 모델 전용 (레거시) disabled thinking: {type: "disabled"} Fable 5, Mythos 5, Mythos Preview에서 지원 안 됨 최저 지연, thinking 불필요 시 모델별 thinking 지원 매트릭스 모델 adaptive manual thinking 기본값 display 기본값 Fable 5 / Mythos 5 항상 켜짐 (비활성화 불가) ❌ 400 오류 adaptive (고정) omitted Mythos Preview 기본값 ✅ 허용 adaptive (기본) omitted Opus 4.8 / Opus 4.7 명시적 설정 필요 ❌ 400 오류 off (명시 설정 필요) omitted Sonnet 5 기본값 ❌ 400 오류 adaptive (기본) omitted Opus 4.6 / Sonnet 4.6 명시적 설정 ⚠️ deprecated off summarized Opus 4.5 / Haiku 4.5 ❌ 지원 안 됨 ✅ 유일한 방식 off Opus 4.8·4.7에서 thinking을 쓰려면 반드시 thinking: {type: "adaptive"}를 명시해야 한다. 생략하면 thinking이 꺼진다.
Claude Adaptive Thinking API 모드와 모델별 지원 관계

budget_tokens에서 effort로: API 변경의 실제 의미

기존 방식과 새 방식은 구조가 다르다.

기존 방식 (deprecated on Opus 4.6 / Sonnet 4.6)

response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=16000,
    thinking={"type": "enabled", "budget_tokens": 10000},
    messages=[{"role": "user", "content": "..."}],
)

새 방식 (adaptive + effort)

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=16000,
    thinking={"type": "adaptive", "display": "summarized"},
    output_config={"effort": "medium"},
    messages=[{"role": "user", "content": "..."}],
)

두 파라미터의 역할을 분리해 이해해야 한다.

파라미터위치역할
thinking.typethinking 객체추론 모드 선택 (adaptive / enabled / disabled)
output_config.effort최상위추론 깊이의 soft 가이드
thinking.budget_tokensthinking 객체최대 토큰 hard limit (legacy; adaptive와 공존 불가)
max_tokens최상위thinking + text를 합친 전체 출력 hard limit

effort는 hard limit이 아니라 soft guidance다. Claude가 판단하기에 간단한 문제라면 high에서도 thinking을 짧게 끝낼 수 있다. 반대로 max_tokens에 가까워지면 stop_reason: "max_tokens"로 응답이 잘릴 수 있으므로, thinking이 활발한 모델에는 max_tokens를 여유 있게 설정해야 한다.


effort 레벨의 실제 동작

effort 레벨thinking 동작가용 모델
max항상 thinking, 깊이 제한 없음adaptive 지원 전 모델
xhigh항상 깊게 thinkingFable 5, Mythos 5, Opus 4.8, Opus 4.7, Sonnet 5
high (기본값)거의 항상 thinking, 복잡한 작업에서 충분한 추론전체
medium중간 수준 thinking, 단순 쿼리는 건너뜀전체
lowthinking 최소화, 속도 우선전체

effort를 명시하지 않으면 기본값은 high다. 고용량 챗봇이나 단순 분류처럼 latency가 중요한 workload에는 lowmedium을 먼저 평가하고, 실제 품질 차이를 측정한 뒤 결정한다. 측정 없이 low로 낮추면 추론이 필요한 요청에서 응답 품질이 조용히 떨어질 수 있다.


인터리빙: 도구 호출 사이에서도 thinking이 이어진다

Adaptive thinking을 사용하면 인터리빙(interleaved thinking)이 자동으로 활성화된다. Claude가 도구 호출 전후로 개별적으로 추론 블록을 생성하면서, 여러 단계로 이어지는 에이전트 루프에서 더 맥락에 맞는 결정을 내릴 수 있다.

Turn 1: User → Claude
사용자 메시지
thinking 블록 ①
tool_use: calculator
Turn 2: tool_result → Claude
tool_result 수신
thinking 블록 ② (도구 결과 해석)
tool_use: database
Turn 3: 최종 응답
tool_result 수신
thinking 블록 ③ (종합)
최종 text 응답
이전 thinking 블록은 반드시 수정 없이 그대로 다음 요청에 포함시켜야 한다.
인터리빙 thinking과 도구 호출의 흐름

도구 결과를 API에 돌려보낼 때 thinking 블록을 수정하거나 제거하면 API가 오류를 반환한다. thinking 필드가 빈 문자열인 omitted 블록도 마찬가지다. 내용을 읽는 것은 괜찮지만, 내용을 바꾸거나 재구성하면 안 된다.

# 반드시 지켜야 할 패턴: thinking 블록을 그대로 포함
messages = [
    {"role": "user", "content": "오늘 매출 vs 지난달 평균 비교해줘"},
    {
        "role": "assistant",
        "content": [
            thinking_block,   # ← 반드시 수정 없이 포함
            tool_use_block,
        ]
    },
    {
        "role": "user",
        "content": [{"type": "tool_result", "tool_use_id": tool_use_block.id, "content": "..."}]
    }
]

도구와 함께 thinking을 쓸 때 tool_choice"auto" 또는 "none"만 허용한다. "any"나 특정 도구 지정({"type": "tool", "name": "..."}은 오류다.


display와 signature: 보임/안 보임과 과금의 분리

display 필드는 thinking 내용이 응답에 어떻게 나타날지를 결정한다. 과금 기준은 바뀌지 않는다.

display 값thinking 필드 내용signature 필드과금기본값인 모델
"summarized"요약된 추론 텍스트포함전체 thinking 토큰Opus 4.6, Sonnet 4.6
"omitted"빈 문자열 ("")포함전체 thinking 토큰Fable 5, Mythos 5, Sonnet 5, Opus 4.8, Opus 4.7, Mythos Preview

"omitted"의 장점은 스트리밍 latency다. thinking_delta 이벤트를 건너뛰고 곧바로 text_delta가 시작하므로 first-text-token까지의 시간이 줄어든다. 단, thinking 토큰 과금은 그대로다.

Sonnet 5와 Opus 4.8·4.7에서 display를 지정하지 않으면 기본값이 "omitted"다. 화면에 추론 과정을 보여 주려면 반드시 명시해야 한다.

# Opus 4.8에서 요약된 thinking을 보려면 명시 필요
thinking={"type": "adaptive", "display": "summarized"}

과금: 보이는 것과 청구되는 것이 다르다

Adaptive thinking의 과금 구조를 잘못 이해하면 예산 계획이 틀어진다.

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=20000,
    thinking={"type": "adaptive", "display": "summarized"},
    messages=[...]
)

print(response.usage)
# {
#   "input_tokens": 120,
#   "output_tokens": 1850,   ← 과금 기준 (full thinking 포함)
#   "output_tokens_details": {
#     "thinking_tokens": 1620   ← 내부 추론에 쓴 토큰
#   }
# }
# 응답 텍스트에 보이는 토큰은 ~230개뿐이지만 1850개 청구

summarized 모드에서 응답에 보이는 요약 텍스트 길이와 output_tokens가 일치하지 않는다. thinking_tokens를 빼면 실제 텍스트 출력 토큰 수를 추정할 수 있다.

비용 관리 기준점은 다음과 같다.

  • max_tokens를 hard ceiling으로 쓴다. thinking + 텍스트 합산이 여기서 멈춘다.
  • effort는 soft guidance다. 같은 high에서도 요청 복잡도에 따라 thinking 소비량이 크게 달라진다.
  • stop_reason: "max_tokens"가 자주 나오면 max_tokens를 올리거나 effort를 낮춘다.
  • 관측은 output_tokens_details.thinking_tokens로 한다.

프롬프트로 thinking을 조정할 수 있다

Adaptive thinking은 프롬프트로 동작을 조정할 수 있다. 시스템 프롬프트에 다음과 같이 명시하면 thinking이 덜 일어난다.

Extended thinking은 다단계 추론이 필요한 경우에만 쓴다.
단순 질문에는 바로 답하라.

반대로 추론을 유도하려면 이렇게 한다.

이 작업은 다단계 추론이 필요하다. 답하기 전에 신중히 생각하라.

사용자 메시지에서 turn별로도 조정할 수 있다. "답변하기 전에 깊이 생각해 줘"는 해당 turn에서 thinking을 유도하고, "바로 답해줘"는 억제한다.

이 방식은 effort 레벨 조정보다 정밀하지 않다. 동일한 문구라도 모델과 맥락에 따라 효과가 다를 수 있다. 품질 차이를 측정하지 않은 채 thinking 억제 프롬프트를 프로덕션에 적용하면 안 된다.


프롬프트 캐시와 multi-turn 주의점

Adaptive thinking과 프롬프트 캐싱은 함께 쓸 수 있지만 몇 가지 동작을 알아야 한다.

  • 같은 thinking.type: "adaptive" 설정을 유지하면 메시지 레벨 캐시가 보존된다.
  • adaptiveenabled/disabled 사이를 전환하면 메시지 레벨 캐시가 무효화된다. 시스템 프롬프트 캐시는 유지된다.
  • multi-turn에서 Opus 4.6+와 Sonnet 4.6+는 thinking 블록을 기본적으로 컨텍스트에 유지한다. 이전 모델(Opus 4.5 이하)은 thinking 블록을 제거한다.
  • 모델을 전환할 때(예: 거절 후 fallback) 이전 어시스턴트 턴의 thinking 블록을 제거해야 한다. thinking 블록은 생성한 모델과 묶여 있다.

신규 모델의 추가 제약

Fable 5, Mythos 5, Mythos Preview, Opus 4.8, Opus 4.7, Sonnet 5에서는 temperature, top_p, top_k를 기본값이 아닌 값으로 설정하면 400 오류가 반환된다. 이 제약은 thinking 활성화 여부와 무관하게 이들 모델의 모든 요청에 적용된다.

기존 파이프라인에서 temperature를 조정해 응답 스타일을 바꾸던 패턴은 이들 모델로 마이그레이션할 때 제거해야 한다.


마이그레이션 체크리스트

Opus 4.6 / Sonnet 4.6에서 Opus 4.8 / Sonnet 5로 이전 시

  • [ ] thinking: {type: "enabled", budget_tokens: N}thinking: {type: "adaptive"}로 교체했는가?
  • [ ] output_config: {effort: "..."}를 적절한 레벨로 설정했는가?
  • [ ] max_tokens가 thinking + 텍스트 합산에 충분한 값인가?
  • [ ] 응답에 thinking 텍스트를 표시해야 한다면 display: "summarized"를 명시했는가? (기본값이 "omitted"로 바뀜)
  • [ ] temperature, top_p, top_k 사용 코드를 제거했는가?
  • [ ] multi-turn 루프에서 thinking 블록을 수정 없이 그대로 포함하는가?
  • [ ] 도구 호출 시 tool_choice: "any" 또는 named tool selection을 제거했는가?
  • [ ] output_tokens_details.thinking_tokens로 과금을 모니터링하고 있는가?

프로덕션 배포 기준

  • [ ] effort 레벨별 응답 품질을 실제 워크로드로 비교 측정했는가?
  • [ ] thinking이 있는 경우와 없는 경우(effort: low, 단순 쿼리)의 비용 차이를 확인했는가?
  • [ ] stop_reason: "max_tokens" 비율을 모니터링하는가?
  • [ ] thinking 억제 프롬프트가 품질에 미치는 영향을 측정했는가?

정리

Adaptive Thinking은 budget_tokens를 효과적으로 쓰는 방법의 문제가 아니라, thinking 토큰 배분을 모델에 위임하는 API 패러다임의 전환이다.

개발자가 기억할 구분은 세 가지다. 첫째, effort는 soft guidance이고 max_tokens가 실제 hard ceiling이다. 둘째, display: "omitted"는 latency를 줄이지만 과금은 줄이지 않는다. 셋째, Opus 4.8·4.7에서는 thinking이 기본으로 꺼져 있어 반드시 명시해야 하고, Sonnet 5에서는 기본으로 켜져 있어 끄려면 명시해야 한다.

budget_tokens는 Opus 4.6·Sonnet 4.6에서 아직 동작하지만 deprecated 상태다. 신규 애플리케이션은 adaptive로 시작하고, 기존 코드는 위 체크리스트를 따라 마이그레이션 계획을 세우는 것이 안전하다.

References