AI 코딩 에이전트 아키텍처 해부 — 내부 동작 원리와 설계 패턴
AI 코딩 에이전트의 ReAct 루프, 도구 호출, 컨텍스트 관리, 에러 복구 메커니즘과 직접 만드는 패턴.
한 줄 요약: AI 코딩 에이전트는 ReAct(추론+행동) 루프를 반복하면서 도구를 호출하고, 컨텍스트를 관리하며, 에러를 스스로 복구한다. 이 구조를 이해하면 Claude Code, Cursor 같은 도구를 더 잘 쓸 수 있고, 직접 에이전트를 설계할 때도 올바른 아키텍처 결정을 내릴 수 있다.
- Claude Code, Cursor, Devin이 내부적으로 어떻게 동작하는지 궁금한 개발자
- ReAct 루프, 도구 호출, 컨텍스트 관리가 무엇인지 코드 수준으로 이해하고 싶은 경우
- 직접 AI 코딩 에이전트를 만들거나, AI 워크플로우를 설계하려는 경우
- 에이전트 아키텍처의 한계와 실패 패턴을 미리 파악하고 싶은 경우
ReAct 루프 — 에이전트의 핵심 동작 원리
AI 코딩 에이전트의 기반 알고리즘은 2022년 논문 "ReAct: Synergizing Reasoning and Acting in Language Models"에서 제안한 ReAct 패턴이다. 핵심 아이디어는 LLM이 추론(Thought)과 행동(Action)을 번갈아 반복하면서 목표를 향해 진행한다는 것이다.
루프의 각 단계:
- Observation: 현재 상태를 입력으로 받는다. (파일 목록, 에러 메시지, 이전 도구 호출 결과 등)
- Thought: LLM이 현재 상황을 추론한다. "파일을 열어봐야 한다", "이 에러는 X 때문이다"
- Action: 도구를 호출한다. 파일 읽기, 코드 실행, 검색 등
- Observation: 도구 호출 결과가 다음 단계의 입력이 된다
- 반복 또는 종료: 목표가 달성되거나 최대 스텝에 도달하면 종료
Claude Code를 예로 들면, 사용자가 "버그를 고쳐줘"라고 하면 에이전트는 파일을 읽고, 에러를 분석하고, 수정 코드를 작성하고, 테스트를 실행하고, 테스트가 실패하면 다시 분석하는 루프를 반복한다.
ReAct 루프 — Python 의사 코드 구현from anthropic import Anthropic client = Anthropic() tools = [read_file_tool, write_file_tool, run_bash_tool, search_tool] def run_agent(task: str, max_steps: int = 20) -> str: messages = [{"role": "user", "content": task}] for step in range(max_steps): # LLM에게 현재 상태를 넘기고 다음 행동 결정 response = client.messages.create( model="claude-opus-4-5", max_tokens=4096, tools=tools, messages=messages, ) # 도구 호출이 없으면 최종 답변 반환 if response.stop_reason == "end_turn": return response.content[0].text # 도구 호출이 있으면 실행하고 결과를 컨텍스트에 추가 if response.stop_reason == "tool_use": messages.append({"role": "assistant", "content": response.content}) tool_results = [] for block in response.content: if block.type == "tool_use": result = execute_tool(block.name, block.input) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": str(result), }) messages.append({"role": "user", "content": tool_results}) return "Max steps reached without completing the task"
도구 호출 설계 — 에이전트가 쓰는 도구의 종류와 설계 원칙
에이전트의 능력은 곧 도구의 집합이다. Claude Code는 파일 시스템 읽기/쓰기, 셸 명령 실행, 웹 검색, MCP 서버 연결 등의 도구를 갖고 있다. 도구 설계는 에이전트 성능을 결정하는 가장 중요한 요소 중 하나다.
코딩 에이전트의 핵심 도구 분류
| 카테고리 | 도구 예시 | 목적 |
|---|---|---|
| 파일 시스템 | read_file, write_file, list_directory, search_files | 코드베이스 탐색 및 수정 |
| 코드 실행 | run_bash, run_python, run_tests | 실행 결과 검증 |
| 검색 | web_search, grep, semantic_search | 문서, 패턴, 해결책 탐색 |
| 외부 서비스 | github_pr, jira_ticket, slack_message | 워크플로우 자동화 |
| 메모리 | save_note, recall, update_context | 장기 컨텍스트 유지 |
좋은 도구 설계 원칙
- 단일 책임: 한 도구가 하나의 명확한 일만 해야 한다. LLM이 언제 어떤 도구를 쓸지 판단하기 쉬워진다.
- 명확한 에러 반환: 실패 시 예외를 던지는 것보다 에러 메시지가 포함된 결과를 반환하는 것이 에이전트가 복구하기 쉽다.
- 입력 검증: 도구가 잘못된 입력을 받으면 에이전트 루프 전체가 오동작할 수 있다. 입력 스키마 검증은 필수다.
Anthropic Tool Use API — 도구 정의 예시tools = [ { "name": "read_file", "description": "Read the contents of a file at the given path. Returns the file content as a string.", "input_schema": { "type": "object", "properties": { "path": { "type": "string", "description": "Absolute or relative path to the file" } }, "required": ["path"] } }, { "name": "run_bash", "description": "Execute a bash command and return stdout/stderr. Use for running tests, installing packages, or checking system state.", "input_schema": { "type": "object", "properties": { "command": { "type": "string", "description": "The bash command to execute" }, "timeout": { "type": "number", "description": "Timeout in seconds (default: 30)" } }, "required": ["command"] } } ]
컨텍스트 관리 — 에이전트가 얼마나 기억할 수 있나
에이전트의 가장 큰 제약 중 하나는 컨텍스트 윈도우(Context Window)다. Claude claude-opus-4-5는 200K 토큰, GPT-4o는 128K 토큰의 컨텍스트를 지원하지만, 대규모 코드베이스에서는 모든 정보를 컨텍스트에 넣을 수 없다.
컨텍스트 관리 전략
1. 계층적 요약 (Hierarchical Summarization)
긴 대화나 파일을 주기적으로 요약해 컨텍스트를 압축한다. Claude Code는 대화가 길어지면 자동으로 이전 내용을 요약해 컨텍스트 효율을 유지한다.
2. 검색 기반 컨텍스트 (RAG)
파일 전체를 컨텍스트에 넣는 대신, 임베딩 기반 유사도 검색으로 현재 태스크와 관련된 파일·함수만 선택적으로 로드한다. Cursor는 이 방식으로 대규모 코드베이스를 처리한다.
3. 외부 메모리
장기 기억이 필요한 정보(프로젝트 구조, 코드 컨벤션, 이전 결정)는 파일(CLAUDE.md 등)에 명시적으로 저장하고, 에이전트가 태스크 시작 시 로드한다.
에러 복구 — 에이전트가 스스로 고치는 원리
코딩 에이전트의 핵심 가치 중 하나는 자동 에러 복구다. 코드를 작성하고 테스트를 실행한 후 실패하면 에러 메시지를 컨텍스트에 추가해 다시 수정하는 사이클을 반복한다.
에러 복구 패턴
- 실행 → 에러 → 분석 → 수정: 가장 기본적인 패턴. 테스트 에러를 컨텍스트에 넣고 다시 수정 요청.
- 자기 검토 (Self-critique): 코드 작성 후 "이 코드에 버그가 있는가?"를 LLM에게 다시 질문해 품질을 높이는 패턴.
- 백트래킹: 잘못된 방향으로 n스텝 이상 진행했다고 판단하면 특정 체크포인트로 롤백. 파일 스냅샷이나 git 커밋이 체크포인트 역할을 한다.
에러 복구의 한계
자동 복구가 잘 동작하는 케이스는 에러 메시지가 명확하고 해결책이 지역적(특정 파일, 특정 함수)인 경우다. 다음 상황에서는 에이전트가 루프에 빠질 수 있다:
- 환경 설정 문제 (Dockerfile, 네트워크 등): 에러 메시지가 근본 원인을 가리키지 않음
- 아키텍처 수준의 설계 오류: 파일 단위 수정으로 해결 불가
- 비결정적 에러 (race condition, 타이밍 문제): 재현이 어려워 수정 확인이 불가
Claude Code / Cursor / Devin — 아키텍처 비교
주요 AI 코딩 에이전트들의 아키텍처 접근 방식을 비교한다.
| 항목 | Claude Code | Cursor | Devin |
|---|---|---|---|
| 실행 환경 | 로컬 터미널 | VS Code 통합 | 클라우드 VM |
| 코드베이스 탐색 | 파일 시스템 도구 | 임베딩 기반 RAG | RAG + 실행 기반 |
| 컨텍스트 지시 | CLAUDE.md | .cursorrules | 시스템 프롬프트 |
| 서브에이전트 | 지원 (병렬 태스크) | 제한적 | 지원 |
| 도구 확장 | MCP 서버 | 플러그인 시스템 | 내부 도구셋 |
| 자율 실행 범위 | 파일+셸 전체 | 편집기 내 | 풀스택 자율 |
직접 에이전트 만들기 — 언제 필요한가
범용 에이전트가 아닌 특정 워크플로우에 특화된 에이전트가 필요한 경우가 있다. 예: CI 파이프라인에서 자동 코드 리뷰 에이전트, 데이터 파이프라인 디버깅 에이전트, 특정 도메인의 코드 생성 에이전트. 이런 경우 Claude API + Tool Use + 커스텀 도구로 직접 구현하는 것이 기성품 에이전트보다 효율적이다.