어떤 에이전트 기반 코딩 패턴이 실제로 확장 가능한가
요약
에이전트 기반 코딩 패턴이 프로젝트 규모가 커짐에 따라 직면하는 확장성 문제를 분석합니다. 코드베이스 성장, 작업 복잡도, 에이전트 수 증가, 프로젝트 기간 연장에 따른 기존 패턴의 한계와 고려 사항을 다룹니다.
핵심 포인트
- 단순한 패턴은 초기 구현에는 유용하나 대규모 코드베이스에서는 한계가 있음
- 확장성은 코드베이스 성장, 작업 복잡도, 에이전트 수, 프로젝트 기간에 의해 결정됨
- 단일 에이전트 감독 방식은 사용자의 주의력과 컨텍스트 윈도우 제한에 부딪힘
- 병렬 작업 시 에이전트 간 결정 사항 공유와 충돌 방지가 핵심 과제임
대부분의 에이전트 기반 코딩 패턴(agentic coding patterns)은 첫 번째 모듈에서는 잘 작동합니다. 스킬 프레임워크(skills framework), 멀티 워크트리 설정(multi-worktree setup), 오케스트레이션 러너(orchestrated runner)와 같은 워크플로우를 선택하면 오후 한나절 만에 실제 결과물을 만들어낼 수 있습니다. 그것은 어려운 부분이 아닙니다. 사람들이 몇 달 뒤, 코드베이스(codebase)가 성장하고 작업이 복잡해졌을 때 마주하게 되는 질문은, 그 패턴이 그때도 여전히 작동하느냐 하는 것입니다. 대부분의 패턴에 대한 솔직한 답변은 '그렇지 않다'입니다.
이것은 도구(tooling)에 대한 비판이 아닙니다. 이는 문제 자체의 속성입니다. 고립된 상태에서 기능을 구축하는 것과 수십 개의 병렬 세션에 걸쳐 시스템을 유지하는 것은 서로 다른 활동입니다. 첫 번째 상황에서 승리하는 패턴이 두 번째 상황에서도 자동으로 승리하지는 않습니다.
다음은 일반적인 패턴들이 무엇에 유용하며, 각각 어느 지점에서 한계에 부딪히는지에 대한 솔직한 분석입니다.
여기서 "확장(scales)"한다는 의미
제가 말하는 "확장(scales)"이란 프로젝트가 성숙함에 따라 함께 나타나는 네 가지 요소를 의미합니다:
- 코드베이스 성장 (Codebase growth). 코드베이스에는 히스토리, 축적된 컨벤션(conventions), 그리고 다른 에이전트들이 의존하는 라이브 인터페이스(live interfaces)가 존재합니다. 코드베이스를 대상으로 작업하는 에이전트들은 단순히 오늘 무엇을 구현하고 있는지만이 아니라, 무엇이 이미 존재하며 어떤 결정이 내려졌는지를 알아야 합니다.
- 작업 복잡도 (Task complexity). 세 개의 컴포넌트(components)를 건드리며 아키텍처 결정(architectural decision)이 필요한 작업은 파일 하나를 수정하는 작업과는 다릅니다. 단순한 사례에서 작동하는 패턴은 복잡한 사례에서 어려움을 겪는 경우가 많습니다.
- 에이전트 수 (Agent count). 두 개의 병렬 에이전트에서 여덟 개로 늘어나는 것은 단순히 처리량(throughput)뿐만 아니라 조정 범위(coordination surface)를 변화시킵니다. 한 세션에서 내려진 결정이 다른 세션에도 전달되어야 하며, 충돌(conflicts)은 머지(merge) 전에 드러나야 합니다.
- 기간 (Duration). 6시간의 스프린트(sprint)는 몇 주 동안 진행되는 프로젝트와 다릅니다. 이전 결정에 대한 기억, 과거 버그의 형태, 그리고 명확하지 않은 선택 뒤에 숨겨진 근거(rationale)는 단일 세션보다 더 오래 지속되어야 합니다.
단일 에이전트, 감독형 (single-agent, supervised)
단 하나의 Claude Code 세션입니다. 당신이 모든 줄을 지켜보며, 매 단계마다 승인하거나 방향을 수정합니다. 이것이 대부분의 사람들이 시작하는 방식이며, 제한된 작업(bounded task) — 새로운 라우트, 리팩토링된 함수, 독립형 스크립트 등 — 에 대해서는 올바른 선택입니다. 당신이 루프(loop) 안에 있기 때문에 일관성(coherence)을 유지하기가 쉽습니다.
한계점은 당신의 주의력(attention)입니다. 처리량(throughput)은 정확히 에이전트 한 명이며, 에이전트의 컨텍스트 윈도우(context window)가 유일한 공유 메모리입니다. AI 코딩 도입 사다리(AI coding adoption ladder)의 1단계를 통과할 때까지는 잘 작동합니다. 하지만 작업 스트림(stream of work)을 하나 이상으로 늘리고 싶어지는 순간, 당신은 이 방식을 넘어선 것입니다.
수동 브리핑을 통한 병렬 에이전트 (parallel agents, briefed by hand)
여러 개의 워크트리(worktrees)를 생성하고, 각 에이전트가 시작하기 전에 브리핑을 제공합니다. 이것은 병렬성(parallelism)으로 나아가는 자연스러운 첫 단계이며, 명확하게 분해된 작업(decomposed tasks)을 수행하는 몇 명의 에이전트에게는 종종 잘 작동합니다.
오버헤드(overhead)는 선형적(linear)입니다. 새로운 에이전트가 추가될 때마다 브리핑이 필요하며, 각 브리핑은 그렇지 않으면 손실될 모든 공유 컨텍스트(shared context) — 컨벤션(conventions), 당일 초기에 내려진 결정들, 다른 에이전트들이 합의한 인터페이스(interfaces) 등 — 를 포함해야 합니다. 에이전트가 두 명일 때는 관리 가능합니다. 하지만 다섯 명이 되면 당신이 통합 계층(integration layer)이 됩니다. 모든 결정이 당신의 작업 기억(working memory)을 거쳐야 하며, 당신의 작업 기억은 확장(scale)되지 않습니다. 우리는 병렬 Claude Code 에이전트를 운영할 때의 인지 부하(cognitive load of running parallel Claude Code agents)에 대해 더 자세히 작성한 바 있습니다.
또 다른 실패 모드(failure mode)는 발산(divergence)입니다. 오늘 아침에 브리핑을 받은 두 에이전트가 오후에 변경된 코드베이스를 대상으로 작업한다면, 그들은 이제 오래된 컨텍스트(stale context)를 바탕으로 작업하게 됩니다. 오전 9시에 작성한 브리핑은 에이전트 A가 오전 11시에 재작성한 인터페이스를 반영하지 못합니다.
스킬 프레임워크 (Skills frameworks: Superpowers, GSD, gstack)
스킬 프레임워크 (Skills frameworks)는 Claude Code에 표준화된 명령 어휘를 설치합니다. 즉, 슬래시 명령 (slash commands), 타입이 지정된 워크플로 (typed workflows), 그리고 세션 전반에 걸쳐 적용되는 확고한 관례 (opinionated conventions)를 제공합니다. 우리는 이 카테고리를 심도 있게 다루었습니다. 요약하자면, 이들은 반복 가능한 마이크로 패턴 (micro-patterns)과 일관된 품질 기준을 설정하는 데 매우 탁월하며, 특히 "모두가 제각각 다르게 작업한다"는 점이 실제 문제인 팀에서 더욱 빛을 발합니다.
하지만 이들이 제공하지 못하는 것은 세션 간 메모리 (cross-session memory)나 오케스트레이션 (orchestration)입니다. 각 호출은 새로 시작됩니다. 프레임워크는 에이전트에게 테스트를 작성하는 방법을 알려줄 수는 있지만, 지난주에 어떤 결정이 내려졌는지, 현재 어떤 인터페이스가 사용 중인지, 또는 다른 에이전트가 지금 무엇을 하고 있는지는 알려줄 수 없습니다. 에이전트 간의 조정은 여전히 수동으로 이루어져야 합니다.
이는 매우 중요한 차이점입니다. 스킬 프레임워크는 개별 에이전트 품질의 "방법 (how)" 문제를 해결합니다. 하지만 시간이 흐름에 따라 병렬로 작동하는 에이전트들 사이의 "누가 무엇을 아는가 (who knows what)" 문제는 해결하지 못합니다. 코드베이스가 성장하고 세션에 결정 사항이 누적되는 경우, 이 격차는 약 두 달 차쯤에 나타납니다.
오케스트레이션 러너 (orchestrated runners: Conductor 스타일)
Conductor와 같은 도구는 팬아웃 (fan-out)을 자동화합니다. 즉, 에이전트를 생성하고, 작업을 라우팅하며, 워크트리 (worktrees)를 관리하고, 사용자가 각 에이전트에게 일일이 브리핑할 필요 없이 많은 에이전트를 동시에 실행합니다. 대규모의 순수 병렬 처리(예: 50개의 작업이 동시에 실행되는 경우)를 위해서는 이것이 적합한 도구입니다. 생성 및 조정 문제는 진정으로 해결됩니다.
오케스트레이터가 추가하지 못하는 것은 프로세스 구조나 코드베이스 상태에 대한 공유 메모리 (shared memory)입니다. 오케스트레이터에 의해 생성된 에이전트는 여전히 자신의 프롬프트와 워크트리에 포함된 컨텍스트로 시작합니다. 생명주기 (lifecycle)가 존재하지 않기 때문에, 에이전트는 설계가 확정되기 전에 구현을 시작하거나, 인접 모듈이 안정화되기 전에 리뷰를 위해 코드를 배포할 수도 있습니다. 구조화된 게이트 (structured gates) 없이 병렬로 실행되는 50개 에이전트의 결과물을 디버깅하는 것은, 감독하에 하나의 에이전트를 실행하는 것과는 전혀 다른 종류의 문제입니다.
이 방식은 대량의, 잘 분해된, 상대적으로 독립적인 작업에 가장 적합합니다. 작업 결합도(Task coupling)가 증가할 때 — 즉, 한 에이전트의 출력이 다른 에이전트의 입력이 되거나, 하나의 설계 결정이 모든 에이전트를 구속해야 할 때 — 오케스트레이터(Orchestrator)는 분배를 담당하지만, 일관성(Coherence)은 여러분의 몫으로 남겨둡니다.
스펙 우선, 그 다음 팬아웃 (spec-first, then fan out)
어떤 에이전트도 시작하기 전에 스펙(Spec)을 작성하는 규율은 이 목록에서 가장 레버리지가 높은(highest-leverage) 관행입니다. 병렬 작업으로 분해하기 전에 설계와 인터페이스(Interface)를 확정하면, 에이전트들은 구축 중간에 서로 협상하지 않고 공유된 계약(Shared contract)에 따라 구현합니다. 위에서 설명한 대부분의 발산(Divergence) 실패는 이 과정을 잘 수행한다면 발생하지 않습니다.
문제는 강제성(Enforcement)입니다. 저장소(Repo)에 있는 spec.md는 문서일 뿐, 게이트(Gate)가 아닙니다. 에이전트들은 구현 중간에 스펙에서 벗어날 수 있으며 실제로도 그렇게 합니다. 구현 중에 설계 결정 사항이 드러나거나, 인터페이스가 약간 잘못된 것으로 판명되거나, 명시되지 않은 엣지 케이스(Edge case)가 나타날 수 있습니다. 이러한 문제들은 리뷰(Review) 단계 전까지는 반드시 드러나는 것이 아니며, 만약 리뷰가 비공식적이라면 아예 드러나지 않을 수도 있습니다. 패턴은 옳지만, 이를 뒷받침할 구조가 없다면 규율을 유지하기 어렵습니다. 이로 인해 발생하는 실패 모드에 대해서는 왜 AI 코딩 에이전트에게 엄격한 단계적 경계가 필요한가를 참조하세요.
게이트가 있는 라이프사이클 (gated lifecycle)
가장 오래 지속되는 패턴은 스펙 우선 방식과 강제된 단계별 게이트(Stage gates)를 결합하는 것입니다. 즉, 구현이 시작되기 전에 설계와 아키텍처(Architecture)가 해결되고, 에이전트들은 확정된 계약에 따라 구현하며, 무언가를 병합(Merge)하기 전에 구조화된 리뷰 게이트를 거칩니다. 설계 단계에서 내려진 결정은 모든 구현 에이전트를 구속합니다. 리뷰 단계는 결과물이 배포(Ship)되기 전에 발산(Divergence)을 잡아냅니다.
트레이드오프(Tradeoff)는 이러한 방식이 작거나 탐색적인 작업에는 설정 오버헤드(Setup overhead)를 추가한다는 점입니다. 만약 빠른 개념 증명(Proof of concept)을 작성 중이거나 곧 버려질 스크립트를 작성하고 있다면, 게이트 방식의 라이프사이클(Gated lifecycle)은 과합니다. 이 방식은 유의미한 복잡성을 가진 작업이나 지속적으로 진화할 프로젝트에서 그 비용만큼의 가치를 발휘합니다. 즉, 오늘 내려진 결정이 3주 후에 실행할 에이전트들에게도 중요하게 작용하는 프로젝트 말입니다.
현재의 패턴이 확장 가능한지 테스트하는 유용한 방법은 다음과 같습니다: 2주 전에 내렸던 결정 하나를 골라보세요. 아키텍처 결정, 명명 규칙(Naming convention), 혹은 횡단 관심사(Cross-cutting concern)에 대한 접근 방식 같은 것 말입니다. 당신이 직접 전달하는 매개체가 되지 않고도, 오늘 모든 에이전트가 그 결정을 준수하고 있는지 확인할 수 있습니까? 만약 그렇지 않다면, 그것이 바로 격차(Gap)입니다.
확장 가능한 것들의 공통점: 한 번 내린 결정이 일관되게 강제됨; 팬아웃(Fan-out)이 일어나기 전에 인터페이스(Interface)가 확정되며 빌드 도중에 협상되지 않음; 단일 세션보다 오래 지속되는 코드베이스 상태에 대한 메모리(Memory); 단순히 처리량(Throughput)을 위한 게이트가 아닌 품질 게이트(Quality gates). 에이전트의 수와 프로젝트 기간이 증가함에 따라, 당신이 통합 계층(Integration layer) 역할을 해야만 하는 패턴은 더 이상 유지될 수 없습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기