이 문서의 과거 버전 (r1)을 보고 있습니다. 수정일: 2026.02.23 13:32
모노레포는 여러 개의 독립적인 프로젝트나 패키지를 하나의 단일 저장소에서 관리하는 소프트웨어 개발 전략이다. 이 방식은 특히 대규모 프로젝트나 여러 패키지로 구성된 라이브러리 생태계를 관리할 때 유용하다. 전통적으로 각 프로젝트를 별도의 저장소로 관리하는 멀티레포 방식과 대비되는 개념이다.
이 접근법의 핵심 목적은 코드베이스의 통합된 관리를 통해 효율성을 높이는 데 있다. 여러 패키지 간의 코드 공유와 재사용이 용이해지며, 의존성 관리를 중앙에서 일관되게 처리할 수 있다. 또한 빌드 자동화, 테스트 자동화, 릴리스 프로세스와 같은 DevOps 워크플로우를 통합하여 구축하기에 적합한 구조를 제공한다.
모노레포를 구현하고 관리하기 위해서는 Lerna, Nx, Turborepo와 같은 전용 도구가 널리 사용된다. 또한 Yarn이나 npm의 워크스페이스 기능을 활용하여 패키지 간 링크와 의존성을 관리하는 경우도 많다. 이 방식은 프론트엔드 개발과 백엔드 개발을 아우르는 풀스택 프로젝트나, 마이크로서비스 아키텍처 환경에서도 적용될 수 있다.
모노레포는 여러 개의 독립적인 프로젝트나 패키지를 하나의 단일 저장소에서 관리하는 소프트웨어 개발 전략이다. 이는 소프트웨어 공학에서 코드베이스를 구성하는 방법론 중 하나로, 특히 대규모 프로젝트나 여러 패키지 간에 긴밀한 의존성이 존재하는 경우에 널리 채택된다.
전통적인 멀티레포 방식과 달리, 모노레포는 모든 관련 코드가 중앙 집중화되어 있다. 이는 프론트엔드 개발과 백엔드 개발 모듈, 공유 라이브러리, 도구 스크립트 등이 모두 동일한 버전 관리 시스템 하에 존재함을 의미한다. 주요 목적은 이러한 구성 요소들 사이의 코드 공유와 재사용성을 극대화하고, 통합된 빌드 및 테스트 프로세스를 구축하며, 일관된 개발 워크플로우를 유지하는 데 있다.
이 전략은 마이크로서비스 아키텍처를 구현하거나, 복잡한 웹 애플리케이션을 구성하는 여러 라이브러리를 개발할 때, 또는 DevOps 파이프라인을 단순화해야 할 때 효과적이다. 모노레포를 성공적으로 운영하기 위해서는 Lerna, Nx, Turborepo 또는 Yarn Workspaces와 같은 전용 관리 도구의 활용이 필수적이다.
모노레포를 효과적으로 운영하기 위해서는 단일 저장소 내의 여러 패키지를 관리하고, 패키지 간 의존성을 해결하며, 효율적인 빌드와 배포 워크플로우를 구축할 수 있는 전용 관리 도구가 필요하다. 이러한 도구들은 패키지 링크 설정, 스크립트 실행 최적화, 변경된 패키지만 선택적 빌드 등의 기능을 제공하여 모노레포의 복잡성을 관리한다.
대표적인 모노레포 관리 도구로는 Lerna, Nx, Turborepo, 그리고 Yarn Workspaces나 npm Workspaces와 같은 패키지 매니저의 워크스페이스 기능이 있다. Lerna는 초기부터 널리 사용된 도구로, 패키지 간 링크 생성과 버전 관리, 변경된 패키지에 대한 스크립트 실행을 지원한다. Nx는 Lerna보다 진화된 형태로, 강력한 코드 생성기, 의존성 그래프 시각화, 분산 캐싱을 통한 빌드 속도 향상 등 고급 기능을 제공한다. Vercel이 개발한 Turborepo는 증분 빌드와 원격 캐싱에 특화되어 대규모 모노레포에서 빌드 성능을 극대화하는 데 강점을 보인다.
한편, Yarn과 npm 자체에 내장된 워크스페이스 기능은 패키지 매니저와의 긴밀한 통합을 바탕으로 의존성 관리를 단순화한다. 이들은 별도의 도구 설치 없이도 모노레포의 기본 구조를 구성할 수 있게 해주며, 다른 고급 관리 도구들과 함께 사용되기도 한다. 개발 팀은 프로젝트의 규모, 필요한 기능, 그리고 프론트엔드 개발 또는 백엔드 개발 스택에 맞춰 이러한 도구들을 선택하거나 조합하여 사용한다.
모노레포의 패키지 구조는 단일 저장소 내에서 여러 프로젝트를 체계적으로 구성하는 방식을 의미한다. 일반적으로 저장소 루트에는 전체 저장소를 관리하는 설정 파일과 도구별 구성 파일이 위치하며, 개별 패키지나 애플리케이션은 packages/ 또는 apps/와 같은 디렉토리 하위에 모듈별로 분리되어 배치된다. 이때 각 패키지는 독립적인 package.json 파일을 가지며, 자체적인 의존성, 빌드 스크립트, 테스트 설정을 관리할 수 있다. 이러한 구조는 마이크로서비스 아키텍처나 라이브러리 개발, 또는 프론트엔드와 백엔드 애플리케이션을 함께 관리하는 풀스택 프로젝트에 적합하다.
패키지 간의 관계는 저장소 루트의 설정을 통해 관리된다. 예를 들어, Yarn Workspaces나 npm Workspaces를 사용하면 루트의 package.json에 workspaces 필드를 정의하여 하위 패키지들의 위치를 지정하고, 패키지 간 의존성을 효율적으로 링크할 수 있다. Lerna나 Nx, Turborepo 같은 전용 도구들은 이러한 구조 위에서 증분 빌드, 태스크 오케스트레이션, 버전 관리 등의 고급 기능을 제공한다. 이로 인해 공통 유틸리티 라이브러리나 디자인 시스템 컴포넌트를 별도의 패키지로 분리하여 여러 애플리케이션에서 참조하는 방식이 용이해진다.
표준적인 패키지 구조는 다음과 같은 형태를 띈다. 이 구조는 프로젝트의 규모와 복잡도에 따라 유연하게 변형될 수 있다.
디렉토리/파일 | 설명 |
|---|---|
| 저장소의 최상위 경로. 전역 설정 파일 위치. |
| 워크스페이스 정의 및 루트 레벨 의존성, 스크립트 관리. |
| 해당 모노레포 관리 도구의 구성 파일. |
| 공유 라이브러리나 독립 패키지가 위치하는 일반적인 디렉토리. |
| 개별 패키지의 루트 디렉토리. |
| 해당 패키지의 메타데이터, 의존성, 스크립트 정의. |
| 실행 가능한 애플리케이션(웹앱, API 서버 등)이 위치하는 디렉토리. |
| 루트 및 패키지별 의존성 모듈이 설치되는 위치 (도구에 따라 중앙화). |
| TypeScript, ESLint, Prettier, Jest 등의 전역 구성 파일. |
모노레포에서 의존성 관리는 여러 패키지 간의 상호 의존 관계를 효율적으로 관리하는 핵심 요소이다. 단일 저장소 내에 여러 패키지가 공존하기 때문에, 패키지 간의 의존성을 중앙에서 통제하고 최적화할 수 있다.
의존성 관리는 크게 내부 의존성과 외부 의존성으로 구분된다. 내부 의존성은 같은 모노레포 내에 있는 다른 패키지를 참조하는 것을 말한다. 대부분의 모노레포 관리 도구는 이러한 내부 의존성을 심볼릭 링크나 특정 워크스페이스 해결 방식을 통해 로컬 파일 시스템에서 직접 참조하도록 설정한다. 이로 인해 외부 NPM 레지스트리에 배포하지 않고도 실시간으로 변경 사항을 반영하여 개발할 수 있으며, 버전 충돌을 방지할 수 있다. 외부 의존성은 서드파티 라이브러리를 의미하며, 이러한 의존성은 중앙 집중식으로 관리하거나 각 패키지별로 분산 관리할 수 있다.
효율적인 의존성 관리를 위해 Yarn Workspaces나 npm Workspaces 같은 기능을 사용하면 루트 디렉터리에서 한 번에 모든 패키지의 외부 의존성을 설치할 수 있어 디스크 공간을 절약하고 설치 시간을 단축한다. 또한 Lerna나 Turborepo 같은 도구는 의존성 그래프를 분석하여 변경된 패키지와 그에 의존하는 패키지만 선택적으로 빌드하고 테스트하는 기능을 제공한다. 이를 통해 불필요한 작업을 줄이고 CI/CD 파이프라인의 실행 속도를 크게 향상시킬 수 있다.
모노레포의 가장 큰 장점 중 하나는 여러 패키지 간의 코드 공유와 재사용성을 극대화할 수 있다는 점이다. 전통적인 멀티레포 방식에서는 서로 다른 저장소에 분리된 패키지들 간에 코드를 재사용하려면 별도의 라이브러리를 배포하거나 복제하는 번거로운 과정이 필요했다. 반면 모노레포에서는 모든 패키지가 동일한 저장소 내에 위치하기 때문에, 공통으로 사용되는 유틸리티 함수, 컴포넌트 라이브러리, 설정 파일, 타입 정의 등을 하나의 패키지로 구성한 후 다른 패키지들이 직접적인 내부 의존성으로 참조할 수 있다.
이러한 구조는 개발 속도를 크게 향상시킨다. 공통 모듈을 수정하면 이를 사용하는 모든 패키지에서 즉시 변경 사항을 반영하여 테스트할 수 있으며, 버전 불일치 문제를 사전에 방지할 수 있다. 특히 프론트엔드와 백엔드가 동일한 비즈니스 로직이나 데이터 모델을 공유해야 하는 풀스택 애플리케이션 개발, 혹은 마이크로서비스 아키텍처에서 여러 서비스가 공통 라이브러리를 사용할 때 매우 효과적이다. 결과적으로 코드 중복을 최소화하고, DRY 원칙을 준수하며, 전체 시스템의 일관성을 유지하는 데 기여한다.
모노레포를 채택하면 여러 패키지가 동일한 저장소 안에 존재하기 때문에, 코드베이스 전반에 걸쳐 일관된 개발 환경과 표준을 유지하기가 용이해진다. 모든 패키지가 동일한 코드 린팅 규칙, 코드 포맷팅 도구, 테스트 프레임워크 버전, 빌드 도구 설정을 공유하도록 강제할 수 있다. 이는 팀 내에서 서로 다른 프로젝트 간에 발생할 수 있는 설정 차이나 도구 버전 불일치 문제를 근본적으로 방지한다.
또한, 의존성 관리 측면에서도 일관성이 크게 향상된다. 모노레포에서는 루트 디렉토리에서 주요 라이브러리나 프레임워크의 버전을 중앙에서 통합 관리할 수 있다. 예를 들어, React나 TypeScript와 같은 공통 의존성을 모든 패키지가 동일한 버전으로 사용하도록 lock 파일을 공유하거나 호이스팅할 수 있다. 이로 인해 버전 충돌이나 의존성 지옥 문제가 줄어들고, 보안 패치나 주요 업데이트를 전체 코드베이스에 신속하고 동기화된 상태로 적용할 수 있다.
개발 워크플로우와 CI/CD 파이프라인 역시 표준화되고 일관성을 갖출 수 있다. 모든 패키지에 대해 통합된 빌드 스크립트, 테스트 실행 절차, 코드 검사 도구를 구성할 수 있어, 개발자들이 새로운 패키지를 추가하거나 기존 프로젝트를 수정할 때마다 반복적으로 설정할 필요가 없다. 이는 신규 팀원의 온보딩 시간을 단축시키고, 프로젝트 간 컨텍스트 전환 비용을 낮추는 효과를 가져온다.
모노레포는 여러 패키지가 하나의 저장소에 통합되어 있기 때문에, 코드베이스 전반에 걸친 대규모 변경 작업을 수행하기에 유리하다. 여러 개의 독립된 저장소(멀티레포)를 사용하는 경우, 각 저장소마다 브랜치를 만들고 변경 사항을 순차적으로 적용하며 버전 호환성을 맞추는 복잡한 과정이 필요하다. 반면 모노레포에서는 모든 관련 코드가 한곳에 모여 있으므로, 한 번의 커밋으로 여러 패키지에 걸친 리팩토링을 원자적으로 수행할 수 있다. 이는 API 변경이나 공통 라이브러리의 인터페이스 수정과 같은 광범위한 작업에서 특히 큰 장점으로 작용한다.
대규모 리팩토링 시 발생할 수 있는 버전 간 불일치 문제도 모노레포 환경에서는 크게 완화된다. 모든 패키지가 항상 최신 상태의 코드를 참조하기 때문에, 특정 패키지가 오래된 버전의 의존성을 사용하는 상황을 방지할 수 있다. 이는 의존성 지옥 문제를 피하고, 변경 사항이 즉시 모든 관련 모듈에 반영되어 테스트될 수 있게 한다. 결과적으로 리팩토링 후의 통합 테스트와 버그 탐지가 더 빠르고 효율적으로 이루어진다.
또한, 모노레포를 지원하는 Lerna나 Nx와 같은 도구들은 변경된 패키지만 선택적으로 빌드하거나 테스트하는 기능을 제공한다. 이는 리팩토링 과정에서 수정된 부분에 대한 피드백 루프를 짧게 유지시켜 주며, 개발 생산성을 높이는 데 기여한다.
모노레포는 여러 패키지가 단일 저장소에 존재함으로써 통합된 개발 도구 체인과 일관된 워크플로우를 구축할 수 있게 한다. 모든 패키지가 동일한 루트 디렉토리 아래에 위치하기 때문에, 린팅, 코드 포맷팅, 테스트 실행, 빌드 프로세스 등을 위한 공통 설정을 한 번만 정의하고 모든 프로젝트에 일괄 적용할 수 있다. 이는 DevOps 관점에서 CI/CD 파이프라인을 단순화하고, 팀 전체가 동일한 도구와 규칙을 사용하도록 강제하여 협업 효율성을 높인다.
예를 들어, ESLint나 Prettier와 같은 정적 분석 도구의 구성 파일을 루트 레벨에 하나만 두고, 모든 하위 패키지에서 이를 상속받아 사용할 수 있다. 마찬가지로 Jest나 Cypress를 이용한 테스트 스크립트, Webpack이나 Vite를 활용한 빌드 설정도 중앙에서 관리될 수 있다. 이렇게 통합된 툴링은 개발 환경 설정의 복잡성을 줄이고, 새로운 팀원의 온보딩 시간을 단축시키는 장점이 있다.
또한, 버전 관리와 릴리스 프로세스도 단순화된다. Lerna나 Turborepo 같은 모노레포 관리 도구는 변경된 패키지만 선택적으로 빌드하거나, 패키지 간의 의존성을 고려해 최적화된 태스크 실행 순서를 제공한다. 여러 패키지에 걸친 대규모 변경사항을 하나의 커밋 히스토리로 관리할 수 있어, 어떤 변경이 다른 패키지에 어떤 영향을 미쳤는지 추적하기 용이하다. 이는 코드베이스의 전반적인 건강 상태를 모니터링하고, 표준화된 방식으로 배포를 수행하는 데 기여한다.
모노레포의 가장 직접적인 단점 중 하나는 저장소 크기의 증가이다. 단일 저장소에 모든 프로젝트의 코드, 의존성, 설정 파일, 문서, 그리고 각 패키지의 히스토리가 누적되기 때문에, 저장소의 전체 용량이 빠르게 커질 수 있다. 이는 특히 오랜 기간 유지되거나 많은 수의 패키지를 포함하는 프로젝트에서 두드러진다.
이로 인해 개발자의 로컬 환경에서 저장소를 처음 클론(clone)하거나 최신 변경 사항을 가져오는(fetch/pull) 시간이 길어지며, 네트워크 대역폭과 디스크 공간을 더 많이 소모하게 된다. 또한, 대부분의 버전 관리 시스템은 전체 히스토리를 다운로드하기 때문에, 특정 패키지만 필요로 하는 개발자에게도 불필요한 오버헤드가 발생할 수 있다.
이 문제를 완화하기 위해 Git의 얕은 복제(shallow clone)나 부분 클론(partial clone)과 같은 기능을 사용하거나, 모노레포 관리 도구에서 제공하는 필터링 기능을 활용하여 특정 패키지만 선택적으로 작업하는 방법이 고려된다. 그러나 이러한 방법들은 워크플로우를 복잡하게 만들거나, 모든 기능을 완전히 사용하는 데 제약이 따를 수 있다. 결국 저장소 크기 관리는 모노레포를 운영하는 팀이 지속적으로 모니터링하고 정리해야 하는 과제가 된다.
모노레포의 가장 큰 단점 중 하나는 빌드 및 테스트 시간이 증가할 수 있다는 점이다. 단일 저장소에 모든 패키지의 소스 코드가 집중되기 때문에, 변경 사항이 발생했을 때 영향을 받는 범위를 정확히 파악하고 최소한의 작업만 수행하는 것이 중요해진다. 예를 들어, A 패키지의 코드를 수정했을 때, A 패키지에 의존하는 B, C 패키지까지 함께 빌드하고 테스트해야 할 수 있다. 이러한 전파 효과는 프로젝트 규모가 커질수록 더욱 두드러지며, 전체 빌드 파이프라인의 실행 시간을 크게 늘릴 수 있다.
이 문제를 완화하기 위해 대부분의 모노레포 관리 도구는 증분 빌드와 캐싱 기능을 제공한다. Nx와 Turborepo는 이 분야에서 특히 강력한 성능을 보여주며, 변경된 패키지만 빌드하고 이전 빌드 결과를 캐싱하여 불필요한 작업을 제거한다. 또한, 패키지 간 의존성 그래프를 분석하여 작업의 실행 순서를 최적화하고, 병렬 처리를 통해 전체 실행 시간을 단축시킨다. 이러한 고급 기능 없이는 모노레포 환경에서의 개발 생산성이 현저히 떨어질 수 있다.
테스트 시간 증가 문제도 유사한 맥락에서 발생한다. 모든 패키지의 테스트를 매번 전체 실행하는 것은 비효율적이므로, 변경된 코드와 직접적 관련이 있는 테스트 스위트만 선별적으로 실행하는 전략이 필요하다. 이를 위해서는 테스트 러너와 모노레포 도구 간의 긴밀한 통합이 필수적이다. 일부 도구는 코드 커버리지 정보나 의존성 분석을 바탕으로 영향받는 테스트를 자동으로 식별하는 기능을 제공하기도 한다.
결론적으로, 모노레포에서 빌드 및 테스트 성능을 관리하는 것은 단순한 기술적 문제를 넘어 중요한 운영 과제이다. 적절한 도구 선택과 구성, 그리고 지속적인 모니터링과 튜닝을 통해 개발자 경험과 피드백 루프의 속도를 유지하는 것이 성공적인 모노레포 운영의 핵심 요소이다.
모노레포는 여러 프로젝트나 패키지를 하나의 저장소에서 관리하기 때문에, 개별 패키지나 디렉터리 단위로 세분화된 접근 권한을 설정하는 것이 기술적으로 어렵거나 불가능한 경우가 많다. 대부분의 버전 관리 시스템은 저장소 전체를 단위로 권한을 제어하는 방식을 기본으로 하기 때문이다.
이로 인해, 외부 협력자나 특정 팀에게는 특정 패키지만 접근 권한을 부여하고 나머지 코드는 숨기고 싶은 경우가 있지만, 모노레포 환경에서는 이를 구현하기가 복잡해진다. 저장소를 분리하는 멀티레포 방식에 비해 권한 관리의 유연성이 떨어진다는 점이 단점으로 지적된다. 이러한 제약은 특히 기업 내에서 보안이 중요한 프로젝트나, 오픈 소스와 폐쇄 소스 코드가 혼재된 환경에서 문제가 될 수 있다.
접근 권한 세분화의 어려움을 해결하기 위한 방법으로는, 저장소를 물리적으로 분리하지 않고도 특정 경로에 대한 읽기 권한을 제어할 수 있는 고급 버전 관리 시스템 도구를 사용하거나, CI/CD 파이프라인 단계에서 접근을 필터링하는 방법 등이 고려된다. 그러나 이러한 방법들은 추가적인 설정과 유지 보수 비용을 발생시키며, 모노레포의 단순함과 통합성이라는 본래 장점을 일부 훼손할 수 있다.
Lerna는 자바스크립트 생태계에서 널리 사용되는 모노레포 관리 도구이다. 주로 Node.js 기반의 여러 패키지를 단일 저장소에서 효율적으로 관리하기 위해 설계되었다. Lerna는 패키지 간의 의존성 연결을 최적화하고, 여러 패키지에 걸친 변경 사항을 한 번에 릴리스하는 버전 관리 및 배포 작업을 자동화하는 데 중점을 둔다.
Lerna의 주요 기능은 패키지 간 링크 생성, 변경된 패키지만 선택적으로 빌드하는 증분 빌드 지원, 그리고 통합된 버전 관리 및 배포이다. 특히 'Fixed'와 'Independent'라는 두 가지 버전 관리 모드를 제공한다. Fixed 모드는 저장소 내 모든 패키지의 버전을 하나로 통일하여 관리하며, Independent 모드는 각 패키지의 버전을 독립적으로 관리할 수 있게 해준다.
이 도구는 주로 npm이나 Yarn과 같은 패키지 매니저와 함께 사용되며, 특히 Yarn Workspaces나 npm Workspaces와 결합하여 의존성 관리를 최적화하는 구성이 일반적이다. Lerna는 복잡한 프론트엔드 애플리케이션이나 여러 상호 연결된 라이브러리로 구성된 대규모 프로젝트에서 코드 공유와 배포 프로세스 표준화를 용이하게 한다.
그러나 Lerna는 주로 작업 오케스트레이션과 버전 관리에 특화되어 있어, 고급 캐싱, 분산 실행, 클라우드 기반 협업과 같은 더 포괄적인 기능을 필요로 하는 프로젝트에서는 Nx나 Turborepo와 같은 다른 모노레포 도구로 전환하는 경우도 있다.
Nx는 모노레포를 위한 강력한 빌드 시스템이자 개발 도구 플랫폼이다. 단순히 여러 패키지를 하나의 저장소에 모아두는 것을 넘어, 프로젝트 그래프를 기반으로 한 지능적인 빌드 자동화, 코드 생성, 그리고 의존성 관리를 제공하는 것이 핵심 특징이다. Nx는 Angular 개발팀에서 시작된 도구로, 현재는 React, Node.js 등 다양한 기술 스택을 지원하며 대규모 엔터프라이즈급 애플리케이션 개발에 널리 사용된다.
Nx의 핵심 기능은 프로젝트 간의 관계를 시각화하고 분석하는 프로젝트 그래프이다. 이 그래프를 통해 변경된 코드가 어떤 다른 프로젝트에 영향을 미치는지 정확히 파악할 수 있어, 증분 빌드와 영향 받은 테스트만을 실행하는 최적화된 워크플로우를 가능하게 한다. 또한, 코드 생성기와 플러그인 생태계를 통해 애플리케이션, 라이브러리, 구성 파일 등을 자동으로 생성하고, 린팅, 테스트, 빌드에 대한 일관된 규칙을 강제함으로써 프로젝트의 유지보수성을 높인다.
주요 구성 요소로는 Nx CLI, Nx Cloud, 그리고 다양한 기술 스택을 위한 플러그인(예: @nrwl/react, @nrwl/node)이 있다. Nx는 Yarn Workspaces나 npm Workspaces와 같은 패키지 링크 기술 위에서 동작하며, 모노레포 관리 도구인 Lerna나 Turborepo와 비교될 때, 더 포괄적인 개발 경험과 강력한 코드 생성 도구를 제공한다는 점에서 차별화된다.
Turborepo는 Vercel이 개발한 고성능 모노레포 빌드 시스템이다. 기존 모노레포 관리 도구들이 패키지 링크와 의존성 해결에 중점을 둔다면, Turborepo는 빌드, 테스트, 린트와 같은 태스크 실행의 속도와 효율성 극대화에 특화되어 있다. 이를 위해 증분 빌드, 원격 캐싱, 병렬 실행 등의 기술을 활용하여 불필요한 작업을 제거하고, CI/CD 파이프라인을 포함한 전체 개발 워크플로우의 속도를 획기적으로 높인다.
Turborepo는 Yarn Workspaces, npm Workspaces, pnpm Workspaces와 같은 패키지 매니저의 워크스페이스 기능 위에서 동작하며, 이들이 관리하는 패키지 간 의존성 그래프를 기반으로 태스크를 최적화한다. 사용자는 turbo.json 설정 파일을 통해 프로젝트 루트와 각 패키지의 빌드 스크립트를 정의하고, 태스크 간 의존 관계를 선언할 수 있다. Turborepo는 이 의존성 그래프를 분석하여 변경된 패키지만 빌드하고, 이전에 성공한 빌드 결과를 로컬 또는 원격 캐시에서 재사용하며, 서로 의존 관계가 없는 태스크들을 병렬로 실행한다.
이 도구의 주요 강점은 대규모 모노레포에서 반복적인 작업 시간을 크게 단축시키는 데 있다. 예를 들어, 수백 개의 패키지로 구성된 저장소에서 단일 파일을 수정했을 때, 관련 없는 모든 패키지를 다시 빌드하는 대신 해당 변경 사항의 영향을 받는 패키지만 선택적으로 빌드할 수 있다. 또한 클라우드 기반의 원격 캐시를 통해 동일한 커밋에 대한 빌드 결과를 팀원들 또는 CI 서버 간 공유함으로써, 동일한 작업을 반복 수행하는 것을 방지한다.
Turborepo는 프론트엔드 생태계, 특히 Next.js와의 긴밀한 통합으로 주목받으며 빠르게 성장했다. 그러나 그 사용 범위는 프론트엔드에 국한되지 않으며, 백엔드 서비스, 라이브러리, 도구 등 다양한 유형의 패키지로 구성된 모든 자바스크립트 또는 타입스크립트 기반 모노레포에서 활용될 수 있다.
Yarn Workspaces는 Yarn 패키지 매니저에 내장된 기능으로, 단일 최상위 package.json 파일과 node_modules 폴더를 사용하여 여러 패키지를 관리한다. Yarn이 의존성을 최상위에서 통합적으로 설치하고, 서로 다른 패키지 간의 심볼릭 링크를 자동으로 생성해 로컬 패키지를 참조할 수 있게 한다. 이는 의존성 관리를 단순화하고 디스크 공간을 절약하는 데 도움이 된다.
npm Workspaces는 npm 버전 7부터 도입된 유사한 기능이다. npm install 명령어를 통해 워크스페이스 내 모든 패키지의 의존성을 한 번에 설치할 수 있으며, --workspace 플래그를 사용해 특정 워크스페이스에만 명령을 실행할 수 있다. 기본적인 개념은 Yarn Workspaces와 유사하지만, npm의 네이티브 기능으로 통합되어 있다는 점이 특징이다.
두 방식 모두 모노레포의 핵심 문제인 의존성 관리와 로컬 패키지 링킹을 해결한다. 프로젝트 루트의 package.json 파일에 "workspaces" 필드를 정의하여 포함할 패키지들의 경로를 배열로 지정하는 방식으로 구성한다. 이를 통해 각 하위 패키지는 서로를 로컬 파일 시스템 경로가 아닌 패키지 이름으로 참조할 수 있게 되어 개발이 편리해진다.
그러나 빌드 순서 제어, 캐싱, 원격 실행과 같은 고급 기능은 이들 워크스페이스 기능만으로는 부족한 경우가 많다. 따라서 대규모 모노레포에서는 Lerna, Nx, Turborepo와 같은 전문 도구를 Yarn Workspaces나 npm Workspaces와 함께 사용하여 더 강력한 프로젝트 관리, 태스크 오케스트레이션, 성능 최적화를 구현하는 것이 일반적이다.
모노레포는 대규모 소프트웨어 조직과 오픈소스 프로젝트에서 널리 채택되어 운영 효율성과 개발 생산성을 높이는 데 기여한다. 특히 여러 패키지가 긴밀하게 연결되어 있고 자주 변경이 발생하는 환경에서 그 가치가 두드러진다.
주요 기술 기업들의 적용 사례로는 메타의 페이스북 코드베이스, 구글의 단일 저장소, 마이크로소프트의 다양한 제품군 개발 등이 있다. 이들은 수천 명의 개발자가 수십만 개의 패키지를 단일 저장소에서 관리하며, 통합된 빌드 시스템과 코드 검색 도구를 활용해 대규모 협업을 가능하게 한다. 오픈소스 진영에서는 React, Babel, 제스트 등의 프로젝트가 Lerna나 Yarn Workspaces와 같은 도구를 사용해 라이브러리 코어, 플러그인, 문서화 사이트 등을 하나의 저장소에서 관리하는 대표적인 예시이다.
프론트엔드 개발 분야에서는 마이크로 프론트엔드 아키텍처를 구현할 때 모노레포가 자주 활용된다. 여러 독립적인 기능 팀이 각자의 마이크로서비스에 해당하는 프론트엔드 모듈을 개발하되, 동일한 저장소 내에서 공통 디자인 시스템 컴포넌트, 빌드 도구 설정, 테스트 환경을 공유할 수 있다. 이는 애플리케이션의 일관된 사용자 경험을 유지하면서도 팀의 자율성을 보장하는 데 유리하다.
또한 풀스택 애플리케이션 개발에서도 백엔드 API 서버, 프론트엔드 웹 애플리케이션, 공유 타입스크립트 타입 정의, 데이터베이스 마이그레이션 스크립트 등을 하나의 모노레포에 포함시켜 종단 간 기능 개발과 테스트를 단순화하는 사례가 증가하고 있다. Nx나 Turborepo와 같은 현대적 도구들은 이러한 복잡한 워크스페이스 내에서 캐싱과 증분 빌드를 통해 개발자 경험을 크게 향상시킨다.
멀티레포는 각 프로젝트나 패키지가 독립된 저장소를 가지는 전통적인 관리 방식이다. 이 방식에서는 각 저장소가 자체적인 버전 관리 시스템, CI/CD 파이프라인, 의존성 관리를 갖추게 된다. 반면 모노레포는 여러 프로젝트를 하나의 거대한 저장소에서 관리하며, 이는 마이크로서비스 아키텍처를 채택한 조직이나 라이브러리를 다수 개발하는 회사에서 선호되는 경향이 있다.
두 방식의 가장 큰 차이는 의존성 관리와 코드 공유에 있다. 멀티레포에서는 패키지 간 의존성을 업데이트하거나 공통 코드를 변경할 때 각 저장소를 개별적으로 수정하고 버전을 조정해야 하므로 작업이 번거롭고 동기화 문제가 발생할 수 있다. 모노레포에서는 모든 패키지가 동일한 저장소 내에 존재하므로, 공유 라이브러리를 한 번 수정하면 이를 사용하는 모든 패키지에 즉시 반영하여 테스트할 수 있어 리팩토링과 대규모 변경이 용이하다.
툴링과 협업 프로세스 측면에서도 차이가 나타난다. 멀티레포는 각 팀이 자신의 저장소에 대한 완전한 자율성을 가지며, 독립적인 배포 주기를 가질 수 있어 팀 간 결합도를 낮출 수 있다. 모노레포는 통합된 빌드 도구, 린터, 테스트 환경을 구축하기 쉬워 개발 환경의 일관성을 유지하는 데 유리하지만, 저장소 접근 권한을 세분화하기 어렵고, 하나의 변경 사항이 전체 저장소의 빌드 및 테스트 시간에 영향을 줄 수 있다.
적합한 방식을 선택하는 것은 프로젝트 규모, 팀 구조, 배포 전략에 따라 달라진다. 작은 규모의 독립 프로젝트나 외부에 공개된 오픈 소스 라이브러리는 멀티레포가 적합할 수 있다. 반면, 긴밀하게 연관된 다수의 패키지를 빠르게 반복 개발하고, 코드 재사용과 통합된 표준을 중시하는 대규모 조직에서는 모노레포의 장점이 부각된다.