티스토리 뷰

Claude Code가 파일을 읽고, 코드를 수정하고, 테스트를 실행하는 걸 보면 마치 AI가 직접 컴퓨터를 조작하는 것처럼 보입니다. 처음 Claude Code를 쓸 때 저도 그렇게 생각했습니다. "AI가 터미널을 쓰고 있구나."

그런데 실제 동작 방식을 알고 나면 생각이 달라집니다. LLM은 파일을 읽을 수 없고, 코드를 실행할 수도 없습니다. 그럼 어떻게 이 모든 걸 하는 걸까요?

1. Tool Use - LLM은 텍스트만 출력한다

1편에서 LLM은 다음 토큰을 예측하는 존재라고 했습니다. 이 원리는 도구를 사용할 때도 동일합니다. LLM이 "도구를 실행"하는 게 아니라, "도구를 실행해달라는 텍스트를 출력"하는 겁니다.

실제 흐름을 풀어보면 이렇습니다.

1. 사용자: "src/app.ts 파일 읽어줘"

2. LLM 출력: { "tool": "Read", "file_path": "src/app.ts" }
   (LLM은 여기서 끝. 파일을 직접 읽는 게 아님)

3. 하네스(Claude Code)가 이 출력을 보고 실제로 파일을 읽음

4. 하네스가 파일 내용을 LLM 입력에 다시 넣어줌:
   "파일 내용: export const app = ..."

5. LLM이 파일 내용을 보고 다음 응답을 생성

핵심은 3번입니다. LLM과 실제 시스템 사이에 하네스가 있고, 하네스가 중간에서 도구를 실행하고 결과를 전달합니다. LLM은 처음부터 끝까지 텍스트를 입력받고 텍스트를 출력할 뿐입니다.

이걸 이해하면 왜 가끔 Claude Code가 엉뚱한 도구를 고르거나, 잘못된 파라미터를 넘기는지 이해가 됩니다. LLM 입장에서는 "이 맥락에서 다음에 올 그럴듯한 도구 호출 텍스트"를 예측하는 것이기 때문입니다. 1편에서 다룬 할루시네이션과 같은 원리죠. 존재하지 않는 파일 경로를 자신있게 넘기는 것도, "그럴듯한 다음 토큰"을 생성한 것일 뿐입니다.

 

2. 도구 설명이 곧 프롬프트다

LLM이 도구를 선택하는 기준이 뭘까요? 각 도구에는 설명(description)이 붙어있고, LLM은 이 설명을 보고 어떤 도구를 쓸지 결정합니다.

예를 들어 Claude Code에서 파일을 읽을 때 사용하는 Read 도구의 설명은 대략 이런 식입니다.

Read: 파일을 읽어서 내용을 반환합니다.
- file_path: 읽을 파일의 절대 경로

LLM은 사용자가 "파일 읽어줘"라고 하면, 등록된 도구들의 설명을 보고 Read가 적절하다고 판단해서 Read 호출 텍스트를 생성합니다. 반대로 도구 설명이 애매하면 LLM이 잘못된 도구를 고르거나, 적절한 도구가 있는데도 직접 답하려고 합니다.

이게 실무에서 중요한 이유가 있습니다. Claude Code에서 커스텀 명령어(slash command)나 MCP 서버를 만들 때, 도구의 이름과 설명을 어떻게 쓰느냐에 따라 LLM이 그 도구를 잘 활용할 수도, 무시할 수도 있습니다. 도구 설명은 결국 LLM에게 주는 프롬프트의 일부이니까요.

 

3. ReAct 패턴 - 생각하고 행동하고 관찰하는 루프

Claude Code가 복잡한 작업을 처리할 때를 보면, 한 번에 끝내지 않고 여러 단계를 거칩니다. 파일 구조를 먼저 파악하고, 관련 파일을 읽고, 코드를 수정하고, 테스트를 돌리고, 결과를 보고 다시 수정하고... 이 패턴이 바로 ReAct(Reasoning + Acting)입니다.

[생각] "사용자가 로그인 버그를 고쳐달라고 했다.
        먼저 인증 관련 파일을 찾아봐야겠다."

[행동] Grep 도구 실행: "authentication" 키워드 검색

[관찰] auth.service.ts, auth.controller.ts 파일 발견

[생각] "auth.service.ts를 먼저 읽어봐야겠다."

[행동] Read 도구 실행: auth.service.ts

[관찰] 파일 내용 확인... validateToken 함수에서 예외 처리가 빠져있다

[생각] "여기에 try-catch를 추가하면 될 것 같다."

[행동] Edit 도구 실행: 코드 수정

[관찰] 수정 완료

[생각] "테스트를 돌려서 확인해보자."

[행동] Bash 도구 실행: npm test

[관찰] 테스트 통과

이 루프가 에이전트의 핵심입니다. 단순한 질의응답이 아니라, 생각 → 행동 → 관찰을 반복하면서 목표에 도달하는 구조죠.

