Loading...
    • 개발자 가이드
    • API 참고자료
    • MCP
    • 리소스
    • 릴리스 노트
    Search...
    ⌘K

    첫 번째 단계

    Claude 소개빠른 시작

    모델 및 가격

    모델 개요모델 선택하기Claude 4.5의 새로운 기능Claude 4.5로 마이그레이션모델 지원 중단가격 정책

    Claude로 빌드하기

    기능 개요Messages API 작업컨텍스트 윈도우프롬프트 작성 모범 사례

    기능

    프롬프트 캐싱컨텍스트 편집확장된 사고스트리밍 메시지배치 처리인용다국어 지원토큰 카운팅임베딩비전PDF 지원Files API검색 결과Google Sheets 애드온

    도구

    개요도구 사용을 구현하는 방법토큰 효율적인 도구 사용세밀한 도구 스트리밍Bash 도구코드 실행 도구컴퓨터 사용 도구텍스트 편집기 도구웹 페치 도구웹 검색 도구메모리 도구

    에이전트 스킬

    개요빠른 시작Skill 작성 모범 사례Skills 사용하기

    Agent SDK

    개요Agent SDK 참조 - TypeScriptPython SDK

    가이드

    스트리밍 입력권한 처리세션 관리Agent SDK 호스팅시스템 프롬프트 수정하기SDK에서의 MCP사용자 정의 도구SDK의 서브에이전트SDK의 슬래시 명령어SDK의 에이전트 스킬비용 및 사용량 추적할 일 목록SDK의 플러그인

    API의 MCP

    MCP 커넥터원격 MCP 서버

    타사 플랫폼의 Claude

    Amazon BedrockVertex AI

    프롬프트 엔지니어링

    개요프롬프트 생성기프롬프트 템플릿 사용하기프롬프트 개선기명확하고 직접적으로예시(멀티샷 프롬프팅) 사용Claude가 생각하도록 하기(CoT)XML 태그 사용Claude에게 역할 부여하기 (시스템 프롬프트)Claude의 응답 미리 채우기복잡한 프롬프트 체이닝긴 컨텍스트 팁확장 사고 팁

    테스트 및 평가

    성공 기준 정의하기테스트 케이스 개발평가 도구 사용하기지연 시간 줄이기

    보안 강화

    환각 현상 줄이기출력 일관성 높이기탈옥 완화handle-streaming-refusals프롬프트 유출 감소Claude의 캐릭터 유지

    관리 및 모니터링

    Admin API 개요사용량 및 비용 APIClaude Code Analytics API
    Console
    Documentation

    중단 이유 처리

    Claude의 응답에서 stop_reason 필드를 이해하고 처리하는 방법을 알아보세요.

    Messages API에 요청을 보낼 때, Claude의 응답에는 모델이 응답 생성을 중단한 이유를 나타내는 stop_reason 필드가 포함됩니다. 이러한 값들을 이해하는 것은 다양한 응답 유형을 적절히 처리하는 견고한 애플리케이션을 구축하는 데 중요합니다.

    API 응답에서 stop_reason에 대한 자세한 내용은 Messages API 참조를 참조하세요.

    stop_reason이란 무엇인가요?

    stop_reason 필드는 모든 성공적인 Messages API 응답의 일부입니다. 요청 처리 실패를 나타내는 오류와 달리, stop_reason은 Claude가 응답 생성을 성공적으로 완료한 이유를 알려줍니다.

    응답 예시
    {
      "id": "msg_01234",
      "type": "message",
      "role": "assistant",
      "content": [
        {
          "type": "text",
          "text": "여기 질문에 대한 답변입니다..."
        }
      ],
      "stop_reason": "end_turn",
      "stop_sequence": null,
      "usage": {
        "input_tokens": 100,
        "output_tokens": 50
      }
    }

    중단 이유 값들

    end_turn

    가장 일반적인 중단 이유입니다. Claude가 응답을 자연스럽게 완료했음을 나타냅니다.

    if response.stop_reason == "end_turn":
        # 완전한 응답 처리
        print(response.content[0].text)

    end_turn과 함께 나타나는 빈 응답

    때때로 Claude는 stop_reason: "end_turn"과 함께 빈 응답(내용 없이 정확히 2-3개 토큰)을 반환합니다. 이는 일반적으로 Claude가 어시스턴트 턴이 완료되었다고 해석할 때 발생하며, 특히 도구 결과 이후에 자주 나타납니다.

    일반적인 원인:

    • 도구 결과 직후에 텍스트 블록 추가 (Claude는 사용자가 항상 도구 결과 후에 텍스트를 삽입할 것으로 학습하므로, 패턴을 따르기 위해 턴을 종료합니다)
    • 아무것도 추가하지 않고 Claude의 완료된 응답을 다시 보내기 (Claude는 이미 완료되었다고 결정했으므로, 완료된 상태를 유지합니다)

    빈 응답을 방지하는 방법:

    # 잘못된 방법: tool_result 직후에 텍스트 추가
    messages = [
        {"role": "user", "content": "1234와 5678의 합을 계산해주세요"},
        {"role": "assistant", "content": [
            {
                "type": "tool_use",
                "id": "toolu_123",
                "name": "calculator",
                "input": {"operation": "add", "a": 1234, "b": 5678}
            }
        ]},
        {"role": "user", "content": [
            {
                "type": "tool_result",
                "tool_use_id": "toolu_123",
                "content": "6912"
            },
            {
                "type": "text",
                "text": "결과입니다"  # tool_result 후에 텍스트를 추가하지 마세요
            }
        ]}
    ]
    
    # 올바른 방법: 추가 텍스트 없이 도구 결과만 직접 보내기
    messages = [
        {"role": "user", "content": "1234와 5678의 합을 계산해주세요"},
        {"role": "assistant", "content": [
            {
                "type": "tool_use",
                "id": "toolu_123",
                "name": "calculator",
                "input": {"operation": "add", "a": 1234, "b": 5678}
            }
        ]},
        {"role": "user", "content": [
            {
                "type": "tool_result",
                "tool_use_id": "toolu_123",
                "content": "6912"
            }
        ]}  # tool_result만, 추가 텍스트 없음
    ]
    
    # 위의 방법을 수정한 후에도 여전히 빈 응답을 받는 경우:
    def handle_empty_response(client, messages):
        response = client.messages.create(
            model="claude-sonnet-4-20250514",
            max_tokens=1024,
            messages=messages
        )
    
        # 응답이 비어있는지 확인
        if (response.stop_reason == "end_turn" and
            not response.content):
    
            # 잘못된 방법: 빈 응답으로 단순히 재시도하지 마세요
            # Claude가 이미 완료되었다고 결정했으므로 작동하지 않습니다
    
            # 올바른 방법: 새로운 사용자 메시지에 계속 진행 프롬프트 추가
            messages.append({"role": "user", "content": "계속해주세요"})
    
            response = client.messages.create(
                model="claude-sonnet-4-20250514",
                max_tokens=1024,
                messages=messages
            )
    
        return response

    모범 사례:

    1. 도구 결과 직후에 텍스트 블록을 절대 추가하지 마세요 - 이는 Claude에게 모든 도구 사용 후에 사용자 입력을 기대하도록 가르칩니다
    2. 수정 없이 빈 응답을 재시도하지 마세요 - 빈 응답을 단순히 다시 보내는 것은 도움이 되지 않습니다
    3. 계속 진행 프롬프트는 최후의 수단으로 사용하세요 - 위의 수정 사항으로 문제가 해결되지 않는 경우에만 사용하세요

    max_tokens

    Claude가 요청에서 지정된 max_tokens 제한에 도달했기 때문에 중단되었습니다.

    # 제한된 토큰으로 요청
    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=10,
        messages=[{"role": "user", "content": "양자 물리학을 설명해주세요"}]
    )
    
    if response.stop_reason == "max_tokens":
        # 응답이 잘렸습니다
        print("응답이 토큰 제한에서 잘렸습니다")
        # 계속하기 위해 다른 요청을 고려하세요

    stop_sequence

    Claude가 사용자 정의 중단 시퀀스 중 하나를 만났습니다.

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        stop_sequences=["END", "STOP"],
        messages=[{"role": "user", "content": "END라고 말할 때까지 텍스트를 생성해주세요"}]
    )
    
    if response.stop_reason == "stop_sequence":
        print(f"시퀀스에서 중단됨: {response.stop_sequence}")

    tool_use

    Claude가 도구를 호출하고 있으며 실행을 기대합니다.

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        tools=[weather_tool],
        messages=[{"role": "user", "content": "날씨가 어떤가요?"}]
    )
    
    if response.stop_reason == "tool_use":
        # 도구 추출 및 실행
        for content in response.content:
            if content.type == "tool_use":
                result = execute_tool(content.name, content.input)
                # 최종 응답을 위해 Claude에게 결과 반환

    pause_turn

    Claude가 장시간 실행되는 작업을 일시 중지해야 할 때 웹 검색과 같은 서버 도구와 함께 사용됩니다.

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        tools=[{"type": "web_search_20250305", "name": "web_search"}],
        messages=[{"role": "user", "content": "최신 AI 뉴스를 검색해주세요"}]
    )
    
    if response.stop_reason == "pause_turn":
        # 대화 계속
        messages = [
            {"role": "user", "content": original_query},
            {"role": "assistant", "content": response.content}
        ]
        continuation = client.messages.create(
            model="claude-sonnet-4-5",
            messages=messages,
            tools=[{"type": "web_search_20250305", "name": "web_search"}]
        )

    refusal

    Claude가 안전 문제로 인해 응답 생성을 거부했습니다.

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": "[안전하지 않은 요청]"}]
    )
    
    if response.stop_reason == "refusal":
        # Claude가 응답을 거부했습니다
        print("Claude가 이 요청을 처리할 수 없습니다")
        # 요청을 다시 표현하거나 수정하는 것을 고려하세요

    Claude Sonnet 4.5 또는 Opus 4.1을 사용하면서 refusal 중단 이유를 자주 접하는 경우, API 호출을 Sonnet 4 (claude-sonnet-4-20250514)로 업데이트해 볼 수 있습니다. 이 모델은 다른 사용 제한이 있습니다. Sonnet 4.5의 API 안전 필터 이해하기에서 자세히 알아보세요.

    Claude Sonnet 4.5의 API 안전 필터에 의해 트리거되는 거부에 대해 자세히 알아보려면 Sonnet 4.5의 API 안전 필터 이해하기를 참조하세요.

    model_context_window_exceeded

    Claude가 모델의 컨텍스트 윈도우 제한에 도달했기 때문에 중단되었습니다. 이를 통해 정확한 입력 크기를 알지 못해도 최대한 많은 토큰을 요청할 수 있습니다.

    # 가능한 한 많이 얻기 위해 최대 토큰으로 요청
    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=64000,  # 모델의 최대 출력 토큰
        messages=[{"role": "user", "content": "컨텍스트 윈도우의 대부분을 사용하는 큰 입력..."}]
    )
    
    if response.stop_reason == "model_context_window_exceeded":
        # 응답이 max_tokens 전에 컨텍스트 윈도우 제한에 도달했습니다
        print("응답이 모델의 컨텍스트 윈도우 제한에 도달했습니다")
        # 응답은 여전히 유효하지만 컨텍스트 윈도우에 의해 제한되었습니다

    이 중단 이유는 Sonnet 4.5 및 최신 모델에서 기본적으로 사용할 수 있습니다. 이전 모델의 경우 이 동작을 활성화하려면 베타 헤더 model-context-window-exceeded-2025-08-26을 사용하세요.

    중단 이유 처리 모범 사례

    1. 항상 stop_reason 확인하기

    응답 처리 로직에서 stop_reason을 확인하는 습관을 만드세요:

    def handle_response(response):
        if response.stop_reason == "tool_use":
            return handle_tool_use(response)
        elif response.stop_reason == "max_tokens":
            return handle_truncation(response)
        elif response.stop_reason == "model_context_window_exceeded":
            return handle_context_limit(response)
        elif response.stop_reason == "pause_turn":
            return handle_pause(response)
        elif response.stop_reason == "refusal":
            return handle_refusal(response)
        else:
            # end_turn 및 기타 경우 처리
            return response.content[0].text

    2. 잘린 응답을 우아하게 처리하기

    토큰 제한이나 컨텍스트 윈도우로 인해 응답이 잘린 경우:

    def handle_truncated_response(response):
        if response.stop_reason in ["max_tokens", "model_context_window_exceeded"]:
            # 옵션 1: 특정 제한에 대해 사용자에게 경고
            if response.stop_reason == "max_tokens":
                message = "[max_tokens 제한으로 인해 응답이 잘렸습니다]"
            else:
                message = "[컨텍스트 윈도우 제한으로 인해 응답이 잘렸습니다]"
            return f"{response.content[0].text}\n\n{message}"
    
            # 옵션 2: 생성 계속하기
            messages = [
                {"role": "user", "content": original_prompt},
                {"role": "assistant", "content": response.content[0].text}
            ]
            continuation = client.messages.create(
                model="claude-sonnet-4-5",
                max_tokens=1024,
                messages=messages + [{"role": "user", "content": "계속해주세요"}]
            )
            return response.content[0].text + continuation.content[0].text

    3. pause_turn에 대한 재시도 로직 구현

    일시 중지될 수 있는 서버 도구의 경우:

    def handle_paused_conversation(initial_response, max_retries=3):
        response = initial_response
        messages = [{"role": "user", "content": original_query}]
        
        for attempt in range(max_retries):
            if response.stop_reason != "pause_turn":
                break
                
            messages.append({"role": "assistant", "content": response.content})
            response = client.messages.create(
                model="claude-sonnet-4-5",
                messages=messages,
                tools=original_tools
            )
        
        return response

    중단 이유 vs. 오류

    stop_reason 값과 실제 오류를 구별하는 것이 중요합니다:

    중단 이유 (성공적인 응답)

    • 응답 본문의 일부
    • 생성이 정상적으로 중단된 이유를 나타냄
    • 응답에 유효한 내용 포함

    오류 (실패한 요청)

    • HTTP 상태 코드 4xx 또는 5xx
    • 요청 처리 실패를 나타냄
    • 응답에 오류 세부 정보 포함
    try:
        response = client.messages.create(...)
        
        # stop_reason으로 성공적인 응답 처리
        if response.stop_reason == "max_tokens":
            print("응답이 잘렸습니다")
        
    except anthropic.APIError as e:
        # 실제 오류 처리
        if e.status_code == 429:
            print("속도 제한 초과")
        elif e.status_code == 500:
            print("서버 오류")

    스트리밍 고려사항

    스트리밍을 사용할 때 stop_reason은:

    • 초기 message_start 이벤트에서 null
    • message_delta 이벤트에서 제공됨
    • 다른 이벤트에서는 제공되지 않음
    with client.messages.stream(...) as stream:
        for event in stream:
            if event.type == "message_delta":
                stop_reason = event.delta.stop_reason
                if stop_reason:
                    print(f"스트림이 다음으로 종료됨: {stop_reason}")

    일반적인 패턴

    도구 사용 워크플로 처리

    def complete_tool_workflow(client, user_query, tools):
        messages = [{"role": "user", "content": user_query}]
        
        while True:
            response = client.messages.create(
                model="claude-sonnet-4-5",
                messages=messages,
                tools=tools
            )
            
            if response.stop_reason == "tool_use":
                # 도구 실행 및 계속
                tool_results = execute_tools(response.content)
                messages.append({"role": "assistant", "content": response.content})
                messages.append({"role": "user", "content": tool_results})
            else:
                # 최종 응답
                return response

    완전한 응답 보장

    def get_complete_response(client, prompt, max_attempts=3):
        messages = [{"role": "user", "content": prompt}]
        full_response = ""
    
        for _ in range(max_attempts):
            response = client.messages.create(
                model="claude-sonnet-4-5",
                messages=messages,
                max_tokens=4096
            )
    
            full_response += response.content[0].text
    
            if response.stop_reason != "max_tokens":
                break
    
            # 중단된 지점부터 계속
            messages = [
                {"role": "user", "content": prompt},
                {"role": "assistant", "content": full_response},
                {"role": "user", "content": "중단된 지점부터 계속해주세요."}
            ]
    
        return full_response

    입력 크기를 모르고 최대 토큰 얻기

    model_context_window_exceeded 중단 이유를 사용하면 입력 크기를 계산하지 않고도 최대한 많은 토큰을 요청할 수 있습니다:

    def get_max_possible_tokens(client, prompt):
        """
        입력 토큰 수를 계산할 필요 없이 모델의 컨텍스트 윈도우 내에서
        가능한 한 많은 토큰을 얻습니다
        """
        response = client.messages.create(
            model="claude-sonnet-4-5",
            messages=[{"role": "user", "content": prompt}],
            max_tokens=64000  # 모델의 최대 출력 토큰으로 설정
        )
    
        if response.stop_reason == "model_context_window_exceeded":
            # 입력 크기를 고려하여 최대한 많은 토큰을 얻었습니다
            print(f"{response.usage.output_tokens}개 토큰 생성됨 (컨텍스트 제한 도달)")
        elif response.stop_reason == "max_tokens":
            # 요청된 토큰을 정확히 얻었습니다
            print(f"{response.usage.output_tokens}개 토큰 생성됨 (max_tokens 도달)")
        else:
            # 자연스러운 완료
            print(f"{response.usage.output_tokens}개 토큰 생성됨 (자연스러운 완료)")
    
        return response.content[0].text

    stop_reason 값을 적절히 처리함으로써 다양한 응답 시나리오를 우아하게 처리하고 더 나은 사용자 경험을 제공하는 더욱 견고한 애플리케이션을 구축할 수 있습니다.

    • stop_reason이란 무엇인가요?
    • end_turn
    • max_tokens
    • stop_sequence
    • tool_use
    • pause_turn
    • refusal
    • model_context_window_exceeded
    • 1. 항상 stop_reason 확인하기
    • 2. 잘린 응답을 우아하게 처리하기
    • 3. pause_turn에 대한 재시도 로직 구현
    • 중단 이유 vs. 오류
    © 2025 ANTHROPIC PBC

    Products

    • Claude
    • Claude Code
    • Max plan
    • Team plan
    • Enterprise plan
    • Download app
    • Pricing
    • Log in

    Features

    • Claude and Slack
    • Claude in Excel

    Models

    • Opus
    • Sonnet
    • Haiku

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Claude Developer Platform

    • Overview
    • Developer docs
    • Pricing
    • Amazon Bedrock
    • Google Cloud’s Vertex AI
    • Console login

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Help and security

    • Availability
    • Status
    • Support center

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy

    Products

    • Claude
    • Claude Code
    • Max plan
    • Team plan
    • Enterprise plan
    • Download app
    • Pricing
    • Log in

    Features

    • Claude and Slack
    • Claude in Excel

    Models

    • Opus
    • Sonnet
    • Haiku

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Claude Developer Platform

    • Overview
    • Developer docs
    • Pricing
    • Amazon Bedrock
    • Google Cloud’s Vertex AI
    • Console login

    Learn

    • Blog
    • Catalog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Help and security

    • Availability
    • Status
    • Support center

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy
    © 2025 ANTHROPIC PBC