LLM은 어떻게 개발자가 되는가 — Claude Code라는 하네스의 해부

Claude Code가 LLM 모델을 어떻게 코딩 에이전트로 변환하는지, 공식 문서와 소스 코드를 분석하여 살펴보았습니다.

업로드 날짜: 2026년 04월 23일


LLM은 어떻게 개발자가 되는가 — Claude Code 해부해보기

요즘 들어 바이브 코딩(혹은 에이전트 코딩)이라는 말을 개발자가 아닌 사람들도 자주 입에 올릴 정도로 AI의 발전이 뜨겁다. 그중 가장 선두 주자인 Anthropic은 Claude Code라는 툴을 출시하고 나서부터, Claude 모델을 cli 환경에서 돌릴 수 있게 되었다. 개발자들은 Claude Code를 사용해 Claude 모델을 로컬 터미널상에서 접근하여 질문도 하고, 코드를 작성하기도 한다.

"Claude가 코드 진짜 잘 짠다..!!"라는 말이 나올 정도로 높은 만족도를 보이고 있다.

하지만 여기서 중요한 오해가 하나 있다. Claude는 모델일 뿐이다. 파일을 읽고, 명령을 실행하고, 결과를 검증하는 일은 Claude가 하는 것이 아니다.

공식 문서는 이 부분을 아래와 같이 한 문장으로 정리한다.

Claude Code는 Claude 주변의 에이전트 하네스 역할을 합니다: 언어 모델을 능력 있는 코딩 에이전트로 변환하는 도구, 컨텍스트 관리, 실행 환경을 제공합니다. — Claude Code 공식 문서 — 작동 방식

그렇다면 어떻게 Claude Code는 Claude 모델을 한 명의 개발자로 만들어 주는 걸까?

이 글은 공식문서와 소스 코드를 바탕으로 Claude Code가 어떻게 Claude를 체계적으로 관리하고 구동하는지에 대한 설명을 담았다.

이 글에서 작성된 Claude Code의 내부 코드들은 타 언어로 변형된 소스 코드에 기반하여, 설명의 용이성을 위하여 축약 및 JS로 다시 변형한 코드이다. 실제 코드와는 차이가 있을 수 있다.


1부: 왜 모델만으로는 부족한가

LLM 자체가 할 수 있는 일은 생각보다 좁다. 공식 문서는 아래와 같이 서술한다.

도구가 없으면 Claude는 텍스트로만 응답할 수 있습니다.

LLM은 단순히 프롬프트에 대한 텍스트 응답을 내놓는 도구일 뿐, 현실세계의 그 어떤 것에도 영향을 주지 못한다. 실제로 "일하는 LLM"을 만들기 위해서는 모델 바깥에서 다음 네 가지를 제공해야 한다.

컨텍스트, 즉 시작할 때 무엇을 알고 있게 할지. 도구, 즉 무엇을 할 수 있게 할지. 루프, 즉 어떻게 반복시킬지. 상태, 즉 무엇을 기억하게 할지. 이 네 가지를 모델 바깥에서 조립해주는 하네스가 바로 Claude Code이다.

하네스라는 용어에 대해서 익숙해질 필요가 있다. 하네스는 말에게 씌우는 마구를 뜻하는 단어로, 말의 예측 불가능한 행동을 바로잡고 의도대로 움직일 수 있도록 유도하는 장치를 말한다. 말의 힘을 올바른 방향으로 사용하기 위해서 마구를 씌우는 것처럼, LLM의 지능이 파일을 고치고 테스트를 돌리게 만드는 마구가 바로 Claude Code의 역할이다.


2부: 에이전트 루프 — 하네스의 심장

공식문서에 따르면 Claude에게 작업을 주면 컨텍스트 수집, 작업 수행, 결과 검증 3가지의 일을 반복한다고 한다.

image

이 루프를 에이전트 루프(agentic loop)라고 부른다. 실제 코드에서는 query loop라는 이름으로 표현되어있다.

실제 코드를 바탕으로 동작을 추상화 하면 아래와 같다.

image

