코딩 에이전트는 그저 하나의 루프일 뿐입니다 — 의존성 없는 전체 구조 공개
요약
코딩 에이전트의 본질이 단순한 반복 루프임을 설명하며, 의존성 없는 Node.js 기반의 구현 구조를 공개합니다. 에이전트 설계 시 주의해야 할 단계별 예산 설정, 오류 처리 방식, 그리고 보안을 위한 경로 검증의 중요성을 다룹니다.
핵심 포인트
- 코딩 에이전트는 모델 호출과 도구 실행이 반복되는 하나의 루프 구조임
- 무한 루프 방지를 위해 maxSteps와 같은 단계별 예산 설정이 필수적임
- 도구 실행 오류는 중단이 아닌 모델이 인지할 수 있는 데이터로 전달해야 함
- 파일 접근 시 path.resolve만으로는 부족하며 경로 검증을 통한 샌드박스 구현이 필요함
누구나 에이전트 프레임워크 (agent framework)를 호출할 수는 있습니다. 하지만 그 밑에서 무엇이 돌아가는지 다시 구축할 수 있는 사람은 거의 없습니다. 그러다 무언가 고장 나면: 도구 호출 (tool call)이 무한 루프에 빠지거나, 토큰 비용이 폭발하며, 프레임워크의 추상화 (abstraction)가 갑자기 당신과 해결책 사이를 가로막는 장애물이 됩니다.
여기 불편한 비밀이 있습니다: Claude Code, Cursor, 그리고 모든 "AI 엔지니어" 제품의 근간이 되는 코딩 에이전트 (coding agent)는 바로 **하나의 루프 (one loop)**입니다. 모델에게 무엇을 할지 묻고, 모델이 요청하는 도구 (tools)를 실행하고, 그 결과를 다시 입력으로 넣어주고, 모델이 완료되었다고 말할 때까지 반복하는 것입니다. 이 포스트에서는 의존성 없이 순수 Node.js로 이 루프를 구축하고, 거의 모든 첫 구현이 빠지는 두 가지 함정을 보여줍니다.
루프 (The loop)
실제 모델이든 모의 모델 (mocked model)이든, 모든 모델은 { messages, tools }를 입력받아 { toolCalls: [...] } 또는 { done: true, text }를 반환하는 하나의 함수일 뿐입니다. 모든 것이 여기에 연결됩니다:
export async function runAgent({ task, model, tools, maxSteps = 10, log = () => {} }) {
const messages = [{ role: 'user', content: task }];
...
이 안에는 네 가지 핵심적인 결정 사항이 있습니다:
- 모델은 파라미터 (parameter)입니다. 스크립트로 작성된 모의 모델 (mock)과 실제 작동하는 LLM은 동일한 계약 (contract)을 충족하므로, 루프는 절대 변하지 않습니다. 따라서 당신의 CI (지속적 통합) 환경에서 API 키 없이도 에이전트를 실행할 수 있습니다.
maxSteps가 루프를 제한합니다. 단계별 예산 (step budget)이 없는 에이전트는 신용카드를 들고 있는 무한 루프와 같습니다.- 도구 실패는 충돌이 아니라 데이터입니다.
try/catch는 발생한ENOENT오류를 모델이 볼 수 있는 결과 문자열로 변환합니다. 그래야 모델이 경로를 수정하거나 다른 접근 방식을 시도하는 등의 반응을 할 수 있기 때문입니다. MCP (Model Context Protocol)도isError를 통해 동일한 개념을 인코딩합니다. 이것이 없다면, 단 한 번의 잘못된 읽기 작업이 전체 실행을 중단시킵니다. - 트랜스크립트 (transcript)가 상태 (state)입니다. 모델은 상태가 없는 (stateless) 존재입니다. 계속 늘어나는
messages배열이 에이전트의 전체 메모리입니다.
함정 #1: path.resolve는 샌드박스 (sandbox)가 아닙니다
에이전트에게 파일 도구를 부여하면 아마 다음과 같이 작성하게 될 것입니다:
const resolve = (p) => path.resolve(cwd, p); // "모든 경로는 워크스페이스 내에 머문다"... 맞죠?
아닙니다. 그리고 단 한 줄로 증명할 수 있습니다: path.resolve(cwd, '../escape.txt')는 아무 문제 없이 cwd 외부의 경로를 반환하며, 절대 경로도 마찬가지입니다. 사용자의 '샌드박스' 에이전트는 프로세스가 접근 가능한 모든 곳에 쓸 수 있습니다.
진정한 격리(containment)는 **해결(resolve)**한 다음, **검증(verify)**하는 것입니다:
const resolve = (p) => {
const full = path.resolve(cwd, p);
const rel = path.relative(cwd, full);
...
path.relative는
루프는 10개 구성 요소 중 하나
에이전트 루프(agent loop)는 스택의 한 조각일 뿐입니다. 전체 지도(build-your-own-agent)는 10가지 구성 요소 각각에 대해 가장 강력한 바닥부터 구축하는(from-scratch) 튜토리얼을 색인화합니다: 에이전트 루프, 도구 호출(tool calling), 메모리(memory), RAG, MCP, 코딩 에이전트(coding agents), 토큰 회계(token accounting), 평가(evals), 다중 에이전트(multi-agent), 그리고 가드레일(guardrails). 좋은 자료가 없었던 곳에는 자체적인 단계별 튜토리얼을 배포하며, 각 튜토리얼은 빈 파일에서 실행 가능한 코드를 구축합니다:
- 코딩 에이전트 구축하기 — 이 게시물의 전체 버전: 루프, 도구, 샌드박싱(sandboxing), 목 모델(mock) 및 라이브 모델
- MCP 서버 + 클라이언트 구축하기 — 전체 '프로토콜'은 JSON-RPC이며 3가지 메서드로 구성됩니다
- 토큰 회계 구축하기 — 비용 계산 및 프롬프트 캐시 경제학; 데모는 원리(first principles)로부터 ~80%의 캐시 절감액을 재현합니다.
색인화된 모든 링크는 CI를 통해 매주 가져오고 재확인되며, 모든 데모는 푸시될 때마다 실행되고, 어떤 리소스도 색인 전체에 걸쳐 중복되어 나타나지 않습니다. 이것은 의도적으로 색인이며, 또 다른 강좌가 아닙니다 — 벤더 중립적(vendor-neutral)이고 프레임워크 독립적(framework-free)입니다.
만약 어떤 섹션에 대해 더 강력한 바닥부터 구축하는 자료를 알고 있다면, 기준이 높게 설정된 것이니 가져와 주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기