$ yh.log
[스터디] npm deep dive - 8장 모노레포로 서비스와 라이브러리 모두 관리하기

[스터디] npm deep dive - 8장 모노레포로 서비스와 라이브러리 모두 관리하기

npm모노레포멀티레포터보레포패키지 관리

작성자 : 오예환 | 작성일 : 2026-03-24 | 수정일 : 2026-03-24 | 조회수 :

기존에는 각 프로젝트를 별도의 저장소로 관리하는 방식이 일반적이었으나, 관리 복잡성이 증가함에 따라 더 나은 해결책을 찾기 위한 필요성이 대두되었다. 이에 따라 모노레포가 등장하였고, 여러 패키지를 하나의 저장소에서 통합 관리하는 방식이 주목받게 되었다. 오픈소스 생태계에서도 모노레포를 지원하는 다양한 도구들이 등장하고 있다.

8.1 모노레포와 터보레포

여러 개의 패키지를 개발하고 유지보수하는 메인테이너이거나, 한 조직에서 다수의 프로젝트와 라이브러리를 함께 관리해야 하는 상황이라면 다음과 같은 고민이 생긴다.

고민설명
일관된 환경 구성개발 환경 구축을 매번 반복적으로 수행하지 않을 수 있을까?
배포 전략의 일관성모든 패키지에 동일한 배포 전략을 적용할 수 있을까?
공통 모듈 관리여러 패키지에서 공유하는 모듈을 효율적으로 관리할 수 있을까?
협업 환경 개선팀 간 협업을 더 원활하게 할 수 있을까?
의존성 관리패키지 간 의존성을 체계적으로 관리할 수 있을까?
테스트와 품질 관리전체 시스템의 품질을 일관되게 유지할 수 있을까?
코드 재사용성코드 중복을 줄이고 재사용성을 높일 수 있을까?

이러한 고민들을 해결하기 위해 모노레포라는 개념이 등장했다.

8.1.1 모노레포란?

여러 패키지를 한데 모아 단 하나의 저장소에서 관리할 때, 이 모든 코드베이스가 저장된 저장소를 **모노레포(Monorepo)**라고 한다.

멀티레포 vs 모노레포 비교

멀티레포 (Multi-repo)

특징

  • 각 패키지별로 저장소를 생성해서 패키지와 저장소가 1:1로 매핑된다.
  • 각 패키지가 저장소라는 물리적인 단위로 분리돼 있으므로 설치 방법이나 구성이 상이할 수 있다.
  • 패키지들의 저장소가 분리되어 어떤 의존 관계도 없이 독립적으로 관리할 수 있다. 이는 곧 변경에 각 구성원이 독립적으로 신속하게 대응할 수 있는 개발 문화를 조성하기도 한다.

장점

  • 저장소마다 빌드를 병렬로 진행할 수 있기 때문에 CI/CD 파이프라인을 수행할 컴퓨팅 파워가 충분하다면 빌드 속도가 빠르다.
  • 의존성의 버전을 독립적으로 관리할 수 있다.
  • 저장소별로 소유자를 지정해 패키지들을 자율적으로 관리하기가 쉽다. 이는 보안 및 권한 관리 측면에서 특히 유용하다.
  • 한 패키지에서 발생한 문제가 다른 패키지에 쉽게 전파되지 않는다.
  • 팀이 여러 개의 프로젝트를 병렬로 처리할 때 서로 다른 저장소에서 독립적으로 개발을 진행하므로 개발 속도가 빠르다.

결론: 멀티레포는 저장소별로 코드가 분리돼 있어 각 코드 소유자가 환경을 유연하게 구성하고 독립적으로 유지보수할 수 있다. 특히 애플리케이션과 같은 서비스 개발에 유용하게 적용될 수 있는 관리 방식이다.