이 다이어그램과 타 언어로 재작성된 Claude Code 소스 코드를 통해 에이전트 루프의 코드를 예측하면 아래와 같을 것이다.

// 에이전트 루프 async function agentLoop(userMessage, tools) { // 대화 이력에 사용자 메시지 추가 const messages = [{ role: "user", content: userMessage }]; while (true) { // 1. API에 현재까지의 대화와 도구 스키마를 보낸다 const response = await client.messages.create({ model: "claude-opus-4-7", messages, tools, }); // 2. 응답을 대화 이력에 추가한다 messages.push({ role: "assistant", content: response.content }); // 3. 모델이 도구를 쓰지 않았다면 루프 종료 if (response.stop_reason !== "tool_use") { return response; } // 4. 도구를 썼다면 실행하고 결과를 다시 대화에 붙인다 const toolResults = await executeTools(response.content); messages.push({ role: "user", content: toolResults }); // 루프 맨 위로 돌아간다 } }

Claude Code는 도구를 사용할 수 있는 환경을 제공하며, 모델에게 프롬프트(messages)를 전달하고 응답과 사용할 도구를 전달받는다.

이때 Claude는 텍스트만 입력이 가능하므로 tool_use: FileRead({...}) 와 같은 포매팅된 텍스트 형식으로 전달을 하게 된다.

이 과정에서 응답을 대화 이력에 추가하고, 도구 사용을 요청할 시 사용 결과와 함께 다시 한번 루프를 돈다.

모델이 "도구가 더 필요하다"라고 말하는 한 계속 돌고, 도구 요청을 하지 않으면 멈춘다.

한 턴(turn)의 내부

에이전트 루프(혹은 쿼리 루프) 한 바퀴를 코드상에서는 "턴(turn)"이라고 호칭한다.

한 턴 안에서 무슨 일이 일어나는지 조금 더 자세히 다이어그램을 그리면 아래와 같다.

쿼리 루프: 1회 회전(One turn) ===================== +--[1. 메시지 전처리]---------------------------------------+ | Snip Compact -----> 오래된 메시지를 완전히 제거 | | Microcompact -----> tool_use 블록을 인라인으로 축소 | | Context Collapse -> 단계별 축소 작업 수행 | | Auto-Compact -----> 토큰 제한 근접 시 요약 처리 | | (임계값 = 컨텍스트 창 - 13,000) | +----------------------------+------------------------------+ | v +--[2. API 스트리밍 호출]-----------------------------------+ | 전송: 메시지 + 시스템 프롬프트 + 도구 스키마 | | 수신: 스트리밍 응답 (토큰 단위) | | 모델 과부하 발생 시 --> 대체 모델로 전환 | +----------------------------+------------------------------+ | v +--[3. 오류 억제 및 복구]-----------------------------------+ | 413 프롬프트 너무 길음(Prompt Too Long): | | 축소 드레인 시도 --> 반응형 압축 시도 --> 실패 | | 최대 출력 토큰 제한: | | 8K에서 64K로 확장 --> 최대 3회 재시도 --> 실패 | +----------------------------+------------------------------+ | v +--[4. 도구 실행]-------------------------------------------+ | 안전한 도구 (Read, Grep, Glob): | | --> 최대 10개까지 병렬 실행 | | 안전하지 않은 도구 (Edit, Bash, Write): | | --> 순차적으로 하나씩 실행 | | 대규모 결과물 --> 디스크에 보존 후 참조 전달 | +----------------------------+------------------------------+ | v +--[5. 후처리]----------------------------------------------+ | 중단 후크(Stop Hooks) 실행 (검증) | | 토큰 예산 확인 | | 최대 회전(Turn) 제한 확인 | | 응답 내 tool_use 포함 여부 확인: | | 예(YES) --> 새로운 상태(State) 생성 후 1단계로 복귀 | | 아니오(NO) --> 루프 종료 및 사용자에게 결과 반환 | +-----------------------------------------------------------+

앞에서 본 JS 코드의 await client.messages.create(...) 에는 메시지에 대한 최적화 내용 및 스트리밍 방식으로 API를 호출하는 로직이 담겨있다.

