Swift로 Claude Code 스타일 Coding Agent 처음부터 만들기
Building a coding agent in Swift from scratch
TL;DR Highlight
Claude Code가 왜 잘 동작하는지 이해하기 위해 핵심 구조를 Swift로 9단계에 걸쳐 재구현한 학습 프로젝트로, '도구는 적게, 모델에게 더 많이 맡겨라'는 설계 철학을 직접 검증한다.
Who Should Read
LLM 기반 코딩 에이전트를 직접 구현해보고 싶은 백엔드/iOS 개발자, 또는 Claude Code 같은 AI 에이전트가 내부적으로 어떻게 동작하는지 원리 수준에서 이해하고 싶은 개발자.
Core Mechanics
- 이 프로젝트의 핵심 가설은 '도구가 많을수록 에이전트가 좋아진다'는 통념에 반론을 제기한다. Claude Code가 효과적인 이유는 복잡한 오케스트레이션이 아니라 검색 도구, 파일 편집 도구처럼 단순하지만 품질 높은 소수의 도구와 모델에 대한 높은 신뢰 덕분이라는 것이 저자의 주장이다.
- 에이전트 루프 설계 원칙으로 5가지를 제시한다: ① 소수의 고품질 도구 > 방대한 도구 카탈로그, ② 얇은 오케스트레이션(모델이 직접 판단), ③ 명시적인 태스크 상태 관리로 신뢰성 향상, ④ 영속 메모리보다 제어된 컨텍스트 주입이 더 중요, ⑤ Context Compaction(컨텍스트 압축)은 단순한 토큰 절약이 아니라 실제 제품 기능이다.
- 총 9개 단계(Stage)로 구성된 학습 시리즈 형태로 구현되었고, 각 단계가 루프, 도구 디스패치, 상태 유지, 서브에이전트/스킬/컨텍스트 압축 등 하나의 메커니즘을 격리해서 실험하도록 설계되었다. 덕분에 어떤 아키텍처 결정이 실제로 차이를 만드는지 직접 눈으로 확인할 수 있다.
- 구현 언어로 Swift를 선택한 이유가 단순한 취향 이상이다. Swift의 Structured Concurrency(구조화된 동시성, async/await 기반으로 작업 생명주기를 명확하게 관리하는 방식)가 에이전트 루프 구조와 자연스럽게 맞아떨어지고, 강타입 시스템 덕분에 도구 스키마를 정의할 때 다른 언어에서 흔한 JSON 문자열 파싱 오류가 줄어든다.
- 프로젝트 구조는 Sources, Tests, docs, skills/example 디렉토리로 구성되어 있으며, .env.example 파일과 Package.swift가 포함되어 있어 Swift Package Manager로 바로 빌드할 수 있다. GitHub Actions 워크플로우도 포함되어 있다.
- 저자는 '대부분의 마법은 상태 관리와 제어 흐름에 있다'고 결론 내린다. 즉, LLM 자체의 능력보다 에이전트가 언제 무엇을 하는지 명확하게 통제하는 설계가 품질을 좌우한다는 주장이다.
- 전체 9부 학습 시리즈가 ivanmagda.dev에 공개되어 있어 단순히 코드를 읽는 것을 넘어 단계별 설계 의도와 실험 결과를 글로도 확인할 수 있다.
Evidence
- 긴 세션에서의 컨텍스트 관리가 가장 어려운 부분이라는 실전 경험이 공유됐다. 한 댓글 작성자는 하드 컨텍스트 한계에 도달하기 훨씬 전부터 도구 호출 히스토리가 쌓이면 '다시 확인해볼게요' 루프나 모호한 도구 선택 같은 품질 저하가 발생한다고 지적했다. 이를 해결하기 위해 ① 완료된 서브태스크 출력을 요약해서 compact한 작업 메모리 블록으로 교체, ② 정보를 추출한 후 중간 파일 읽기 결과는 공격적으로 드롭, ③ 초기 시스템 프롬프트에 '완료' 상태의 명확한 정의를 포함시키는 방법이 도움이 됐다고 한다.
- CLI 컴포넌트 이름을 'claude'라고 지은 것에 대해 법적 문제를 우려하는 댓글이 있었다. Anthropic의 상표와 충돌할 수 있으므로 테이크다운 요청을 받을 수 있다는 실질적인 경고였다.
- 에이전트 루프의 핵심 부분을 처리하는 Swift 라이브러리 'Operator'(github.com/bensyverson/Operator)를 직접 만들었다는 개발자가 링크를 공유했다. 비슷한 작업을 하는 사람에게 시간을 아껴줄 수 있다고 소개했다.
- 단계별 빌드 방식이 실패 모드를 명확하게 만든다는 점을 높이 평가하는 댓글이 있었다. 루프 → 도구 디스패치 → 상태 유지 → 서브에이전트/스킬/압축 순서로 쌓아가면서 '대부분의 마법이 상태 관리와 제어 흐름에 있다'는 것을 상기시켜줬다는 반응이다.
- Apple Intelligence가 Gemini를 코어로 사용하게 되면 이 프로젝트에 드롭인해서 100% 로컬 AI 에이전트를 만들 수 있을지 묻는 댓글도 있었다. 직접적인 답변은 없었지만 Swift 생태계에서 로컬 모델 연동에 대한 관심이 있음을 보여준다.
How to Apply
- Claude Code 같은 코딩 에이전트를 직접 만들어보고 싶다면, 이 레포의 9단계 시리즈를 처음부터 따라가면서 각 단계에서 하나의 메커니즘(루프 → 도구 디스패치 → 컨텍스트 관리 순)만 집중적으로 구현해보면 된다. 한 번에 전체를 구현하려는 것보다 실패 원인을 훨씬 빠르게 격리할 수 있다.
- 긴 세션에서 에이전트 품질이 떨어지는 문제를 겪고 있다면, 도구 호출 히스토리 전체를 컨텍스트에 유지하는 대신 완료된 서브태스크는 요약 블록으로 교체하고 이미 정보를 추출한 파일 읽기 결과는 즉시 드롭하는 방식을 적용해볼 것. 댓글 경험에 따르면 하드 컨텍스트 한계 이전에 품질이 먼저 떨어지는 문제를 크게 줄여준다.
- 새 코딩 에이전트를 설계할 때 도구 수를 늘리기 전에 기존 도구의 품질을 먼저 높이는 방향을 검토해볼 것. 이 프로젝트의 가설처럼, 검색 도구 하나와 파일 편집 도구 하나라도 각 도구가 정확하게 동작한다면 20개의 허술한 도구보다 낫다는 것을 실험을 통해 직접 검증해볼 수 있다.
- Swift로 에이전트를 구현하려는 경우, 댓글에서 소개된 'Operator' 라이브러리(github.com/bensyverson/Operator)를 먼저 살펴보면 에이전트 루프 보일러플레이트 코드를 줄일 수 있다.
Terminology
Agent Loop에이전트가 '사용자 입력 → 모델 추론 → 도구 실행 → 결과 피드백 → 다시 추론' 과정을 반복하는 핵심 사이클. 무한루프처럼 돌다가 태스크 완료 조건을 만나면 멈춘다.
Context Compaction대화/작업 히스토리가 길어질수록 토큰이 낭비되고 모델 성능이 떨어지는 문제를 해결하기 위해 오래된 내용을 요약본으로 압축하는 기법. 단순한 비용 절감이 아니라 품질 유지를 위한 필수 기능.
Orchestration여러 도구와 모델 호출을 조율하는 상위 레이어. 두껍게 만들수록 복잡도가 올라가고, 이 프로젝트는 최대한 얇게 유지하는 것을 목표로 한다.
Structured ConcurrencySwift 5.5에서 도입된 async/await 기반 동시성 모델. 작업의 생명주기와 취소가 코드 구조에 명확히 표현되어 에이전트처럼 병렬 도구 실행이 필요한 경우에 오류 추적이 쉽다.
Tool Schema에이전트가 사용할 수 있는 도구의 이름, 파라미터, 타입을 LLM이 이해할 수 있는 형태로 정의한 명세. 잘못 정의하면 모델이 엉뚱하게 도구를 호출한다.
Sub-agent메인 에이전트가 복잡한 태스크를 처리할 때 특정 서브태스크를 위임하는 독립적인 에이전트 인스턴스. 병렬 처리나 역할 분리에 활용된다.