단점

  • 중복된 코드가 많아지거나 매번 동일한 환경 구성을 반복해야 한다. 깃허브 템플릿 저장소를 통해 어느 정도 문제를 완화할 수 있지만 완벽한 해결책은 아니다.
  • 프로젝트를 유지보수할 때 이슈나 변경 로그가 분산되어 관리 포인트가 늘어날 수 있다.
  • 패키지 간 의존성 관리에 어려움이 있다. 동일한 모듈을 사용하는 여러 패키지가 각기 다른 버전을 사용할 경우 의존성 충돌이 발생할 수 있다.
  • 의존 관계가 복잡한 패키지들을 순서대로 배포하려면 추가적인 관리와 노력이 필요하다.
  • 공통 의존성들을 관리하기 어렵다.

모노레포 (Monorepo)

특징

  • 모든 코드가 하나의 저장소에 위치해 있어 설치나 구성과 같은 공통 항목이 단일화돼 있다.
  • 패키지 간 의존 관계가 하나의 저장소에서 이뤄진다.
  • 모든 코드가 하나의 저장소에 위치하므로 한 패키지의 수정이 다른 패키지들에 영향을 미치기 쉽다. 즉, 하나의 변경으로 인해 다른 패키지들의 동작이 실패하면 수정 사항을 모든 패키지에 반영해야 한다. 이는 패키지들의 소유자와 협력해야 하는 구조로, 모든 구성원이 변경 사항을 인지하고 있어야 해서 개발자들이 협력하는 개발 문화를 조성한다.

장점

  • 프로젝트 간 의존성을 파악하고 관리하기 쉽다.
  • 단일 저장소이기 때문에 이슈 추적이 단순해지고, 모든 패키지의 변경 로그 또한 함께 관리된다.
  • 패키지 간 의존성을 설정하기 쉬워 공유하기가 쉽다.
  • 전체 패키지에 영향이 갈 수 있는 수정을 단 한 번의 변경만으로 해결할 수 있다.
  • 멀티레포에서는 공통으로 포함된 의존성을 관리하기가 어려웠지만, 모노레포는 이 문제를 쉽게 해결할 수 있다. 많은 모노레포 도구들이 이러한 문제를 자동으로 해결하는 기능을 제공하므로 개발자는 더 적은 노력으로 시스템의 일관성을 유지할 수 있다.

단점

  • CI/CD 속도 저하 가능성: 모든 패키지가 단일 저장소에 위치하기 때문에 빌드 속도가 느릴 수 있다. 단, 이는 순차 실행 때문이 아니라 전체 규모가 크기 때문이다. 모노레포에서도 병렬 실행과 캐싱 같은 최적화 기법으로 속도를 개선할 수 있으며, 각 패키지별로 CI/CD 파이프라인을 효율적으로 관리해야 한다.
  • 저장소 관리 부담: 코드베이스 규모가 커질수록 Git 저장소 관리가 느려질 수 있다. 방대한 코드베이스는 로컬 하드 드라이브의 공간 활용도를 떨어뜨리고 I/O 성능에 영향을 준다.
  • 변경 영향 파악의 어려움: 오픈소스의 경우 기여자가 A 패키지에만 사소한 수정을 가했더라도, 이 수정이 A 패키지에 의존하는 다른 패키지에 부수 효과를 끼칠 수 있어 영향 범위를 파악하기 어렵다.
  • 접근 권한 관리의 어려움: 여러 팀이 작업하는 경우 각 팀마다 다른 접근 권한을 부여하기가 어려울 수 있다.
  • 도구 설정의 복잡성: 빌드, 테스트, 린팅 등 여러 도구의 설정이 멀티레포보다 복잡해질 수 있다. 각 패키지마다 서로 다른 설정이 필요한 경우 일관성 유지가 어려워 이런 경우에는 멀티레포가 더 나은 선택일 수 있다.

사례를 통한 모노레포 특징

React: 코드 재사용성과 협업의 최적화

특징설명
코드 재사용성과 모듈화react, react-dom, react-reconciler 같은 여러 패키지가 독립적으로 존재하며, 하나의 코드베이스에 모여 있어 패키지 간 의존성을 명확하게 정의하고 관리할 수 있다. 코드 중복을 줄이고 공통 로직을 쉽게 재사용할 수 있다.
일관된 빌드 및 테스트 환경여러 패키지가 서로 의존성을 가지고 있지만 각 패키지를 독립적으로 빌드하거나 테스트할 수 있다. 모노레포 환경에서는 빌드와 테스트를 일관된 방식으로 설정하고 관리할 수 있어 효율적인 협업이 가능하다.
일관된 배포 관리여러 패키지를 동시에 배포할 수 있으며, 패키지 간 버전 호환성을 쉽게 유지할 수 있다.