메시지를 전달하기 전 메시지 전처리(Message Preprocessing)를 통해 대화가 길어짐에 따라 토큰이 부족해지는 것을 방지하기 위한 최적화 작업을 진행한다. Claude Code는 사용자의 작업에 최적의 결과 및 안정적인 사용자 경험을 주는 방향으로 Claude에게 전달하는 프롬프트를 수정한다. 수행하는 동작은 아래와 같다.

  • Snip Compact: 아주 오래된 메시지들을 컨텍스트에서 제거
  • Microcompact: 이전의 도구 사용(tool_use) 블록들을 인라인으로 축소
  • Context Collapse: 일반 컨텍스트를 단계별로 축소
  • Auto-Compact (자동 압축): 누적된 토큰 사용량이 임계점(전체 컨텍스트 윈도우 - 13,000 토큰)에 도달하면, 대화 전체를 AI가 요약하도록 하여 공간 확보.

또한 여러 에러 상황 발생시 에러 상황을 대처한다. 413 "Prompt Too Long" 에러 발생시 먼저 예약해둔 압축 작업을 한꺼번에 흘려보내보고(collapse drain), 그래도 안 되면 AI에게 전체 대화 요약을 시키고(reactive compact), 그래도 안 되면 그제야 실패를 사용자에게 보여준다.

그리고 출력 토큰 최초 초과 시 8K 토큰 한도를 64K로 에스컬레이션한다. 이후 최대 3번까지 이어쓰기를 재시도한다.

Claude Code는 다양한 에러 상황에 맞추어서 Claude가 사용자가 목표로 하는 결과를 낼 수 있도록 유도하고 대응하는 방식으로 하네스한다.


3부: 도구 — 하네스의 손발

루프가 심장이라면, 도구는 실제 세계에 영향을 미치는 하나의 손발이라고 말할 수 있다.

API 레벨의 도구 프로토콜

모델과 하네스는 JSON 블록으로 대화한다. 모델이 "이 도구를 쓰고 싶어"라고 말할 때는 tool_use 블록을, 하네스가 "이게 실행 결과야"라고 돌려줄 때는 tool_result 블록을 사용한다.

// 모델이 응답에 담는 tool_use 블록 { type: "tool_use", id: "toolu_abc123", // 나중에 tool_result와 매칭할 때 쓰는 고유 ID name: "FileRead", // 모델이 호출하고 싶어하는 도구의 이름 input: { path: "auth.ts" } // 도구에 전달할 인자 (input_schema에 맞는 JSON) } // 하네스가 실행 후 돌려주는 tool_result 블록 { type: "tool_result", tool_use_id: "toolu_abc123", // 위의 id와 매칭 content: "[파일 내용 문자열]" // 도구 실행 결과 }

에이전트 루프(혹은 쿼리 루프) JS 코드에서 도구 실행 단계의 executeTools(response.content) 코드가 하는 일을 알아보자.

모든 도구의 공통 인터페이스

Claude Code에는 파일 작업, 셸, 검색, 웹, 에이전트/팀, 플래닝, 태스크, 스킬까지 여덟 개의 범주로 나눌 수 있는 45개가 넘는 내장 도구가 있다. 모든 도구는 아래와 같은 동일한 인터페이스를 따른다.

모든 도구(Tool)의 구성 요소: +-----------------------------------------------------------------+ | name "BashTool", "FileEditTool" 등 명칭 | | inputSchema 필수/선택적 입력을 정의하는 Zod 스키마 | | call() 실제 실행 기능 | | description() AI가 사용 시점을 알 수 있도록 보여주는 설명 | | | | checkPermissions() 현재 컨텍스트에서 실행 가능한지 확인 | | validateInput() 입력값이 의미론적으로 유효한지 검사 | | isConcurrencySafe() 다른 도구와 병렬 실행이 안전한지 여부 | | isReadOnly() 수정 사항이 발생하는지 여부 | | maxResultSizeChars 제한 초과 시 디스크에 보존할 결과물 크기 | | render*() 터미널 UI용 React 컴포넌트 | +-----------------------------------------------------------------+