그런데 여기서 2편의 내용이 연결됩니다. 이 루프가 반복될 때마다 컨텍스트가 쌓입니다. 도구 실행 결과가 매번 컨텍스트에 추가되니까요. 파일 내용을 읽을 때마다, 테스트 결과가 나올 때마다 컨텍스트 윈도우가 채워집니다. 루프가 길어지면 초반에 했던 생각이나 관찰이 컨텍스트에서 밀려날 수 있습니다.

4. 에이전트 루프가 실패하는 순간들

이 구조를 이해하면 에이전트가 실패하는 패턴도 예측할 수 있습니다.

루프에 빠져서 못 나오는 경우
테스트가 계속 실패하면 수정 → 테스트 → 실패 → 수정을 반복합니다. 같은 접근을 반복하면서 컨텍스트만 쌓이고, 결국 초반의 맥락을 잃어버려서 점점 엉뚱한 방향으로 가기도 합니다. "아까 시도한 건데 왜 또 같은 걸 하지?"라는 경험, 해보신 적 있을 겁니다.

도구 선택을 잘못하는 경우
파일을 검색해야 하는데 Bash로 find 명령어를 실행하거나, 간단한 수정인데 파일 전체를 다시 작성하려고 하거나. LLM이 "가장 그럴듯한 다음 토큰"을 예측하다 보니, 최적이 아닌 도구를 고를 때가 있습니다.

너무 많은 정보를 한 번에 가져오는 경우
큰 파일을 통째로 읽거나, 로그를 전부 가져오면 컨텍스트가 한 번에 차버립니다. 정작 중요한 부분은 2편에서 다룬 Lost in the Middle 현상으로 놓치게 되죠.

 

5. 이걸 알면 에이전트를 더 잘 다룰 수 있다

에이전트의 동작 원리를 알면, 문제가 생겼을 때 대응 방식이 달라집니다.

에이전트가 루프에 빠졌을 때
무작정 기다리지 말고 Esc로 중단하고, 새로운 방향을 제시하는 게 낫습니다. 이미 쌓인 컨텍스트에서 같은 실수를 반복할 가능성이 높으니까요. 때로는 /clear 명령어 처럼 대화를 아예 새로 시작하는 게 빠릅니다.

도구 사용이 비효율적일 때
"Grep으로 검색해봐"처럼 도구를 직접 지정해주면 LLM이 적절한 도구를 고를 확률이 올라갑니다. 프롬프트에 도구 이름을 포함하면 해당 도구를 호출하는 텍스트가 생성될 확률이 높아지는 원리입니다.

컨텍스트가 비대해졌을 때
작업 단위로 대화를 끊는 게 효과적입니다. "파일 구조 파악"과 "코드 수정"을 같은 대화에서 하기보다, 구조 파악 결과를 정리한 뒤 새 대화에서 수정 작업을 시작하는 거죠.

이게 OMC 같은 플러그인에서 서브 에이전트를 쓰는 이유이기도 합니다. 탐색은 explore 에이전트가 깨끗한 컨텍스트에서 하고, 결과만 메인 에이전트에 전달하면 메인 에이전트의 컨텍스트는 깨끗하게 유지됩니다.

 

6. 하네스의 역할이 보이기 시작한다!

지금까지 3편에 걸쳐 다룬 내용을 연결하면 이런 그림이 됩니다.

LLM 본질 (1편)
  → 다음 토큰 예측기
  → 이해가 아니라 패턴 매칭
  → 할루시네이션은 정상 동작

컨텍스트 제약 (2편)
  → 컨텍스트 윈도우 = 볼 수 있는 범위의 한계
  → 어텐션 = 위치에 따라 다른 주의력
  → 길어지면 정보 손실

도구와 루프 (3편)
  → LLM은 텍스트만 출력, 하네스가 실행
  → 생각-행동-관찰 루프로 복잡한 작업 처리
  → 루프가 길어지면 컨텍스트 문제 발생

이 세 가지를 종합하면, 하네스 엔지니어링이 왜 필요한지가 자연스럽게 이해됩니다. LLM 자체는 한계가 명확한 존재입니다. 하지만 그 한계를 이해하고 적절한 환경을 만들어주면 강력한 도구가 됩니다.

이전에 쓴 하네스 엔지니어링 글에서 Mitchell Hashimoto의 말을 인용했었는데, 다시 한번 가져오면 이렇습니다. "에이전트가 실수할 때마다, 그 실수가 다시는 발생하지 않도록 엔지니어링하는 것." 이제 이 문장이 더 구체적으로 와닿지 않나요?

  • 에이전트가 할루시네이션을 하면 → 검증 도구를 연결한다 (1편의 원리)
  • 에이전트가 지시를 까먹으면 → 중요한 정보를 컨텍스트 앞쪽에 고정한다 (2편의 원리)
  • 에이전트가 루프에 빠지면 → 작업을 분할하고 컨텍스트를 관리한다 (3편의 원리)

AI를 다루고 실제 업무에 활용하는 개발자일뿐, AI를 잘 쓰기 위해 모델을 만들 줄 알 필요는 없다고 생각합니다. 하지만 모델이 어떻게 동작하는지 이해하면, "왜 이렇게 해야 하는지"를 알게 되고, 그러면 상황에 맞게 응용할 수 있습니다.


참고 자료

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함