Babel: 플러그인과 프리셋의 독립적인 관리

  • 유기적인 관리와 독립성
  • 일관된 프로젝트 관리

Next.js: 모듈화된 개발과 빠른 배포 주기

  • 모듈화된 개발
  • 빠른 배포 주기

언제 모노레포를 선택해야 할까?

고려 사항설명
패키지 간 버전 일관성각 패키지 간의 의존성 버전을 일관되게 유지해야 한다면, 모노레포는 모든 패키지가 같은 코드베이스 내에 있으므로 버전 충돌을 최소화할 수 있다.
의존성 관리 및 영향 범위 파악멀티레포에서 패키지나 모듈 간 변경 사항이 다른 패키지에 미치는 영향을 파악하기 어려웠다면 모노레포가 도움이 된다.
일관된 프로젝트 환경모든 패키지에 동일한 개발 환경과 설정을 적용해야 하는 경우
협업 필요성모노레포는 모든 코드를 하나의 저장소에서 관리하여 구성원이 변경한 코드를 추적하기 용이하며, 팀원 간의 코드 공유와 협업을 더욱 긴밀하고 원활하게 만든다.

다만 여러 가지 이유로 당장 확인하기 힘들 수 있으므로, 목표로 하는 프로젝트의 성격, 개발 환경 및 담당할 개발 조직의 문화를 항상 최우선으로 고려해야 한다.

핵심: 모노레포의 도입 여부는 구성원들의 생산성이 향상되는가에 중점을 두고 고려해야 한다.

추가적인 외부 요소

요소고려할 점
코드베이스의 예상 규모규모가 클수록 모노레포 도구의 최적화 기능이 중요해진다
관련 구성원의 인원팀 규모에 따른 협업 방식 고려
개발할 패키지 개수패키지가 많을수록 관리 도구의 필요성 증가
패키지 간 결합도강하게 결합된 패키지들은 모노레포에 적합
사용하는 프로그래밍 언어 개수다양한 언어를 사용할 경우 도구 지원 확인 필요
사용하는 배포 도구기존 배포 파이프라인과의 호환성
팀의 개발 문화협업 중심인지 독립적 개발 중심인지
학습 비용새로운 도구나 기술 스택을 팀 내 구성원들이 얼마나 배워야 하는가
구성원들의 동의모노레포 전환에 대한 팀의 합의 필요

8.1.2 npm 워크스페이스

8.1.3 모노레포를 구성하는 도구, 터보레포

**터보레포(Turborepo)**는 Vercel이 관리하는 고성능 빌드 시스템으로, 모노레포를 확장 및 관리하는 데 많은 도움을 준다. 원래는 자레드 팔머(Jared Palmer)가 만든 오픈소스 프로젝트였고, 2021년에 Vercel이 인수하며 Vercel 생태계에서 중요한 도구로 자리 잡았다.

터보레포의 핵심 기능

1. 작업 캐싱

터보레포의 핵심 기능 중 하나는 작업 캐싱이다. 모노레포의 단점 중 하나로 멀티레포와 비교해서 상대적으로 전체적인 CI/CD 속도가 느려질 수 있다고 설명했다. 이는 모노레포상에 패키지가 계속 추가되고 순차적으로 실행되는 경우 더욱 느려질 가능성이 있다.

터보레포는 이러한 모노레포의 한계를 캐싱 시스템으로 극복한다. 이전에 수행한 빌드, 테스트, 린트와 같은 작업의 결과를 저장해 이후 실행 시 동일한 작업을 반복하지 않고 캐시된 결과를 재사용할 수 있다. 이를 통해 불필요한 재작업을 줄이고 빌드 시간을 크게 줄여 모노레포 환경에서의 작업 속도를 극대화할 수 있다.