위쪽 네 개(name, inputSchema, call, description)는 API 프로토콜에 붙는 표준 필드다. 아래쪽 여섯 개가 Claude Code 고유의 요구사항이다. "이 도구가 지금 실행되어도 되는가", "다른 도구와 같이 돌려도 안전한가", "결과가 너무 크면 어떻게 할 것인가". 하네스는 도구 하나마다 이 여섯 개의 약속을 받아놓는다.

도구 하나가 실행되기까지 — 10단계 파이프라인

도구 실행(executeTools ) 코드의 동작을 알아보자.

Claude Code가 도구 하나를 실행하기까지 아래의 열 개의 단계를 거친다.

도구 실행 파이프라인 (각 tool_use 블록별) ================================================== [1] 이름으로 도구 조회 ---> 찾지 못했나요? 별칭(aliases) 시도 | [2] 중단 신호 확인 ---> 사용자가 Ctrl+C를 눌렀나요? 종료 | [3] 입력값 검증 (Zod) -> 형식이 잘못되었나요? 사용자 친화적 오류 출력 | [4] PreToolUse 훅 실행 -> 훅에서 차단했나요? 여기서 중단 | [5] 권한 확인 -----> 거부? 사용자에게 질문? 자동 분류? | [6] tool.call() 실행 ---> 실제 작업이 여기서 수행됨 | [7] 결과를 API 형식으로 매핑 | [8] 크기 초과 시 보존 ---> 디스크에 저장하고 참조값 반환 | [9] PostToolUse 훅 실행 | [10] 원격 측정(Telemetry) 이벤트 기록

위의 단계를 검증(1~4), 허가 및 실행(5, 6), **뒷정리(7~10)**으로 나눌 수 있다.

도구를 올바르게 조회한 이후 입력값을 검증하고 훅의 규칙과 setting.json 권한에 따라서 실행 여부와 방식을 선택한다. 실행한 이후에는 결과를 Claude가 이해할 수 있는 형식으로 매핑해 메모리 보호 과정을 거쳐 주기게 맞는 훅 실행 및 로그를 기록한다.

Claude Code에서 도구의 검증 단계를 거치는 이유는 AI가 rm -rf / 와 같은 부적절한 방향으로 도구를 실행하려는 것을 막기 위함이다. 또한 도구 실행 이후 시스템의 메모리와 비용을 보호하고, AI의 연속적인 에이전트 루프를 통제하기 위한 필수적인 안전 및 최적화 장치를 마련하였다.

가장 위험한 도구 — Bash

Bash도구는 가장 강력하지만 가장 위험하다.

Claude Code는 Tree-sitter 파서를 바탕으로 명령어의 구조를 분석하고, 허용 목록에 있는 구문만 통과시키는 방식으로 위험한 명령어를 실행하지 못하도록 한다. 또한 명령 실행이 15초를 넘어가면 자동으로 백그라운드로 전환되고, 2초마다 진행 상황을 보고하도록 한다.

도구 실행 최적화_배치 시스템과 동시 실행

모델이 한 턴에 여러 도구를 쓰려고 하면, 빠른 실행을 위하여 하네스는 이들을 배치로 나눈다.

Tool Concurrency: Partitioning Algorithm ========================================= Input: [Read] [Grep] [Glob] [Edit] [Read] [Read] [Bash] safe safe safe UNSAFE safe safe UNSAFE Batch 1: [Read, Grep, Glob] --> parallel (up to 10) Batch 2: [Edit] --> serial (alone) Batch 3: [Read, Read] --> parallel Batch 4: [Bash] --> serial (alone)

읽기 같은 안전한 도구는 최대 10개까지 병렬로 묶어서 돌리고, 편집이나 셸 실행처럼 부작용이 있는 도구는 배치를 끊어 단독으로 돌린다.

이때 도구 실행 중 에러가 발생할 경우,아직 실행 중인 다른 형제 도구들의 작업을 즉시 중단시키는 안전 메커니즘도 존재한다.

Streaming Tool Executor (overlaps API streaming + execution) ============================================================= Time ---> API stream: [...text...][tool_use A][...text...][tool_use B][done] | | Execution: start A start B |..running..|done |..running..|done | Collect: drain remaining

