Claude Code는 어떻게 동작하는가


터미널에서 Claude Code에게 프롬프트 하나를 던지면, 그 뒤에서는 생각보다 많은 일이 일어난다. 이 글은 “프롬프트를 입력하는 순간부터 답이 돌아오기까지” 무슨 일이 벌어지는지를, 바깥의 에이전틱 루프(agentic loop) 와 그 안쪽의 자기회귀 디코딩 루프라는 두 겹의 구조로 풀어본다.

1. 프롬프트가 모델에 닿기까지

터미널을 열고 프롬프트를 입력하면, Claude Code는 그 프롬프트를 그대로 모델에게 보내지 않는다. 먼저 변형을 거친다.

  • 시스템 프롬프트: Anthropic이 작성한 기본 프롬프트와, Claude Code가 쓸 수 있는 도구(tool) 정의가 함께 들어간다. 엄밀히 말하면 도구 정의는 Anthropic Messages API에서 시스템 프롬프트와는 별개의 tools 파라미터로 전달되지만, 모델은 이를 시스템 수준의 컨텍스트로 함께 받아들인다.
  • 메시지(messages): 사용 가능한 Skill의 이름·설명이 system-reminder 형태로 들어가고, CLAUDE.md의 내용도 여기에 포함된다.

여기서 한 가지 짚고 넘어갈 점. CLAUDE.md는 시스템 프롬프트가 아니라 메시지(첫 user 메시지 안의 system-reminder)로 들어간다. 그런데도 CLAUDE.md의 지시는 보통 일반 질문보다 강하게 작동하는 경향이 있다. 이유는 두 가지다.

  1. 위치 효과 — 트랜스포머 기반 모델은 컨텍스트의 앞부분과 뒷부분을 상대적으로 더 잘 활용하는 경향이 있다(흔히 “lost in the middle”이라 부른다). 보장은 아니지만 경향성은 분명하다.
  2. 명시적 강조CLAUDE.md의 지시에는 “이 지시는 기본 동작을 OVERRIDE한다” 같은 강한 문구가 붙어 우선도를 직접 끌어올린다.

이렇게 시스템 프롬프트와 메시지가 합쳐져 하나의 완성된 입력(프롬프트)이 만들어진다.

2. 모델 내부: Transformer와 자기회귀 디코딩

완성된 프롬프트를 Claude 모델이 받으면, 내부에서는 Transformer가 토큰을 하나씩 생성하기 시작한다.

Transformer는 쉽게 말해 “입력이 들어오면 다음 토큰 1개를 내놓는” 장치다. 핵심은 그 다음이다. 방금 생성한 토큰을 다시 입력 끝에 붙여서 또 다음 토큰을 만들고, 이 과정을 끝날 때까지 반복한다. 이렇게 자기 출력을 다시 입력으로 먹으며 한 토큰씩 이어 붙이는 방식을 자기회귀(autoregressive) 디코딩이라고 부른다. (예전 글이나 메모에서 “aggressive decoding”처럼 적기 쉬운데, 정확한 용어는 autoregressive 다.)

이 글에서 Transformer의 내부 동작 원리나 “토큰이 정확히 무엇인가”는 다루지 않는다. 여기서는 “한 번 호출에 한 토큰, 그걸 반복”이라는 그림만 잡으면 충분하다.

3. Thinking, 그리고 Effort / Adaptive Thinking

Claude에는 EffortAdaptive Thinking 같은 파라미터가 있는데, 이건 생각(thinking)의 정도를 조절한다.

여기서 Thinking이란, 모델이 입력을 받은 뒤 최종 출력을 내기 전에 먼저 Thinking block을 생성하는 것을 말한다. 비유하자면 답을 쓰기 전에 연습장에 먼저 끄적여 보는 과정이다. Effort나 Adaptive Thinking은 이 연습장을 얼마나 길게 쓸지를 조절한다. 경우에 따라서는 thinking이 아예 일어나지 않을 수도 있다.

4. 모델의 출력: Thinking → tool_use / text

모델은 Thinking을 마친 뒤 출력을 내놓는다. 이 출력은 크게 두 가지다.

  • text — 사용자에게 보여주는 텍스트.
  • tool_use — sub-agent, grep, glob, read 같은 도구의 사용 요청. 파일을 읽고 쓰거나 검색하는 등 Claude가 쓸 수 있는 도구들이다.

생성 순서는 대략 Thinking → (tool_use들, text) 이다. 그런데 Claude Code 화면에는 보통 text와 tool_use만 보이고 Thinking block은 표시되지 않는다.

이 점이 흔한 오해를 만든다. 예를 들어 “프로젝트를 분석해줘”라고 하면 Claude가 “프로젝트를 분석하겠습니다”라고 답할 때가 있다. 이건 thinking이 아니라, thinking이 끝난 뒤에 tool_use와 함께 생성된 평범한 text일 뿐이다.

중요한 사실 하나. 모델의 입력부터 출력까지, 도구가 실제로 실행되지는 않는다. 모델은 그저 “이 도구를 써 달라”고 요청만 한다. 도구 요청이 있었다면 모델의 마지막 출력에는 stop_reason: tool_use가 담겨, 도구를 실행해야 한다는 신호를 보낸다.

5. Claude Code가 루프를 돌린다

모델이 stop_reason: tool_use로 돌아오면, 이제 Claude Code가 나설 차례다.

  1. 모델이 요청한 도구들을 실제로 실행한다.
  2. 요청된 모든 도구가 끝날 때까지 기다린다.
  3. tool_use와 그 결과(result)를 알맞게 매핑해 컨텍스트에 추가한다.
  4. 그 컨텍스트로 모델을 다시 호출한다.

모델이 더 이상 도구가 필요 없다고 판단하면, 출력의 stop_reasonend_turn을 담아 “이번 턴을 끝내겠다”고 알린다. Claude Code는 이 신호를 보고 턴을 종료한다.

결국 Claude Code의 동작 방식은 “프롬프트가 들어오면 모델을 반복 호출하는 것” 으로 요약된다. 이 반복 구조를 추상화한 것이 바로 에이전틱 루프다.

6. 루프 속의 루프

흥미로운 점은, 모델 안에서도 루프가 돈다는 것이다.

  • 바깥 루프(에이전틱 루프): Claude Code가 모델을 호출하고 → 도구를 실행하고 → 결과를 붙여 다시 호출한다.
  • 안쪽 루프(자기회귀 디코딩 루프): 모델 한 번의 호출 안에서, Transformer가 토큰을 하나씩 계속 뽑아낸다.

즉 Claude Code는 루프가 중첩된 구조다. 바깥은 “모델 호출 ↔ 도구 실행”의 에이전틱 루프, 안쪽은 “한 토큰씩”의 자기회귀 디코딩 루프. 우리가 터미널에서 보는 매끈한 한 번의 응답은, 사실 이 두 겹의 루프가 함께 돌아간 결과다.

다루지 않은 것

  • Transformer의 구체적인 동작 원리
  • 토큰이 정확히 무엇인지

이 둘은 그 자체로 한 편씩 따로 다룰 만한 주제라, 다음 글로 미뤄둔다.