byteforce

CPN 한국어 자습서 · 러닝패스 2 / 4 — Building with the Claude API

Claude의 기능

확장된 사고

Extended thinking

확장된 사고는 Claude가 최종 답을 내기 전에 추론할 시간을 줍니다. 더 복잡한 작업을 더 정확히 다루지만, 사고 단계의 토큰에 과금되고 지연도 늘어납니다. 응답에는 새 블록인 thinking 블록이 추가되고, 그 안에는 변조를 막는 signature가 들어갑니다.

전체 내레이션영상 나레이션 한국어 번역 (전체)

Stephen Grider · Anthropic 기술 스태프

Claude의 좀 더 고급 기능인 확장된 사고를 살펴봅니다. 확장된 사고는 Claude가 사용자의 질문에 대해 최종 응답을 생성하기 전에 추론할 시간을 줍니다. 많은 채팅 UI에서는 이 과정이 별도의 사고 과정으로 표시되며, 사용자는 원하면 그것을 펼쳐 Claude가 문제에 어떻게 접근하는지 더 잘 파악할 수 있습니다.

일반적으로 확장된 사고를 켜면 Claude가 더 복잡한 작업을 더 높은 정확도로 처리할 수 있습니다. 다만 큰 트레이드오프가 있습니다. 사고 단계에서 Claude가 생성한 토큰에 과금되고, 그 단계 자체가 완료되는 데 시간이 걸립니다. 지능이 높아지는 대신 비용이 오르고 지연도 함께 늘어납니다.

확장된 사고에서 흔한 고민은 언제 켤지입니다. 답은 아주 단순합니다 — 프롬프트 평가(eval)에 의존합니다. 먼저 프롬프트를 작성하고, 그것으로 eval을 돌립니다. 그래서 정확도가 원하는 수준에 못 미치고, 게다가 프롬프트 개선에 이미 충분히 공을 들였다면, 그때가 바로 확장된 사고를 켜는 것을 고려할 시점입니다.

사용법은 꽤 직관적입니다. 평소 Claude를 쓸 때 우리는 text 블록이 든 user 메시지를 보내고, 역시 text 블록이 든 assistant 메시지를 돌려받습니다. 확장된 사고를 켜기 시작하면, 돌려받는 응답에 지금까지 본 적 없는 새 블록 타입 — thinking 블록 — 이 포함됩니다. 이 thinking 블록 안에는 Claude가 사고하는 동안 생성한 텍스트가 들어 있습니다.

이 thinking 블록에는 바로 보여 드리고 싶은 흥미로운 점이 있습니다. 확장된 사고를 켜고 코드를 짜 요청을 보내자마자 금방 보게 될 것이기 때문입니다. thinking 블록 안에는 signature라는 것이 있습니다. signature는 암호화 토큰입니다. 이 메시지를 나중에 대화의 일부로 Claude에게 다시 보내고 싶을 때, Claude는 당신이 thinking 블록의 텍스트를 어떤 식으로도 수정하지 않았는지 확인하고 싶어 합니다. signature가 바로 그 텍스트가 바뀌지 않았음을 보장합니다.

Claude는 그 텍스트가 전혀 바뀌지 않기를 바랍니다. 응답 생성 과정에서 그 텍스트에 매우 크게 의존하기 때문입니다. 만약 개발자가 그 텍스트를 수정할 수 있다면, Claude를 안전하지 않은 방향으로 유도할 수도 있습니다.

이와 관련해 사고에는 또 하나의 측면이 있습니다. 어떤 경우에는 사고 텍스트가 전혀 없이 redacted 콘텐츠 필드만 든 thinking 블록을 돌려받을 수 있습니다. 이는 Claude가 생성한 사고 텍스트가 내부 안전 시스템에 걸렸을 때 발생합니다. redacted 콘텐츠는 실제 사고 텍스트이지만 완전히 암호화된 형태입니다. 나중에 이 전체 메시지를 대화의 일부로 Claude에게 그대로 돌려주면, Claude가 이전 사고의 맥락을 잃지 않도록 제공되는 것입니다.

이제 코드를 봅니다. 새 노트북 001 thinking입니다. 확장된 사고를 켜려면 chat 함수를 찾아 인자를 추가합니다 — 기본값 false인 thinking, 그리고 1024인 thinking_budget. thinking budget은 Claude가 응답의 사고 부분을 생성할 때 쓸 수 있는 토큰 수입니다. 최솟값은 1024라서 그보다 작은 값은 둘 수 없습니다. Claude가 1024 토큰을 다 쓰지 않을 수도 있지만, 어쨌든 우리가 budget으로 지정할 수 있는 최솟값입니다.