캐싱 특징설명
명령어 단위 캐싱turbo run 명령어를 사용해서 실행되는 작업에 대해 캐싱을 수행한다. 작업의 입력과 출력을 기반으로 캐시가 이뤄지며, 동일한 입력이 있을 때는 캐시된 결과를 재사용한다.
다양한 작업 지원빌드뿐만 아니라 린트, 테스트, 타입 체크 등 모든 종류의 작업에 대해 캐싱을 지원한다. 터미널 명령어 실행 결과뿐만 아니라 빌드 결과물도 캐싱 범위에 포함된다.
스마트 캐시 관리작업의 의존성과 변경 사항을 기반으로 캐시를 효율적으로 관리한다. 한 모듈에서 발생한 변경 사항이 다른 모듈에 영향을 미치는 경우에만 재빌드를 수행하고, 나머지 모듈들은 캐싱된 결과를 재사용한다.
원격 캐시기본적으로 터보레포는 로컬에서 작업 결과를 캐싱한다. 팀 단위 작업에서 캐시를 재사용하고 싶은 경우 원격 캐시를 사용할 수 있다. Vercel 또는 자체 서버를 통해 관리할 수 있으며, 팀원들이 동일한 작업을 할 때 각자의 로컬에서 반복 작업을 하지 않고 원격에 저장된 캐시를 사용할 수 있다.

2. 해시 기반 캐싱 시스템

터보레포가 세부적으로 캐싱을 제공할 수 있는 이유는 빌드 시점의 타임스탬프가 아닌 파일 변경점을 기반으로 해싱하기 때문이다. 캐싱 시스템이 작업의 입력값을 기반으로 해시값을 생성하고, 이 해시값으로 캐시를 저장하고 조회한다. 해시값은 특정 작업의 입력값이 동일한지 여부를 판단하는 기준이 되어, 입력값이 같으면 캐시를 사용하고 입력값이 달라지면 새로 작업을 실행한다.

터보레포 작업의 입력값은 크게 두 가지로 나눌 수 있다.

파일 시스템 입력값

작업을 실행할 때 모노레포상의 모든 패키지의 특정 파일 또는 디렉터리를 추적해서 그 파일의 변경점을 기준으로 해싱한다.

  • 패키지 구성 변경점
  • 패키지의 락 파일, 패키지 단위의 package.json
  • 패키지 소스 코드

환경변수 및 명령어

작업을 실행하는 데 사용하는 환경변수나 명령어 자체도 입력값에 포함된다. 예를 들어 NODE_ENV=productionNODE_ENV=development는 서로 다른 환경변수를 입력값으로 사용하므로 각 작업 결과가 따로 캐싱된다. 따라서 같은 명령어라도 환경변수가 달라지면 새로운 작업으로 간주되어 캐시된 결과가 재사용되지 않는다.

  • turbo.json
  • 최상위 경로의 락 파일
  • turbo.jsonglobalDependencies에 정의된 파일 내용
  • turbo.jsonglobalEnv에 정의된 환경변수
  • turbo CLI의 실행 옵션
  • 작업의 매개변수

터보레포는 모노레포상의 모든 파일 변경점을 기본적으로 해싱해서, 이 값이 변경되면 해시값이 달라지므로 작업을 다시 수행해 새로 캐싱한다.

3. 캐싱하지 않아도 될 때

모든 작업에 캐싱이 필요한 것은 아니다. 다음과 같은 경우에는 캐싱을 적용하지 않는 것이 더 효율적일 수 있다.

  • 충분히 빠른 속도로 완료되는 작업
  • 결과물의 크기가 매우 큰 작업
  • 자체적으로 캐싱하는 스크립트

4. 작업 그래프

**작업 그래프(Task Graph)**는 터보레포가 프로젝트의 의존성과 작업 간의 상호 관계를 분석해서 효율적인 작업 순서를 결정하는 도구다. 각 작업 간의 의존성을 시각적으로 표현해 프로젝트 내에서 작업이 어떻게 연결되고, 어떤 작업이 먼저 실행돼야 하며, 어떤 작업이 병렬로 실행될 수 있는지를 알려준다.

이 그래프는 **DAG(Directed Acyclic Graph, 방향성 비순환 그래프)**라는 자료구조로 만들어져 있어, 각 작업을 노드로, 작업 간의 의존성은 엣지로 표현한다.