또한 Claude 모델과의 API 스트리밍으로 흘리는 도중에, 이미 도착한 tool_use 블록을 동시에 실행한다. 이를 통해서 데이터 수신과 물리적인 도구 실행 작업이 동시에 진행되어 전체 응답 속도를 크게 높인다.

도구 등록 순서의 고정

소스 분석에 따르면 모든 도구는 tools.ts특정 순서로 등록되어 있고, MCP로 추가되는 외부 도구도 이름순 정렬 후 내장 도구 뒤에 병합된다.

getAllBaseTools() 44+ tools registered | v Feature gate filter Remove disabled features | v Deny rules filter Remove user-blocked tools | v Mode filter SIMPLE mode: only Bash, Read, Edit | v Built-in tools (sorted by name) | +------> assembleToolPool() <------+ | | v MCP tools Merged tool list (sorted by name) (built-in first, dedup by name)

정렬 순서를 고정한 이유는 API의 프롬프트 캐싱 안정성 때문이다.

Claude Code는 API 통신 비용을 절감하기 위해 시스템 프롬프트와 도구 스키마(Tool Schema)를 1시간 동안 캐시(Cache)하여 재사용하는 방식을 사용한다. 이때 도구 순서가 바뀌면 캐시가 무효화되어 비용이 증가한다.

이처럼 Claude Code는 도구를 통해 Claude 모델이 파일을 고치고, 명령을 실행하고, 결과를 확인하도록 만들어준다. 그 과정에서 모델이 올바르지 않은 방향으로 도구를 사용하는 것을 막고, 효율적으로 사용할 수 있는 장치를 제공한다.


4부: 컨텍스트 관리 — 하네스의 뇌 보호 장치

루프가 심장이고 도구가 손발이라면, 컨텍스트 관리는 뇌 보호 장치에 가깝다. 모델의 컨텍스트 윈도우는 유한하고, 이 한계 안에서 무엇을 넣고 무엇을 뺄지를 결정하는 일이 하네스의 중요한 책임이다.

공식 문서에 따르면 컨텍스트 윈도우에 들어가는 것은 대화 기록, 파일 콘텐츠, 명령 출력, CLAUDE.md, 자동 메모리, 로드된 skills, 시스템 지침등이다. 이러한 컨텍스트는 작업하면서 계속 추가된다. 그리고 Claude Code는 한계에 접근할 때 이를 자동으로 관리한다.

소스 코드를 보면서 더욱 자세하게 Claude code가 하는 일을 확인해보자.

이중 주입 — System Context와 User Context

Claude Code의 모든 대화에는 두 가지 컨텍스트가 주입된다.

Context injection (memoized for session lifetime) ================================================== System Context User Context +--------------------------+ +--------------------------+ | Git branch: main | | CLAUDE.md files | | Default branch: main | | (project instructions) | | Git status (max 2000ch) | | | | Recent commits | | Today's date | | Git user name | | | +--------------------------+ +--------------------------+ | | +----------------+-----------------+ | v Injected into every API conversation turn

System Context는 Git 상태(브랜치, 커밋, 변경사항)를 담고, User Context는 CLAUDE.md와 프로젝트 구조, 그리고 오늘 날짜를 담는다. 이 두 컨텍스트는 매 API 요청마다 추가되는 정보이다.

반대로 주된 대화 내용이 아닌 Git 상태와 같은 정보가 너무 방대해지면 오히려 컨텍스트는 상할 수 있으므로(Context-Rot 현상) Git 상태는 2,000자에서 잘리도록 되어있다.

이러한 정보들은 Claude 모델이 더 나은 답을 내놓도록 하네스 한다.

네 가지 압축 전략의 상호작용

2부에서 봤듯이 Claude Code는 메시지 전처리 단계에서 네 가지 압축 전략(Snip Compact, Microcompact, Context Collapse, Auto-Compact)을 사용한다. 이들은 각각 제거, 축소, 스케줄링, 요약이라는 서로 다른 방식으로 컨텍스트를 줄인다.

