Claude Code Tools 심층 분석 #0 — 도구 메커니즘의 실제 작동 방식
요약
Claude Code 도구의 작동 메커니즘과 정의 방식을 심층 분석하는 시리즈의 첫 번째 포스트입니다. LLM의 한계를 극복하기 위한 도구의 역할과 JSON Schema를 활용한 도구 정의의 핵심 구성 요소를 설명합니다.
핵심 포인트
- 도구는 LLM이 외부 세계에 직접 작용하고 구조화된 출력을 생성하게 돕는 신뢰 채널임
- 도구 정의는 name, description, input_schema의 세 가지 핵심 필드로 구성됨
- 도구의 효과적인 설계는 명명, 도구 설명, 필드 설명, 스키마 유효성 검사의 계층적 접근이 필요함
이 시리즈의 각 포스트는 하나의 특정 Claude Code 도구를 해부할 것입니다. 하지만 그 전에, 공통된 기초가 필요합니다: 도구(tool)란 무엇이며, Claude는 이를 어떻게 사용하는가? 이후의 모든 심층 분석은 이 메커니즘을 바탕으로 구축됩니다.
도구가 존재하는 이유
LLM(대규모 언어 모델)은 그 자체만으로는 오직 **텍스트를 생성(generate text)**할 수 있을 뿐입니다. 이는 두 가지 근본적인 한계를 만듭니다:
- 외부 세계에 작용할 수 없습니다. “파일을 삭제했습니다”라는 문장을 생성하는 것이 실제로 무언가를 삭제하는 것은 아닙니다.
- 출력이 본질적으로 신뢰할 수 없습니다. 모델은 잘못된 구조를 반환하거나, 필드를 누락하거나, 내용을 환각(hallucination)할 수 있으며, 이는 결과물을 다운스트림(downstream) 프로그램이 소비하기에 안전하지 않게 만듭니다.
도구는 이 두 가지 간극을 메워줍니다:
- 동작 (Actions) — 도구는 실행 가능한 함수를 선언합니다. 모델이 도구를 호출하면, 하네스(harness)가 파일을 읽거나, 요청을 보내거나, 모드를 전환하는 등의 실제 작업을 수행합니다.
- 구조 (Structure) — JSON Schema가 입력을 정의합니다. 모델은 해당 스키마를 준수하는 인자(arguments)를 생성해야 하며, 유효하지 않은 입력은 실행 전에 거부될 수 있습니다.
이러한 관점에서 도구는 단순히 “LLM을 더 강력하게 만드는 것”이 아닙니다. 도구는 **LLM과 외부 세계 사이의 신뢰할 수 있는 채널(trusted channel)**을 생성합니다.
도구 정의의 모습
Anthropic API에서 도구 정의는 JSON 객체입니다. 다음은 AskUserQuestion의 단순화된 버전입니다:
{
"name": "AskUserQuestion",
"description": "Use this tool only when you are blocked on a decision that is genuinely the user's to make: one you cannot resolve from the request, the code, or sensible defaults. ...",
...
세 가지 최상위 필드가 있습니다:
name— 도구의 고유 식별자이자 모델이 해석할 수 있는 명명 신호(naming signal)description— 도구가 무엇을 하는지, 언제 사용해야 하는지, 그리고 언제 사용하지 말아야 하는지를 설명하는 자연어 가이드input_schema— 인자 구조, 필드 수준의 설명 및 유효성 검사 규칙을 정의하는 JSON Schema
그것이 도구 정의(tool definition)의 전부입니다. 정의 자체 내부에 숨겨진 설정은 없습니다. 모든 설계 의도는 이 세 가지 필드에 인코딩되어야 합니다.
도구 정의의 4가지 계층
이후 포스트에서는 네 가지 계층을 통해 각 도구를 분석할 것입니다. 이 계층들은 단순히 세 가지 최상위 필드를 확장하여 바라본 관점입니다:
| 계층 | 위치 | 목적 |
|---|---|---|
| 1. 명명 (Naming) | name 및 스키마 내부의 필드 이름 | 이름을 통해 의미를 전달함 |
| ... |
커버리지는 증가하는 반면 신호 밀도(signal density)는 감소합니다:
- 명명 (Naming) — 단 하나의 단어로부터 이해되며, 모델이 해당 필드를 마주할 때마다 강화됩니다.
- 도구 설명 (Tool description) — 모델이 도구 사용을 고려할 때마다 사용 가능하며, 광범위한 행동 경계를 정의합니다.
- 필드 설명 (Field description) — 모델이 해당 필드를 채우는 동안 가장 관련성이 높아지며, 정밀한 힌트를 제공합니다.
- 스키마 유효성 검사 (Schema validation) — 모델이 무언가 잘못했을 때 가시화되며, 강력한 가드레일 (guardrail) 역할을 합니다.
이 네 가지 계층이 모여 도구 정의의 완전한 프롬프팅 표면 (prompting surface)을 형성합니다.
Claude가 도구 정의를 "읽는" 방식
중요한 점은 사용 가능한 도구 정의가 도구가 선택된 후에 나타나는 것이 아니라, 모델 요청과 함께 전송된다는 것입니다.
흐름은 대략 다음과 같습니다:
- 하네스 (harness)가 사용 가능한 모든 도구 정의를 수집합니다.
- Claude에 대한 각 요청 시, API의
tools파라미터에 도구 목록을 포함합니다. - Claude는 요청 컨텍스트 (request context)의 일부로 시스템 지침 (system instructions), 사용 가능한 도구 정의, 그리고 대화 기록을 전달받습니다.
이는 두 가지 직접적인 결과를 초래합니다:
- 설명(description)의 모든 단어는 토큰 비용을 발생시킵니다. 만약 도구 정의(tool definitions)의 총합이 20 KB라면, 해당 페이로드는 여러 요청에 걸쳐 처리되어야 하며, 긴 대화가 이어질수록 비용이 누적됩니다.
- 도구 설명은 인접한 다른 도구를 참조할 수 있습니다. 모델은 사용 가능한 정의들을 함께 보기 때문에, 예를 들어
AskUserQuestion은 "이 도구를 사용하여 계획이 괜찮은지 묻지 마세요. 그것은ExitPlanMode의 책임입니다."라고 명시할 수 있습니다.
그렇기 때문에 좋은 도구 설명은 반드시 **짧고 정확(short and precise)**해야 합니다. 짧으면 토큰을 절약할 수 있고, 정확하면 모든 문장이 책임, 경계 또는 협업 계약을 정의하도록 보장할 수 있습니다.
Claude가 도구를 호출하는 방식
도구 호출은 하나의 메시지 왕복(message round trip) 과정입니다.
1단계: 모델이 tool_use 블록을 생성합니다
Claude가 도구를 사용하기로 결정하면, 도구를 직접 실행하지 않습니다. 대신 응답에 특수한 블록을 생성합니다:
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
...
2단계: 하네스(Harness)가 이를 가로채어 실행합니다
하네스는 모델의 출력을 가로채어 name과 연관된 구현체(implementation)를 찾고, 여기에 input을 전달합니다. 이 구현체는 로컬 함수, 외부 서비스, 또는 UI 상호작용일 수 있습니다.
3단계: 하네스가 tool_result를 반환합니다
실행 후, 하네스는 결과를 모델에게 다시 보냅니다:
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
...
이 블록은 Claude에게 보내는 다음 메시지에 포함됩니다. 그러면 Claude는 대화를 이어갑니다. 결과에 따라 다른 도구를 호출할 수도 있고, 사용자에게 일반 텍스트로 응답할 수도 있습니다.
이 과정 전반에 걸쳐 모델은 의사 결정자(decision-maker) 역할을 합니다. 모델은 언제 도구를 호출할지, 어떤 도구를 호출할지, 어떤 인자(arguments)를 전달할지, 그리고 결과를 어떻게 사용할지를 결정합니다. 하네스는 실행을 담당하며 모델과 도구 구현체 사이에서 메시지를 전달하는 역할을 합니다.
두 가지 도구-결과 모드
성공 (Success)
성공적인 tool_result는 콘텐츠를 포함합니다:
{
"type": "tool_result",
"tool_use_id": "...",
...
콘텐츠는 일반 텍스트(plain text)이거나, 여러 텍스트 세그먼트 및 이미지와 같은 구조화된 콘텐츠 블록(structured content blocks)일 수 있습니다.
실패 (Failure)
실패한 결과에는 is_error: true가 추가됩니다:
{
"type": "tool_result",
"tool_use_id": "...",
...
이것은 **명시적 실패 (loud failure)**입니다. 즉, 에러가 조용히 묻히지 않습니다. 모델은 실패를 인지하고 다음에 무엇을 할지(재시도, 다른 접근 방식 선택, 또는 사용자에게 질문) 결정할 수 있습니다.
이것이 엄격한 스키마 검증 (strict schema validation)이 중요한 이유이기도 합니다. 하네스 (harness)는 모델이 비어 있거나 의미론적으로 모호한 결과로 계속 진행하도록 허용하는 대신, 유효하지 않은 입력을 명시적으로 거부할 수 있습니다.
도구 결과 또한 컨텍스트를 소비합니다
모델로 반환되는 모든 tool_result는 대화 컨텍스트 (conversation context)의 일부가 됩니다. 이는 결과 크기가 반드시 제어되어야 함을 의미합니다:
- 100,000줄을 포함하는
grep결과는 컨텍스트 윈도우 (context window)를 거의 즉시 고갈시킬 수 있습니다. - 우수한 도구들은 결과를 반환하기 전에 출력을 요약 (summarize), 절단 (truncate) 또는 페이지네이션 (paginate) 합니다.
- 읽기 도구 (read tool)는 기본적으로 고정된 줄 수를 지정할 수 있으며, 검색 도구 (search tool)는 결과 제한 (result limit)을 노출할 수 있습니다.
이것이 Claude Code의 많은 읽기 중심 도구들이 의도적으로 압축된 결과를 반환하는 이유를 설명해 줍니다. 이는 기능의 부족이 아니라, 의도적인 **컨텍스트 예산 관리 (context-budget management)**입니다.
도구는 구조화된 프롬프트 엔지니어링입니다
두 가지 접근 방식을 비교해 보십시오.
자유 형식 프롬프트 (Free-form prompt) 버전:
당신은 사용자에게 질문하기 위해 AskUserQuestion이라는 함수를 호출할 수 있습니다. 사용자가 선택한 후, 당신은 답변을 받게 됩니다.
도구 (Tool) 버전:
name=AskUserQuestiondescription= 상세한 동작 제약 조건input_schema= 정확한 필드 타입, 검증 규칙 및 예시
차이점은 함수를 구현할 수 있느냐의 여부가 아닙니다. 차이점은 함수가 신뢰할 수 있게 (reliably) 동작할 수 있느냐의 여부입니다.
| 차원 (Dimension) | 자유 형식 프롬프트 (Free-form prompt) | 도구 (Tool) |
|---|---|---|
| 구조 (Structure) | 모델이 즉흥적으로 수행 | JSON Schema가 엄격한 제약 조건 (hard constraints)을 제공 |
| ... |
도구는 근본적으로 **구조화된 프롬프트 엔지니어링 (structured prompt engineering)**입니다. 도구는 "모델이 이를 신뢰할 수 있게 수행하도록 하라"는 모호한 요구사항을 검증 가능하고 (validatable), 조합 가능하며 (composable), 유지보수 가능한 (maintainable) 명세(specification)로 변환합니다.
다음 단계
메커니즘이 확립되었으므로, 이 시리즈의 이후 모든 포스트는 동일한 개요를 사용하여 하나의 구체적인 도구를 해부할 것입니다:
- 목적 (Purpose)
- 반례 (counterexample)를 포함한 구체적인 예시
- 트리거 조건 (Trigger conditions)
- 4개 계층에 걸친 기술적 구현 (Technical implementation)
- 네이밍 (Naming)
- 도구 수준의 설명 (Tool-level description)
- 필드 수준의 설명 (Field-level descriptions)
- 스키마 검증 규칙 (Schema validation rules)
- 인접한 도구들과의 책임 분할 (Division of responsibility)
- 핵심 요약 (Takeaway)
이 서론은 메커니즘 (mechanism), 즉 도구가 무엇이며 Claude가 이를 어떻게 사용하는지를 설명합니다. 시리즈의 나머지 부분은 **설계 (design)**에 초점을 맞춥니다. 즉, 특정 도구가 어떻게 4개 계층 모두를 사용하여 기능을 단순히 "가능한" 수준에서 안정적이고, 예측 가능하며, 조합 가능한 것으로 바꾸는지 다룹니다.
다음: AskUserQuestion—Claude Code가 "AI가 질문을 던지는 것"을 어떻게 구조화된 상호작용 프리미티브 (interaction primitive)로 전환하는지 알아봅니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기