내가 회사에서 마주친 거대한 모노레포 — AI 시대엔 득일까, 실일까?
입사하고 나서 처음으로 회사 레포지토리를 클론받았던 날을 아직도 기억한다.
git clone 명령어를 입력하고 나서, 이렇게 많은 파일이 쭉쭉 내려받아지는 건 처음 봤다. 다운로드가 끝나고 VSCode로 프로젝트를 열었을 때 눈앞에 펼쳐진 폴더 구조는, 내가 생각했던 것보다 훨씬 복잡했다.
‘이게 다 뭐지? 에반데?’
들여다보니 회사 프로젝트는 모노레포(monorepo) 구조였다. OCR 관련 AI 스크립트, Python+Django 기반 백엔드, React+TypeScript 기반 프론트엔드가 모두 한 레포지토리에 몰려있는 대규모 프로젝트였던 거다. 그 규모가… 생각보다 겁나게 컸다.
모노레포가 뭔데? (그리고 멀티레포랑은 뭐가 다른데?)
모노레포 자체는 알고 있었다. 개념 정도는 입사 전에도 들어봤으니까. 근데 이렇게 큰 규모의 모노레포는 처음이었다. 일단 모르는 분들을 위해 비유로 간단히 짚고 넘어가자면 이렇다.
멀티레포는 여러 집에 나눠서 사는 것, 모노레포는 대형 아파트 한 동에 다 같이 사는 것이다.
멀티레포(polyrepo)는 서비스나 팀마다 별도의 레포지토리를 갖는 방식이다. A팀은 /frontend 레포, B팀은 /backend 레포, C팀은 /design-system 레포 이런 식으로. 독립적으로 관리되고, 각자의 배포 사이클을 갖는다.
반면 모노레포는 이 모든 걸 하나의 레포지토리 안에 때려 넣는 방식이다. 폴더 구조로 서비스를 구분하고, 전체 코드베이스가 한 곳에 모여있다.
글로벌 빅테크들이 실제로 이 방식을 쓴다. 구글의 모노레포는 무려 80테라바이트 규모로 알려져 있고, 하루에 수만 건의 커밋이 일어난다고 한다. 규모가 너무 커서 일반 Git으로는 감당이 안 되니 아예 Piper라는 자체 버전 관리 시스템을 만들었을 정도다. 메타(페이스북)도 Mercurial 기반의 모노레포를 쓰고, 이를 위한 자체 빌드 툴 Buck도 만들었다.
반면 아마존과 넷플릭스는 수백 개의 개별 레포지토리를 운영하는 멀티레포 방식을 선택했다. 정답이 없다는 방증이기도 하다.
일단 실행부터 해봤더니…
“오케이, 이제 npm install 하고 dev 서버 켜볼게.”
…
내 맥북은 자신을 좀 살려달라고 하는 것 같았다.
모노레포의 현실적인 단점은 꽤 직빵으로 다가왔다:
느린 초기 설정과 실행: 하나의 레포에 여러 프로젝트가 담겨있으니, 처음 세팅하거나 의존성을 설치할 때 드는 품이 만만치 않다. 내가 실제로 건드리지 않을 서비스의 패키지까지 전부 설치되는 느낌.
메모리를 생각보다 많이 잡아먹음: 여러 개발 서버를 동시에 돌리거나, 전체 빌드를 돌리면 컴퓨터가 버거워하는 게 느껴진다. 특히 IDE가 전체 프로젝트를 인덱싱할 때 더 그렇다.
처음 파악하기 어렵다: 어디서부터 시작해야 하지? 이 폴더는 뭐지? 어떤 서비스가 어떤 서비스를 참조하고 있지? 주니어 입장에서는 지도 없이 미로에 들어온 느낌이 든다.
근데 CI가 진짜 느려 터졌다(?) — PR 올릴 때마다 10분씩
개발 환경만의 문제가 아니었다. PR을 올릴 때마다 마주치는 CI가 더 심각했다.
우리 회사는 GitHub Actions로 PR마다 Django 테스트와 mypy 타입 검사를 돌린다. 알아보니 이미 변경된 영역(백엔드/프론트엔드)만 골라서 테스트하는 path filtering이나 캐싱 같은 최적화 기법들이 적용되어 있었다. 그럼에도 백엔드와 프론트엔드 코드가 함께 변경된 경우엔 어쩔 수 없이 10분 이상 걸렸다.
이게 모노레포의 숙명 같은 면이 있다. 여러 서비스가 한 레포에 엮여 있으니, 연관된 변경이 생기면 검증해야 할 범위도 함께 커진다. 완전히 해결할 수 없는 문제라기보다는, 모노레포를 선택하는 순간 어느 정도 감수해야 하는 트레이드오프에 가깝다.
빌드가 느린 건 어제오늘 일이 아니다 — 업계의 해결 방식
이게 우리 회사만의 문제가 아니라는 걸 알고 나서 좀 위안이 됐다. (다 같이 느리면 괜찮은 거 아닌가요)
모노레포를 진지하게 운용하는 회사들은 빌드 속도 문제를 진즉에 마주쳤고, 각자의 방식으로 해결해왔다.
LINE(현 LY Corp)은 Turborepo를 도입하면서 빌드 시간을 약 14초에서 0.3초로 줄였다. “한 번 계산한 건 다시 계산하지 않는다”는 캐싱 원칙이 핵심이다. 변경된 패키지만 골라서 빌드하고, 결과를 캐시에 저장해두는 방식이다.
구글과 메타는 아예 자체 빌드 도구를 만들었다. 구글의 Bazel, 메타의 Buck이 그것이다. 오픈소스 도구로는 감당이 안 되는 규모가 되자 결국 도구 자체를 직접 만든 거다. (80TB짜리 레포를 일반 빌드 툴로 돌리면 어떻게 될지는 상상에 맡긴다)
결국 모노레포를 제대로 운용하려면 코드 관리 전략만큼이나 빌드 인프라 전략이 따라와야 한다. 빌드가 느리다는 건 모노레포를 선택하는 순간 어느 정도 감수해야 하는 원죄 같은 거고, 이 원죄를 어떻게 갚느냐가 팀마다 다른 접근법으로 나타난다.
근데 같이 쓰니까 편한 것도 있더라
불평만 늘어놓기엔 억울한 장점도 있었다.
공통 컴포넌트를 진짜 “공통”으로 쓸 수 있다: 디자인 시스템이나 공통 UI 컴포넌트가 한 곳에 있으니, A 서비스에서 고친 버튼이 B 서비스에도 바로 반영된다. 멀티레포였다면 패키지 버전을 맞추고, 배포하고, 업데이트하는 과정이 따로 필요하다. 원자적 커밋(atomic commit)이 가능하다는 게 이런 거다 — 연관된 변경사항을 한 번에 묶어서 반영할 수 있다.
그리고, AI 도구랑 쓸 때 생각보다 편하다.
이게 좀 의외였다. Claude나 Cursor 같은 AI 코딩 도구를 쓸 때, 모노레포는 한 프로젝트 안에서 전체 컨텍스트를 한 번에 잡을 수 있다. “이 API는 어디서 정의돼 있어요?” 물어보면 AI가 같은 레포 안에서 바로 찾아준다. 멀티레포였다면 레포를 왔다갔다 하면서 컨텍스트를 수동으로 끊어붙여야 할 수도 있다.
근데 이게 마냥 좋은 것만은 아니더라. 좀 더 들여다보니 고민이 생겼다.
AI 시대엔 어떻게 봐야 할까? — 구조에 따라 AI를 쓰는 방식이 달라지더라
여기서부터가 사실 내가 가장 고민하는 부분이다.
AI 코딩 도구는 결국 “지금 이 순간 볼 수 있는 것”만 가지고 답을 한다.
AI 도구들이 가진 컨텍스트 윈도우 — 한 번에 처리할 수 있는 정보의 양 — 은 제한되어 있다. 요즘은 128K~1M 토큰까지 늘어났지만, 그렇다고 무한하지는 않다. 대규모 모노레포에서는 코드베이스 전체를 AI에게 한꺼번에 던져줄 수 없다.
이 맥락에서 두 구조를 비교해보면:
모노레포에서 AI를 쓸 때: 서비스 간 참조 관계나 공통 코드가 같은 레포 안에 있으니, AI가 연관된 맥락을 더 잘 파악하는 경향이 있다. 반면 레포가 너무 크면, AI가 “지금 내가 어디 있는지”를 파악하는 데 오히려 더 많은 힌트가 필요해진다.
멀티레포에서 AI를 쓸 때: 레포 하나의 범위가 좁으니 AI가 해당 서비스에만 집중할 수 있고 컨텍스트가 깔끔하다. 대신 서비스 간 연관 작업을 할 때 AI가 다른 레포의 코드를 모른다. 직접 복사붙여넣기를 해주거나 추가 컨텍스트를 수동으로 제공해야 한다.
CLAUDE.md — 모노레포 안의 또 다른 모노레포 문제
우리 회사 모노레포를 보면서 흥미로운 걸 발견했다. 우리가 클로드 부장님께 일을 시킬 때 좀 더 잘 해달라는 바람으로 CLAUDE.md라는 파일을 작성한다. “우리 프로젝트는 이런 구조야, 이 컨벤션 따라줘” — 뭐 그런거 적는 내용들 있잖아..
그런데 이게 딱 하나가 아니었다. 구조가 대략 이런 식이었다:
1
2
3
4
5
6
7
8
9
10
11
our-company-monorepo/
├── CLAUDE.md # 진입점: 전체 개요 + 하위 문서 안내
├── docs/
│ ├── team-conventions.md # 팀 개발 컨벤션 개요
│ ├── server-conventions.md # 서버(Django/Python) 개발 컨벤션
│ ├── frontend-conventions.md # 프론트엔드 개발 컨벤션
│ └── design-system.md # 디자인 시스템 가이드
├── backend/
│ └── ...
└── frontend/
└── ...
팀 개발 컨벤션 개요, 서버 컨벤션, 프론트엔드 컨벤션, 디자인 시스템 가이드… 관심사별로 잘 분리되어 있었다. 설계 의도는 명확하다 — AI에게 “지금 백엔드 작업이면 이 파일 봐, 프론트엔드면 저 파일 봐” 하고 역할을 나눠주는 것.
근데 이걸 보면서 이런 생각이 들었다.
결국 CLAUDE.md를 어떻게 관리할지도, 모노레포 vs 멀티레포의 고민과 똑같은 구조의 문제 아닌가?
만약 이 회사가 멀티레포였다면, AI 컨텍스트 파일도 각 레포에 흩어져 있을 것이다:
1
2
3
4
5
6
7
8
backend-repo/
└── CLAUDE.md # 서버 컨벤션만. 간결하고 집중적
frontend-repo/
└── CLAUDE.md # 프론트엔드 컨벤션만. 마찬가지로 깔끔
design-system-repo/
└── CLAUDE.md # 디자인 시스템 가이드만
이 구조는 AI가 현재 작업하는 레포에만 집중하기 때문에 컨텍스트가 군더더기 없이 깔끔하다. 반면 “이 API가 프론트에서 어떻게 쓰이는지”를 물어보고 싶을 때, AI는 다른 레포의 내용을 모른다. 직접 복사붙여넣기를 해줘야 한다.
모노레포 방식의 우리 회사는? AI가 루트의 CLAUDE.md를 읽고 필요한 하위 문서로 이동하는 구조라서, 한 번의 작업 안에서 서버-프론트 양쪽 컨벤션을 모두 참고할 수 있다. 대신 파일이 많아질수록 AI가 “지금 어떤 문서를 읽어야 하지?”를 파악하는 데 드는 비용도 올라간다.
아직 어느 쪽이 낫다고 단언하기 어렵다. 다만 한 가지는 확실해졌다 — 레포 구조가 모노레포든 멀티레포든, AI와 잘 협업하려면 명시적인 컨텍스트 관리가 필수라는 것. AI가 알아서 다 파악해주는 시대는 아직 오지 않았고, 어떤 구조든 “지금 뭘 하려는지, 프로젝트가 어떻게 생겼는지”를 잘 설명해주는 게 결국 답의 질을 가른다.
아직 답은 모르겠다
솔직히 말하면, 모노레포가 좋다 나쁘다 결론 내릴 자신이 아직 없다.
구글은 80TB짜리 모노레포를 쓰고, 아마존은 수백 개의 개별 레포를 쓴다. 둘 다 잘 되고 있다. 어쩌면 정답은 팀의 크기, 서비스의 성격, 빌드 인프라, 그리고 팀 문화에 따라 달라지는 게 아닐까.
나 같은 주니어 입장에서는 일단 ‘어떤 구조인지 이해하고 쓰는 것’이 먼저인 것 같다. 내가 클론받은 레포가 왜 이렇게 크고, 어떤 의도로 이렇게 설계됐는지를 파악하는 것 — 그게 이 구조를 더 잘 활용하는 첫 걸음이지 않을까.
AI 도구도 마찬가지다. 구조가 모노레포든 멀티레포든, 그 안에서 AI와 잘 협업하는 방법은 결국 “맥락을 잘 전달하는 것”으로 귀결된다. 도구는 도구일 뿐, 어떻게 설명하느냐가 답의 질을 가른다.
뭐, 거창하게 이런 생각을 하면서도 오늘도 개발 서버 켜는 데 시간이 좀 걸렸다. (이건 변명의 여지가 없다 후…)
참고 자료
- Monorepo - Wikipedia
- EP62: Why Does Google Use Monorepo? - ByteByteGo
- Turborepo로 모노레포 개발 경험 향상하기 - LINE Engineering
- Advantages of monorepos - Dan Luu
- Benefits and challenges of monorepo development practices - CircleCI
- CI/CD for Monorepos: Taming the Beast with Smart Strategies - DEV Community
- Journey of Systematically Cut Our Monorepo CI Time in Half - DEV Community