중요한 것은 이 네 전략이 독립적으로 동작하는 것이 아니라 계층적으로 맞물려 있다는 점이다. 평상시에는 Auto-Compact가 토큰 사용량을 모니터링하다가 임계점(컨텍스트 윈도우 - 13,000 토큰)에 도달하면 대화 전체를 요약한다. 임계점에 도달하기 전부터는 Context Collapse가 압축 작업을 미리 스케줄링해두고, 필요할 때 한꺼번에 흘려보낸다.

그런데 이러한 예방적 관리에도 불구하고 API가 413 "Prompt Too Long" 에러가 발생할 수 있다. 이때는 예약된 collapse를 먼저 드레인하고, 그래도 해결되지 않으면 **reactive compact(즉흥 요약)**를 시도한다.


5부: 확장 계층 — 하네스 커스터마이즈하기

Claude Code는 자체 하네스 뿐만 아니라 사용자에게 Claude를 하네스 할 수 있는 방법을 제시한다.

CLAUDE.md, Skills, MCP, Hooks, Subagents, Settings, rules 등이 있으며, 이를 사용하여 Claude가 내놓은 답을 원하는 방향으로 유도하고, 실수를 막기 위해 규칙을 세우고, 사용할 수 있는 도구를 설정할 수 있다.

이 파일들이 어떻게 Claude Code의 동작에 관여하는지 확인해보자.

에이전트 루프를 다시 가져왔다. 코드 상에서 각 확장이 어디에 끼어드는지를 주석으로 표시했다.

// 2부에서 본 루프 — 이번엔 확장 지점의 지도로 다시 읽는다 async function agentLoop(userMessage, tools) { // ↓ CLAUDE.md는 여기 바깥에서 매 요청의 "컨텍스트"에 주입된다 const messages = [{ role: "user", content: userMessage }]; while (true) { const response = await client.messages.create({ model: "claude-opus-4-7", messages, tools, // ← MCP는 이 tools 배열을 확장한다 (새 도구 정의를 추가) }); messages.push({ role: "assistant", content: response.content }); if (response.stop_reason !== "tool_use") return response; // ↓ Hooks는 여기 앞뒤에서 결정론적으로 끼어든다 // (PreToolUse / PostToolUse / Stop) const toolResults = await executeTools(response.content); // // Subagents는 이 함수 안에서 새로운 agentLoop를 재귀적으로 생성한다 messages.push({ role: "user", content: toolResults }); } }
MCP

MCP(Model Context Protocol)는 로컬 환경을 넘어서서 타 서비스와 같은 외부 서비스의 기능을 사용할 수 있게 만들어주는 프로토콜을 말한다. 코드상으로는 tools와 동일하다. 실제로 에이전트 루프 상에서 tools 배열에 외부 도구를 추가하는 방식으로 동작한다.

외부 MCP 서버가 제공하는 도구는 Claude Code의 내장 도구 뒤에 이름순으로 정렬되어 병합된다. 정렬이 일관되기 때문에 MCP 도구를 추가해도 캐시가 안정적으로 유지된다.

Hooks

Hooks를 통해서 Claude Code의 동작 주기에 맞추어서 실행할 행동을 지정할 수 있다.

도구 실행 10단계 파이프라인에서 네 번째와 아홉 번째 단계가 바로 Hook이 끼어드는 자리다.

확장 중에 유일하게 LLM을 통과하지 않는다.

Subagents

Subagents는 메인 에이전트의 동작을 완전히 격리된 컨텍스트로 동작 후 그 결과를 메인 에이전트의 컨텍스트에 넣어주는 에이전트를 말한다.

Subagents는 코드상에서는 기본 에이전트 루프 내에서 새로운 루프를 재귀적으로 만드는 방식으로 동작한다. 메인 대화에서 서브에이전트에게 작업을 위임하면, 서브에이전트는 자기만의 깨끗한 컨텍스트로 새 agentLoop를 돈다. 작업이 끝나면 요약만 메인 대화로 돌아오고, 중간 과정은 메인 컨텍스트를 오염시키지 않는다.

CLAUDE.md와 rules, Skills의 비대칭 로딩

