모노레포(Monorepo) vs 멀티레포(Multi-Repo): 왜 AI 에이전트가 승부의 저울을 기울이는가
요약
모노레포와 멀티레포 사이의 오랜 논쟁이 AI 코딩 에이전트의 등장으로 새로운 국면을 맞이하고 있습니다. AI 에이전트가 최적의 성능을 내기 위해서는 넓은 컨텍스트 확보가 필수적이며, 이에 따라 원자적 변경과 통합된 의존성 그래프를 제공하는 모노레포가 새로운 우위를 점하고 있습니다.
핵심 포인트
- 과거의 저장소 구조 결정은 인간 엔지니어의 워크플로와 관리 편의성에 최적화되어 있었습니다.
- AI 코딩 에이전트의 핵심 요구사항은 전체 코드베이스에 대한 넓은 컨텍스트 대역폭입니다.
- 모노레포는 서비스 간 원자적 변경과 단일 의존성 그래프를 제공하여 AI 에이전트의 작업 효율을 높입니다.
- 멀티레포의 장점이었던 독립적 버전 관리와 격리된 빌드는 AI 에이전트의 컨텍스트 제한 문제로 인해 상대적 가치가 변화하고 있습니다.
모노레포(Monorepo) 대 멀티레포(Multi-Repo) 논쟁은 명확한 승자 없이 10년 넘게 이어져 왔습니다. 그것은 엔지니어들이 의견을 모으지 못해서가 아니라, 두 모델 모두 서로 다른 제약 조건 하에서 진정한 장점을 제공했기 때문입니다. 3개의 서비스를 가진 50명 규모의 스타트업과 수백 개의 마이크로서비스(Microservices)를 가진 10,000명 규모의 기업은 서로 다른 문제에 직면했습니다. 적절한 저장소 구조는 팀 규모, 배포 주기(Deployment cadence), 소유권 모델(Ownership models), 그리고 도구의 성숙도(Tooling maturity)에 따라 달라졌습니다.
하지만 그 계산법이 바뀌었습니다. AI 코딩 에이전트(AI coding agents), 코드 생성(Code generation), 그리고 에이전트 기반 개발 워크플로(Agentic development workflows)가 저장소 모델에서 중요한 요소들을 변화시켰습니다. AI 코딩 에이전트에게 최대의 컨텍스트(Context)를 제공하고, 원자적 교차 변경(Atomic cross-cutting changes)과 트랜잭션 실행(Transactional execution)을 가능하게 하는 저장소 모델이 이제 명확한 우위를 점하고 있습니다. 그 모델이 바로 모노레포(Monorepo)입니다.
과거의 트레이드오프(Tradeoffs)는 실재했습니다. AI 코딩 에이전트가 주류가 되기 전, 모노레포 대 멀티레포 결정은 인간의 워크플로(Workflows)에 최적화되어 있었습니다. 즉, 엔지니어가 코드를 탐색하는 방식, 팀이 소유권 경계를 긋는 방식, CI/CD 파이프라인이 확장되는 방식, 그리고 릴리스(Releases)가 배포되는 방식에 맞춘 결정이었습니다.
모노레포(Monorepo)는 서비스 간 원자적 변경(Atomic cross-service changes), 단일 의존성 그래프(Single dependency graph), 통합된 CI/CD, 그리고 내부 라이브러리 간의 버전 불일치(Version skew) 제로를 제공했습니다. 그 대가는 큰 클론(Clone) 크기, 빌드 캐싱(Build caching) 없이는 느려지는 CI, 복잡한 권한 모델, 그리고 빌드 속도를 유지하기 위한 Bazel, Pants, Nx 또는 Buck2와 같은 전문 도구의 필요성이었습니다.
멀티레포(Multi-repo)는 강력한 소유권 경계, 독립적인 버전 관리(Versioning), 더 작은 체크아웃(Checkouts), 더 빠른 격리된 빌드, 그리고 무언가 고장 났을 때의 영향 범위(Blast radius) 감소를 제공했습니다. 그 대가는 고통스러운 저장소 간 변경(Cross-repo changes), 서비스 간의 의존성 드리프트(Dependency drift), 버전 조정 오버헤드(Version coordination overhead), 그리고 공유 API 계약(Shared API contracts)을 둘러싼 마찰이었습니다.
두 가지 트레이드오프 모두 실재했습니다. Google은 모노레포를 선택하고 수십억 줄의 코드에서 이를 작동시키기 위해 소스 제어를 위한 Piper, 클라우드 워크스페이스를 위한 CitC, 빌드를 위한 Blaze와 같은 커스텀 도구에 막대한 투자를 했습니다. 많은 기업은 멀티레포를 선택하고 경계 지점에서 조정 프로세스(Coordination processes)를 구축했습니다. 어느 쪽도 틀리지 않았습니다.
단지 입력값(Inputs)이 아직 변하지 않았을 뿐입니다. AI가 최적화 함수(Optimization function)를 바꾸었습니다. AI 코딩 에이전트(AI coding agents)는 기존의 트레이드오프(Tradeoff) 분석이 의존했던 세 가지 가정을 변화시켰습니다.
이제 컨텍스트 대역폭(Context bandwidth)이 결합 제약 조건(Binding constraint)이 되었습니다. AI 코딩 에이전트는 전체 코드베이스에 걸친 타입 정의(Type definitions), 호출 지점(Call sites), 테스트 케이스(Test cases), 의존성 관계(Dependency relationships), 그리고 사용 패턴(Usage patterns) 등 전체 그림을 볼 수 있을 때 더 나은 코드를 생성합니다. 저장소 경계(Repository boundary)는 하나의 컨텍스트 벽(Context wall)입니다. 모든 벽은 AI가 생성한 결과물의 품질을 저하시킵니다.
횡단적 변경 비용(Cross-cutting change cost)은 0에 가깝게 떨어졌습니다. 인터페이스를 이름을 바꾸고, 모든 호출 지점을 업데이트하며, 다운스트림 테스트(Downstream tests)를 수정하고, 문서를 조정하는 작업은 과거에 여러 저장소에 걸쳐 며칠간의 조정 노력이 필요한 일이었습니다. 모노레포(Monorepo) 환경의 AI 코딩 에이전트는 이를 단 한 번의 패스(Single pass)로 수행합니다. 멀티레포(Multi-repo) 설정에서는 동일한 변경을 위해 여전히 조정된 PR(Pull Requests), 버전 업데이트(Version bumps), 릴리스 순서(Release ordering), 그리고 호환성 윈도우(Compatibility windows)가 필요합니다.
의존성 추론(Dependency reasoning)이 자동화되었습니다. 엔지니어들은 과거에 서비스들이 서로 어떻게 의존하는지에 대한 정신적 모델(Mental models)을 유지해야 했습니다. AI 코딩 에이전트는 실제 의존성 그래프(Dependency graph)를 읽습니다. 이 그래프가 더 크고 더 연결되어 있을수록, 에이전트는 변경 영향(Change impact)에 대해 더 정확하게 추론합니다. 저장소 전반에 걸쳐 그래프를 파편화하면 에이전트는 볼 수 없는 경계를 추측해야만 합니다.
이 세 가지 변화가 멀티레포를 불가능하게 만드는 것은 아닙니다. 다만 멀티레포를 과거보다 모노레포 대비 더 비용이 많이 드는 방식으로 만듭니다.
컨텍스트가 새로운 병목 현상(Bottleneck)입니다. 구체적인 시나리오를 생각해 봅시다. 당신이 AI 코딩 에이전트에게 5개의 서비스가 소비하는 공유된 protobuf 정의 내의 필드 이름을 바꾸라고 요청한다고 가정해 보겠습니다. 모노레포에서는 에이전트가 .proto 파일, 생성된 바인딩(Generated bindings), 그리고 모든 서비스의 핸들러 코드(Handler code)를 볼 수 있습니다. 에이전트는 필드 이름을 바꾸고, 바인딩을 재생성하며, 한 번의 패스로 5개의 소비자(Consumers)를 모두 업데이트합니다. 멀티레포 설정에서 에이전트는 proto 정의 저장소만 볼 수 있습니다. 거기서 필드 이름을 바꾸긴 하지만, 이를 소비하는 5개의 서비스는 별도의 저장소에 존재합니다.
각각의 서비스는 다음 빌드 시점에 깨지게 되며, 누군가는 수동으로 업데이트를 조율해야 합니다. 이러한 실패 모드는 일반화될 수 있습니다. 서비스 A에서 작업하는 AI 코딩 에이전트(AI coding agent)가 서비스 B가 공유 라이브러리(shared library)를 어떻게 소비하는지 이해해야 할 때, 에이전트는 해당 코드에 접근할 수 있거나 혹은 접근할 수 없거나 둘 중 하나입니다. 멀티레포(Multi-repo) 환경에서는 대개 접근할 수 없습니다. 에이전트는 스텁(stub) 가정을 사용하거나, 불완전한 타입 힌트(type hints)로부터 API 동작을 추론하거나, 혹은 고립된 상태에서는 작동하지만 통합(integration) 시점에 깨지는 코드를 생성하게 됩니다. 멀티레포 프로젝트에서 AI 코딩 에이전트를 사용해 본 사람이라면 누구나 이와 유사한 상황을 경험했을 것입니다. 에이전트가 로컬에서는 컴파일되지만 다른 저장소에 정의된 계약(contract)을 위반하는 변경 사항을 생성하는 경우 말입니다. 해결책은 매번 동일합니다. 에이전트에게 더 많은 컨텍스트(context)를 제공하는 것입니다. 모노레포(Monorepo)는 기본적으로 모든 컨텍스트를 제공합니다.
횡단적 변경(Cross-cutting changes)이 비싼 비용에서 저렴한 비용으로 바뀌었습니다. AI 코딩 에이전트는 횡단적 작업에서 가장 효과적입니다. 예를 들어, 공유 인터페이스(shared interface)를 리팩터링하고 모든 소비자(consumer)를 업데이트하거나, 의존성(dependency)을 마이그레이션하고 모든 하위 단계의 오류를 수정하거나, 혹은 서비스 경계를 가로질러 타입 변경(type change)을 전파하는 작업 등이 이에 해당합니다. 모노레포에서는 이러한 작업들이 원자적 연산(atomic operations)이 됩니다. 에이전트는 소스를 수정하고, 모든 호출 지점(call site)을 업데이트하며, 테스트를 조정하고, CI(Continuous Integration)를 통과하거나 통과하지 못하는 단일 커밋(single commit)을 생성합니다. 부분적인 상태(partial state)도, 버전 왜곡(version skew)도 없습니다. 서비스 A는 새로운 인터페이스를 실행하고 있는데 서비스 B는 여전히 이전 인터페이스를 기대하는 시간적 간극(window)도 존재하지 않습니다.
멀티레포 설정에서 동일한 변경 사항은 분산 트랜잭션(distributed transaction)이 됩니다:
- 라이브러리 저장소에서 변경 사항을 적용하고 새 버전을 게시합니다.
- 의존성을 업데이트하기 위해 각 소비 저장소에서 PR(Pull Request)을 엽니다.
- 모든 소비 저장소가 올바른 순서로 머지(merge)되도록 보장합니다.
- 일부 서비스는 이전 버전을 사용하고 다른 서비스는 새 버전을 사용하는 간극을 처리합니다.
- 단계 중 하나라도 실패할 경우 롤백(rollback)을 조율합니다.
이 과정은 사람이 관리할 때조차 충분히 취약합니다. 현재 AI 코딩 에이전트는 여러 저장소에 걸친 변경 사항을 하나의 논리적 트랜잭션으로 오케스트레이션(orchestrating)하기 위한 표준화된 도구가 부족합니다. 에이전트에게는 작업할 수 있는 하나의 그래프(graph)가 있거나, 혹은 아예 없거나 둘 중 하나입니다.
모노레포(Monorepo)는 에이전트에게 그 하나의 그래프(graph)를 제공합니다. AI가 모노레포의 역사적 비용을 잠식하다. 모노레포에 대한 표준적인 반대 의견은 항상 운영상의 마찰(operational friction)에 관한 것이었습니다. 즉, 저장소(repo)가 너무 커서 클론(clone)하기 어렵고, 빌드(build)가 너무 느리며, 탐색(navigation)이 너무 어렵고, 온보딩(onboarding)에 너무 오래 걸린다는 점이었습니다. AI 코딩 에이전트(AI coding agents)는 이러한 문제들을 하나씩 해결해 나가고 있습니다.
| 과거의 반대 이유 | 현재 상태 |
|---|---|
| "코드베이스(codebase)가 너무 커서 탐색하기 어렵다" | AI 코딩 에이전트는 수백만 줄의 코드베이스를 검색하고 추론합니다 — Cursor는 전체 워크스페이스(workspace)를 인덱싱(index)하며, Sourcegraph Cody는 전체 코드베이스에 걸쳐 의미론적 검색(semantic search)을 구축합니다 |
| "저장소 전반에 걸친 리팩터링(refactor)은 위험하다" | AI 코딩 에이전트는 전체 그래프 인지(graph awareness)와 테스트 검증을 통해 리팩터링을 실행합니다 |
| "의존성 그래프(dependency graph)가 너무 복잡하다" | AI 코딩 에이전트는 의존성 그래프를 자동으로 매핑(map)합니다 |
| "빌드 설정(build configuration)이 부담스럽다" | AI 코딩 에이전트는 빌드 파일(build files)을 생성하고 유지 관리합니다 (Gazelle과 같은 도구는 이미 Bazel을 위한 규칙 생성(rule generation)을 수행하고 있으며, AI는 이를 더욱 확장합니다) |
| "신입 엔지니어의 온보딩에 몇 주가 걸린다" | AI 코딩 에이전트는 저장소 구조를 설명하고, 코드 경로를 추적하며, 요구에 따라 아키텍처(architecture) 질문에 답변합니다 |
인프라 측면에서도 발전을 이루었습니다. Git sparse-checkout과 Scalar(원래 Microsoft가 Windows 저장소를 위해 개발한 VFS for Git)는 작업 세트(working set)를 필요한 파일로만 제한합니다. Bazel 또는 유사한 시스템을 통한 원격 빌드 실행(Remote build execution)은 로컬 머신의 사양(specs)이 덜 중요해짐을 의미합니다. Nx 및 Turborepo와 같은 그래프 인지형 CI 시스템은 변경된 부분만 다시 빌드하고 재테스트합니다.
한때 멀티레포(multi-repo)를 "더 단순한 선택"으로 정당화했던 운영 비용은 줄어들고 있습니다. 반면, AI 코딩 에이전트가 개발 워크플로(workflow)에서 차지하는 비중이 커짐에 따라 멀티레포의 컨텍스트 비용(context costs)은 증가하고 있습니다.
도구 체인(Toolchains)은 단일 워크스페이스를 가정합니다. 현재 세대의 AI 코딩 도구들이 어떻게 구축되었는지 살펴보십시오. Cursor 및 GitHub Copilot과 같은 IDE 통합형 에이전트들은 컨텍스트를 위해 열려 있는 워크스페이스를 인덱싱합니다. Claude Code 및 Aider와 같은 CLI 기반 에이전트들은 단일 저장소 디렉토리 내에서 작동합니다.
Sourcegraph Cody와 같은 코드 인텔리전스 (Code intelligence) 플랫폼은 저장소 간의 간극을 메울 수 있지만, 이를 위해서는 대부분의 팀이 생략하는 명시적인 멀티레포 (Multi-repo) 설정이 필요합니다. 이러한 도구들의 기본 설정은 다음과 같습니다: 저장소를 열고, 인덱싱(Indexing)한 뒤, 이를 하나의 단위로 추론(Reasoning)하는 것입니다. 멀티레포는 저장소 경계를 가로질러 그래프를 분할하며, 각 도구는 커스텀 브릿징(Custom bridging, 대부분의 팀이 구축하지 않음)이 필요하거나 시스템의 부분적인 뷰(Partial view)로 작동해야 합니다. 인기를 얻는 도구들은 단일 워크스페이스 (Single-workspace) 설정을 가정하는 경향이 있는데, 이는 최소한의 설정으로 최상의 결과를 낼 수 있는 환경이기 때문입니다.
에이전트 워크플로우 (Agentic workflows)에는 트랜잭션 경계 (Transactional boundaries)가 필요합니다. AI 코딩 에이전트가 자율적으로 다단계 계획을 실행하는 에이전트 코딩 (Agentic coding)은 다음과 같은 일관된 루프를 따릅니다: 코드베이스 분석, 일련의 조정된 변경 사항 적용, 영향을 받는 테스트 업데이트, CI 검증, 그리고 커밋 (Commit). 이 루프는 단일 트랜잭션 경계를 가정합니다. 에이전트는 변경에 포함된 모든 파일에 대한 쓰기 권한, 동일한 커밋 내에서 의존성 항목을 업데이트할 수 있는 능력, 그리고 전체 변경 세트를 검증하는 단일 CI 실행이 필요합니다. 모노레포 (Monorepo)는 이를 자연스럽게 제공합니다. 하나의 저장소, 하나의 커밋 경계, 하나의 CI 파이프라인 (CI pipeline)을 갖습니다. 반면 멀티레포는 분산 트랜잭션 (Distributed transaction)을 강제합니다. 변경 사항이 여러 저장소에 걸쳐 있으며, 각 저장소는 고유한 커밋 히스토리, CI 파이프라인, 머지 (Merge) 프로세스를 가집니다. 분산 트랜잭션은 목적에 맞게 설계된 조정 인프라가 있더라도 올바르게 구현하기 어렵습니다. 오늘날 AI 코딩 에이전트에는 그러한 인프라가 없으며, 이를 억지로 덧붙이는 것은 모노레포가 완전히 피할 수 있는 복잡성을 추가하는 일입니다.
솔직히 말해 반론은
확장성(Scaling)에 대한 반론은 도구(Tooling)에 대한 투자 문제이지, 내재적인 아키텍처의 한계가 아닙니다. "팀에는 격리(Isolation)가 필요하다"라는 주장은 타당합니다. 하지만 격리가 반드시 저장소(Repository) 경계로만 이루어져야 하는 것은 아닙니다. CODEOWNERS 파일, 경로 기반 코드 소유권(Path-based code ownership), 보호된 디렉토리 정책(Protected directory policies), 그리고 빌드 그래프 강제(Build-graph enforcement) 등을 통해 모노레포(Monorepo) 내에서도 충분히 격리를 제공할 수 있습니다. 핵심은 별도 저장소를 통한 격리의 이점이 컨텍스트 비용(Context cost)보다 큰가 하는 점입니다. 대부분의 내부 팀에게는 그렇지 않습니다. "멀티레포(Multi-repo)가 독립적인 릴리스에 더 유리하다"라는 주장도 있습니다. 현재로서는 그렇습니다. 하지만 AI 지원 릴리스 도구들이 그 격차를 줄이고 있습니다. 자동화된 버전 전파(Automated version propagation), 의존성 업데이트 PR(Dependency-update PRs), 호환성 검증(Compatibility verification), 그리고 시맨틱 릴리스 파이프라인(Semantic release pipelines)은 모두 모노레포 릴리스의 조정 오버헤드(Coordination overhead)를 줄여줍니다. 이 반론은 유효하지만 점차 힘을 잃고 있습니다.
멀티레포가 여전히 승리하는 경우
멀티레포는 다음과 같은 특정 상황에서는 여전히 올바른 선택입니다:
- 법적 또는 컴플라이언스(Compliance) 분리: 규정에 따라 서로 다른 사업 부문이나 관할 구역에 대해 별도의 코드베이스가 필요한 경우
- 오픈소스(Open-source) 경계 관리: 공개용 오픈소스(OSS) 프로젝트가 자체적인 기여 워크플로우와 라이선스를 가져야 하는 경우
- 벤더(Vendor) 또는 제3자 경계: 구성 요소가 자체적인 릴리스 주기를 가진 외부 당사자에 의해 소유된 경우
- 보안 격리 명령: 규제상의 이유로 저장소 수준에서 액세스 제어(Access controls)를 강제해야 하는 경우
- 근본적으로 상이한 기술 스택(Tech stacks): 프로젝트 간에 의존성, 인터페이스, 팀 중복이 전혀 없는 경우
이것들은 최적화 선호도의 문제가 아니라 구조적인 제약 사항입니다. 이러한 상황에 직면했다면, AI 도구와 상관없이 멀티레포가 실용적인 선택입니다.
다음 프로젝트를 위한 시사점
새로운 플랫폼을 시작하거나 기존 서비스를 통합하려 한다면, 기본값으로 모노레포를 선택하십시오. 코드베이스가 커질수록 AI 지원 개발을 위한 컨텍스트의 이점은 복리로 쌓이게 됩니다.
동일한 저장소(repo)에 있는 모든 서비스, 라이브러리, 스키마(schema)는 AI 코딩 에이전트(AI coding agents)가 더 나은 코드를 생성하고, 더 많은 버그를 잡아내며, 더 큰 규모의 리팩터링(refactor)을 수행하는 데 사용할 수 있는 또 다른 컨텍스트(context) 조각이 됩니다. 서비스와 공유 라이브러리를 같은 위치에 배치(Co-locate)하십시오. 공유 스키마, 타입 정의(type definitions), API 계약(API contracts)을 중앙 집중화하십시오. 테스트를 구현부(implementations) 옆에 두십시오. 그래프 인식 빌드 시스템(graph-aware build system, 예: Bazel, Nx, Turborepo)을 조기에 도입하십시오. AI 코딩 도구를 위해 저장소 전역 인덱싱(repository-wide indexing)을 활성화하십시오. 엔지니어만이 저장소 구조의 유일한 소비자였을 때는 모노레포(monorepo) 대 멀티레포(multi-repo) 논쟁이 진정으로 균형 잡혀 있었습니다. 이제 AI 코딩 에이전트가 두 번째 소비자로 등장했으며, 이들은 서로 다른 속성, 즉 전체 코드베이스 컨텍스트(full-codebase context), 원자적 멀티 패키지 변경(atomic multi-package changes), 그리고 연결된 의존성 그래프(connected dependency graph)를 위해 최적화합니다. 이러한 속성을 제공하는 저장소 모델은 모노레포입니다. 남은 의문은 멀티레포 오케스트레이션(multi-repo orchestration) 도구가 얼마나 빨리 따라잡을 것인지, 그리고 컨텍스트의 격차를 줄일 수 있을지 여부입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기