thinking budget에 관해 꼭 이해해야 할 또 한 가지 — max_tokens가 thinking budget보다 커야 합니다. 예를 들어 thinking budget이 1024라면 max_tokens는 최소 1025여야 합니다. 그러면 실제 텍스트 생성에는 단 1토큰만 남습니다. 그래서 보통은 max_tokens를 thinking budget보다 훨씬 크게 둡니다. 제 경우엔 max_tokens를 4000으로 올립니다. 이러면 사고에 약 1000 토큰을 쓰고도 나머지 3000 토큰을 실제 텍스트 생성에 쓸 수 있는 넉넉한 버퍼가 생깁니다.

이 두 키워드 인자를 추가한 다음, params 딕셔너리에 파라미터를 더합니다. thinking이 켜져 있으면 params에 새 키 thinking을 추가합니다. 이건 type이 enabled, budget_tokens가 우리가 넘긴 thinking budget인 중첩 딕셔너리입니다. 그게 전부입니다. 셀을 실행하고 아래로 내려가 테스트합니다. Claude에게 재귀에 대한 한 문단 가이드를 써 달라고 하고, chat 호출에 thinking=True를 넘겨 확장된 사고를 켭니다.

응답을 보면 별개의 블록 두 개가 옵니다. 먼저 thinking 블록, 그리고 조금 아래에 text 블록의 시작이 있습니다. thinking 블록 안에는 실제로 signature가 있고, 그와 함께 사고 텍스트가 있습니다. signature의 목적은 그 사고 텍스트를 어떤 식으로도 건드리지 않았음을 보장하는 것이었죠. 그리고 text 블록에는 우리가 Claude에게 써 달라고 한 실제 가이드가 들어 있습니다.

마지막으로, 애플리케이션을 처음 만들고 테스트할 때 쓸 만한 것을 보여 드립니다. Claude가 redacted thinking 블록을 보내는 시나리오가 있을 수 있는데, 애플리케이션을 만들 때 그런 블록이 왔을 때 코드가 제대로 동작하는지 확인하고 싶을 수 있습니다. 사실 우리는 Claude가 redacted thinking 블록을 보내도록 강제할 수 있습니다. 아주 특별한 형식의 문자열을 보내면 됩니다.

두 번째 셀 맨 위를 보면 thinking_test_str이 있고, 그 값은 ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING 뒤에 특수한 숫자와 글자가 붙은 형태입니다. 이 문자열을 정확히 Claude에 보내면 redacted thinking 블록을 반드시 돌려받습니다. 물론 이건 그런 응답을 처리할 수 있는지 테스트하려는 목적입니다. 맨 아래 셀에서 그 문자열만 담은 user 메시지를 추가해 보냅니다. 그러면 redacted thinking 블록이 든 응답이 옵니다 — type이 redacted_thinking이고 data만 있는 블록입니다. 이렇게 예상치 못한 thinking 블록을 받아도 애플리케이션이 죽지 않도록 확인할 수 있습니다.

이 장에서 배우는 것What you'll learn

약 7분
1

확장된 사고 = 최종 답 전에 추론할 시간. 정확도↑, 비용·지연 트레이드오프

2

언제 켜나? 프롬프트 평가(eval)에 의존 — 개선해도 정확도가 부족할 때

3

응답에 새 블록 thinking 추가 — 안에 signature(암호화 토큰)

4

signature = 사고 텍스트 변조 방지(안전한 방향 유지)

5

redacted thinking = 안전 시스템에 걸린 사고가 암호화 형태로 — 그대로 돌려주면 맥락 유지

6

budget≥1024 & max_tokens > budget 필수 — 보통 4000처럼 넉넉히

먼저 짚고 갈 용어
확장된 사고 (extended thinking)
Claude가 최종 답 전에 추론하도록 켜는 기능. 정확도가 오르는 대신 토큰 과금·지연이 늘어난다.
thinking 블록
확장된 사고를 켜면 응답에 추가되는 새 블록. 안에 사고 텍스트와 signature가 들어 있다.
signature
thinking 블록 안의 암호화 토큰. 사고 텍스트를 바꾸지 않았음을 검증해 변조(악용)를 막는다.
redacted thinking
내부 안전 시스템에 걸린 사고가 암호화된 형태로 온 블록(type:redacted_thinking, data만). 그대로 돌려주면 맥락이 유지된다.
thinking_budget
사고에 허용할 토큰 수. 최소 1024이며, max_tokens는 이보다 커야 한다.

확장된 사고란

Time to reason first

확장된 사고는 Claude가 최종 답을 내기 전에 추론할 시간을 줍니다. 복잡한 작업을 더 정확히 처리하지만, 사고 단계에서 생성한 토큰에 과금되고 지연도 늘어납니다 — 지능이 오르는 만큼 비용·지연이 따라옵니다.

언제 켜나?

정답은 단순합니다 — 프롬프트 평가(eval)에 의존합니다. 프롬프트를 작성해 eval을 돌렸는데 정확도가 부족하고, 게다가 프롬프트 개선에 이미 충분히 공을 들였다면 그때 켭니다. 무작정 처음부터 켜는 기능이 아닙니다.

응답 블록 비교 · 확장된 사고 끔 / 켬

chat 함수에 thinking 켜기

Enable on the request