세 기능은 모두 컨텍스트에 추가되어 "Claude에게 지침을 전달한다"는 목적은 같다. 하지만 언제, 얼마나, 어떤 조건에서 올라오는지가 전부 다르다.

기능로드 시점로드되는 내용누가 로드를 결정하는가
CLAUDE.md세션 시작파일 전체하네스 (무조건)
.claude/rules/세션 시작 또는 매칭 파일 작업 시paths frontmatter에 맞을 때만 전체파일 경로 (결정론적)
Skill세션 시작 시 설명만, 호출 또는 관련 판단 시 전체2단계 로딩Claude (설명을 보고 판단)

CLAUDE.md는 항상 켜진 컨텍스트다. 프로젝트 루트에 있는 CLAUDE.md는 세션이 시작되는 순간 전체가 컨텍스트에 올라가고, 이후 모든 요청에서 같이 전송된다. 비용이 가장 비싼 대신 "매번 반드시 보게 만드는" 힘이 가장 강하다.

rules는 조건부로 켜진 컨텍스트다. .claude/rules/ 아래의 규칙 파일은 paths frontmatter로 "이 경로의 파일을 다룰 때만 로드하라"는 스코프를 지정할 수 있다. 파이썬 파일을 열면 파이썬 규칙만, 프론트엔드 디렉토리를 건드리면 프론트엔드 규칙만 올라오는 식이다. 로드 여부를 판단하는 주체가 Claude가 아니라 파일 경로라는 결정론적 조건이 rules의 특징이다.

Skill은 2단계로 로드된다. 세션 시작 시에는 skill의 이름과 설명(description)만 컨텍스트에 올라간다. Claude가 작업을 진행하면서 "지금 이 skill이 필요하다"고 판단하거나 사용자가 /<skill-name>으로 직접 호출할 때, 비로소 전체 콘텐츠가 로드된다. 판단 주체는 Claude 모델이다. 그러므로 설명이 모호하면 엉뚱한 skill을 로드하거나 필요한 skill을 놓칠 수 있다는 트레이드오프가 여기서 발생한다.


결론: 하네스라는 관점에서 보면

지금까지 Claude Code가 Claude 모델을 하네스하기 위해 하는 일들을 알아봤다. Claude Code는 Claude 모델을 한 명의 개발자로 만들어 주기 위해 아래와 같은 일들을 한다.

  • Claude 모델이 특정 작업을 수행하기 위한 도구를 더 이상 요청하지 않을 때까지 컨텍스트 수집과 작업 수행, 결과 검증을 반복하는 에이전트 루프를 돌려준다.
  • Claude 모델이 파일을 고치고 명령을 실행하고 결과를 확인할 수 있도록 도구를 쥐여준다. 모델이 올바른 방향으로 도구를 쓸 수 있도록 입력 검증과 권한 확인 단계에서 적절히 막아준다.
  • Claude 모델이 긴 대화에서도 버티면서 더 나은 답을 내놓을 수 있도록 컨텍스트를 관리해준다. 제거, 축소, 스케줄링, 요약이라는 네 가지 압축 전략을 계층적으로 맞물리게 해서 토큰 한계 안에서 대화를 유지해준다.
  • 사용자가 Claude 모델을 사용자의 상황에 맞게 하네스할 수 있도록 확장 창구를 열어준다. MCP, Hooks, Subagents, CLAUDE.md, rules, Skills로 각자의 방식으로 모델의 동작에 개입할 수 있게 해준다.

Claude 모델은 개발자가 아니다. Claude 모델을 한 명의 개발자로 만들어 주기 위해서 Claude Code는 이 정도로 많은 일들을 대신해준다.

도입부에서 말했던 마구 비유로 돌아가보자. 아무리 힘 좋은 말이라도 마구 없이는 밭을 갈 수 없다. Claude Code가 씌워주는 이 마구 덕분에,모델은 더 좋은, 올바른 방향으로 결과물을 낼 수 있으며, 뱉는 텍스트가 비로소 파일을 고치고, 테스트를 돌리고, 커밋을 작성할 수 있게 된다.