평소 쓰던 chat 함수에 인자 두 개만 더합니다 — thinking(기본 꺼짐)과 thinking_budget. 켜져 있으면 params에 thinking={type:"enabled", budget_tokens:…}를 넣습니다.

001_thinking.ipynb · chat 함수 확장
# chat 함수에 thinking 인자 추가 (기본 꺼짐, budget 최소 1024)
def chat(messages, system=None, temperature=1.0,
         stop_sequences=[], tools=None,
         thinking=False, thinking_budget=1024):
    params = {
        "model": model,
        "max_tokens": 4000,   # max_tokens > thinking_budget 필수
        "messages": messages,
        "temperature": temperature,
        "stop_sequences": stop_sequences,
    }
    if thinking:
        params["thinking"] = {
            "type": "enabled",
            "budget_tokens": thinking_budget,
        }
    if tools:  params["tools"]  = tools
    if system: params["system"] = system
    return client.messages.create(**params)

두 가지 규칙이 있습니다. thinking_budget최솟값은 1024이고(그보다 작게 둘 수 없음), max_tokens는 budget보다 커야 합니다. budget이 1024인데 max_tokens도 1025면 텍스트엔 단 1토큰만 남습니다. 그래서 보통 4000처럼 넉넉히 둡니다 — 사고에 약 1000, 텍스트에 약 3000을 쓸 수 있습니다.

예산 / max_tokens 관계 · 슬라이더
사고
텍스트
사고에 쓰는 예산실제 텍스트에 남는 분량

규칙 ① thinking_budget ≥ 1024   규칙 ② max_tokens > thinking_budget. 둘째 규칙을 어기면 텍스트에 남는 토큰이 없거나 요청 자체가 거부됩니다.

응답 구조 · 두 블록

thinking + text

재귀를 설명해 달라고 하면서 thinking=True를 넘기면, 응답에 별개의 블록 두 개가 옵니다 — 먼저 thinking 블록(signature + 사고 텍스트), 그다음 text 블록(실제 답).

001_thinking.ipynb · 확장된 사고로 요청
messages = []
add_user_message(messages, "한 문단으로 재귀를 설명해 줘")

response = chat(messages, thinking=True)   # 확장된 사고 켜기
response.content
출력 · 응답 블록(thinking + text)
[
  ThinkingBlock(
    type="thinking",
    signature="ErcBCkgIB...<암호화 토큰>...RhA=",
    thinking="재귀를 설명하려면 먼저 함수가 자기 자신을…"
  ),
  TextBlock(
    type="text",
    text="재귀(recursion)는 함수가 자기 자신을 호출하여…"
  )
]

응답을 미래의 대화로 다시 보낼 때, Claude는 signature로 사고 텍스트가 변조되지 않았음을 검증합니다. 응답 생성에서 그 텍스트에 크게 의존하므로, 개발자가 사고를 고쳐 안전하지 않은 방향으로 유도하는 것을 막습니다.

redacted thinking · 테스트

Force a redacted block

사고 텍스트가 내부 안전 시스템에 걸리면, 텍스트 없이 암호화된 redacted_thinking 블록이 옵니다. 애플리케이션이 이런 블록을 받아도 죽지 않는지 확인하려면, 매직 스트링으로 강제 발생시킬 수 있습니다.

001_thinking.ipynb · redacted 강제 테스트
# redacted thinking 블록을 강제로 받아 처리 코드를 테스트하는 매직 스트링
thinking_test_str = "ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING_46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB"

messages = []
add_user_message(messages, thinking_test_str)
response = chat(messages, thinking=True)
response.content
출력 · redacted_thinking 블록
[
  RedactedThinkingBlock(
    type="redacted_thinking",
    data="EvgGCkYIB...<암호화된 사고 데이터>...c3Q="
  ),
  TextBlock(type="text", text="…")
]
핵심 정리
  • 확장된 사고 = 최종 답 전에 추론할 시간. 정확도↑이지만 토큰 과금·지연 트레이드오프.
  • 언제 켜나 → 프롬프트 평가에 의존. 개선해도 정확도가 부족할 때.
  • 응답에 thinking 블록(+signature) 추가 — signature가 사고 텍스트 변조를 막는다.
  • redacted_thinking은 그대로 돌려줘야 맥락 유지. 매직 스트링으로 처리 코드를 테스트.
  • thinking_budget ≥ 1024 그리고 max_tokens > thinking_budget(보통 4000).

Q1확장된 사고는 언제 켜는 것이 권장되나요?

Q2signature는 무슨 역할을 하나요?

Q3thinking_budget이 1024일 때 max_tokens 조건은?

MEMBER SESSION REQUIRED · REGISTRATION IS FREE

여기부터는 등록한 분에게 열립니다.

전 코스는 계속 무료입니다. 등록하면 이 코스의 남은 76개 레슨을 끝까지 읽을 수 있습니다.

등록하고 이어서 읽기

이미 등록하셨다면 그때 쓰신 이메일을 넣어 주세요.