Skip to content

모노레포의 특성과 구조

모노레포의 루트 프로젝트 역할, 워크스페이스 구성, 외부/내부 의존성 관리 방식, 그리고 빌드 시스템 도구가 필요한 이유를 구조적으로 이해한다.

학습 목표

  1. 모노레포에서 루트 프로젝트가 수행하는 역할을 이해한다.
  2. 워크스페이스의 개념과 패키지 매니저가 제공하는 기능을 파악한다.
  3. 외부 의존성과 내부 의존성의 차이를 구분하고 관리 방식을 이해한다.
  4. 빌드 시스템 도구(Nx, Turborepo 등)가 필요한 이유를 설명할 수 있다.
  5. 모듈 패키징과 배포의 기본 흐름을 파악한다.

본문

1. 모노레포의 전체 구조

모노레포는 크게 루트 프로젝트와 그 아래의 여러 워크스페이스로 구성된다. 각 워크스페이스는 독립적인 패키지로, 앱이 될 수도 있고 라이브러리가 될 수도 있다.


2. 루트 프로젝트의 역할

모노레포의 루트 프로젝트는 앱이나 라이브러리가 아니다. 루트는 전체 모노레포를 관리하는 관제탑 역할을 수행한다.

루트가 담당하는 핵심 역할

역할설명대표 파일
워크스페이스 등록어떤 디렉터리가 워크스페이스인지 선언package.jsonworkspaces 필드
관리 도구 설치모노레포 운영에 필요한 도구를 devDependencies로 관리package.jsondevDependencies
공통 설정ESLint, Prettier, TypeScript 등 전체 프로젝트에 적용할 공통 설정 보관tsconfig.base.json, .eslintrc.js
스크립트 정의전체 워크스페이스에 대한 빌드, 테스트, 린트 명령 통합package.jsonscripts
CI/CD 진입점파이프라인이 시작되는 기준점.github/workflows/, turbo.json

루트의 package.json 예시 구조:

json
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "devDependencies": {
    "turbo": "^2.0.0",
    "typescript": "^5.4.0",
    "eslint": "^9.0.0"
  },
  "scripts": {
    "build": "turbo run build",
    "test": "turbo run test",
    "lint": "turbo run lint"
  }
}

중요한 점은 루트의 private: true 설정이다. 루트 자체는 npm에 퍼블리시되지 않으며, 오직 내부 워크스페이스를 조율하는 역할만 한다.


3. 워크스페이스: 패키지 매니저가 제공하는 모노레포 기능

워크스페이스는 하나의 레포지토리 안에서 여러 독립적인 패키지를 관리할 수 있게 해주는 패키지 매니저의 기능이다. npm, yarn, pnpm 모두 워크스페이스를 지원하며, 설정 방식에 약간의 차이가 있다.

패키지 매니저워크스페이스 설정 위치설정 방식
npmpackage.json"workspaces": ["packages/*"]
yarnpackage.json"workspaces": ["packages/*"]
pnpmpnpm-workspace.yamlpackages: ["packages/*"]

각 워크스페이스는 자체 package.json을 가지며, 여기에 패키지 이름, 버전, 의존성 정보를 정의한다. 패키지 매니저는 이 정보를 분석하여 **내부 패키지 간 연결(심볼릭 링크)**과 외부 의존성 설치를 처리한다.


4. 외부 의존성 vs 내부 의존성

모노레포에서는 두 종류의 의존성을 구분하여 관리해야 한다.

외부 의존성 (External Dependencies)

npm 레지스트리에서 설치하는 서드파티 라이브러리다.

  • react, typescript, lodash 같은 범용 패키지
  • 각 워크스페이스의 package.json에 선언하면 패키지 매니저가 node_modules에 설치
  • 루트에 설치하면 전체 워크스페이스에서 접근 가능 (도구 의존성에 주로 사용)

내부 의존성 (Internal Dependencies)

같은 모노레포 안에 있는 다른 워크스페이스를 참조하는 것이다.

  • package.json에 내부 패키지 이름을 명시하면, 패키지 매니저가 npm 레지스트리가 아닌 로컬 워크스페이스로 연결
  • 별도의 npm 퍼블리시 없이 즉시 사용 가능
json
{
  "name": "@my-org/web-app",
  "dependencies": {
    "react": "^18.3.0",
    "@my-org/ui-kit": "workspace:*",
    "@my-org/utils": "workspace:*"
  }
}

위 예시에서 react는 외부 의존성이고, @my-org/ui-kit@my-org/utils는 내부 의존성이다.


5. 빌드 시스템 도구가 필요한 이유

패키지 매니저의 워크스페이스 기능만으로도 모노레포를 운영할 수 있다. 하지만 프로젝트가 커지면 다음 세 가지 영역에서 추가 도구의 도움이 필수적이 된다.

5-1. 속도 (Performance)

모노레포의 각 패키지는 TypeScript 컴파일, 번들링 등 빌드 과정이 필요하다. 앱을 실행하기 전에 의존하는 모든 패키지를 빌드해야 하는데, 변경점이 없는 패키지까지 매번 다시 빌드하면 개발 생산성이 급격히 떨어진다.

빌드 시스템 도구가 제공하는 속도 관련 핵심 기능:

기능설명지원 도구
로컬 캐싱한번 빌드된 결과를 캐시에 저장하고, 변경이 없으면 캐시된 결과를 재사용Lerna, Nx, Rush, Turborepo
분산 캐싱팀원 간 캐시를 공유하여 CI와 로컬 환경 모두에서 빌드 시간 단축Nx Cloud, Turborepo Remote Cache
태스크 오케스트레이션패키지 간 의존 순서를 분석하여 순차/병렬 실행을 자동으로 결정Lerna, Nx, Rush, Turborepo
변경 감지코드 변경이 발생한 패키지와 영향받는 패키지만 선별하여 빌드Lerna, Nx, Rush, Turborepo

태스크 오케스트레이션의 핵심 원리: A를 빌드해야 B를 빌드할 수 있고, C는 독립적이라면 A와 C를 병렬로 실행한 뒤 A 완료 후 B를 실행한다.

5-2. 분석 (Analysis)

기능설명지원 도구
워크스페이스 감지package.json 등을 자동 분석하여 프로젝트 그래프 생성Lerna, Nx, Rush, Turborepo
의존성 그래프 시각화패키지 간 관계를 시각적으로 확인Nx (인터랙티브), Turborepo (HTML)

5-3. 관리 (Management)

기능설명지원 도구
코드 공유npm 패키지 형태로 소스 코드 조각을 공유Lerna, Nx, Turborepo
스케폴딩새 워크스페이스를 템플릿 기반으로 빠르게 생성Nx (내장), 기타 (외부 생성기)
일관된 도구 경험언어나 프레임워크가 달라도 동일한 명령어로 빌드/테스트Nx
의존성 규칙특정 패키지 간 의존을 제한하거나 허용하는 규칙 정의Nx

6. 모듈 패키징과 배포

모노레포의 각 워크스페이스는 npm 패키지와 동일한 형태로 제작된다. 다만 모두 npm에 퍼블리시할 필요는 없으며, 내부에서만 사용하는 패키지는 퍼블리시 없이 심볼릭 링크로 연결하여 사용한다.

모듈이 외부로 노출되는 과정

  1. 소스 코드 작성: TypeScript 등으로 작성
  2. 빌드: 트랜스파일(TS -> JS), 번들링, 타입 선언 파일 생성
  3. 패키지 정보 정의: package.jsonmain, module, types, exports 필드로 진입점 명시
  4. 내부 사용: 다른 워크스페이스에서 패키지 이름으로 import
  5. 외부 배포 (선택): 필요 시 npm 레지스트리에 퍼블리시

중요한 점은 소스 코드를 그대로 노출하는 것이 아니라, 빌드 과정을 거쳐 가공된 결과물을 노출한다는 것이다. 이 빌드 과정에서 트랜스파일러(TypeScript, Babel)와 번들러(Rollup, esbuild, Vite)가 사용된다.


7. 대표적인 모노레포 빌드 도구 비교

도구특징캐싱오케스트레이션시각화스케폴딩
Lerna가장 오래된 도구. Nx와 통합됨OOXX
Nx가장 풍부한 기능. 플러그인 생태계OOO (인터랙티브)O (내장)
RushMicrosoft 오픈소스. 대규모에 강점OOXX
TurborepoVercel 소속. 간결한 설정, 빠른 시작OOO (HTML)X

도구 선택 시 고려할 점:

  • 프로젝트 규모: 소규모면 Turborepo의 간결함이 장점, 대규모면 Nx나 Rush가 적합
  • 학습 곡선: Turborepo가 가장 낮고, Nx와 Rush는 기능이 많은 만큼 학습이 필요
  • 팀 요구사항: 시각화와 스케폴딩이 중요하면 Nx, 빠른 빌드가 최우선이면 Turborepo

핵심 정리

  1. 루트 프로젝트는 앱이나 라이브러리가 아니라, 워크스페이스를 등록하고 관리 도구를 설치하며 공통 설정을 제공하는 관제탑이다.
  2. 워크스페이스는 패키지 매니저(npm/yarn/pnpm)가 제공하는 기능으로, 하나의 레포에서 여러 독립 패키지를 관리할 수 있게 해준다.
  3. 외부 의존성은 npm 레지스트리에서 설치하고, 내부 의존성은 심볼릭 링크로 모노레포 내부 패키지를 연결한다.
  4. 패키지 매니저만으로는 캐싱, 태스크 오케스트레이션, 변경 감지를 처리하기 어려우므로 빌드 시스템 도구(Nx, Turborepo 등)가 필요하다.
  5. 각 워크스페이스의 모듈은 npm 패키지 형태로 제작되며, 빌드(트랜스파일 + 번들링) 과정을 거쳐 노출된다.

다음 단계

모노레포의 구조와 빌드 도구의 필요성을 이해했으므로, 다음으로 워크스페이스의 구체적인 동작 원리(심볼릭 링크, 호이스팅, 패키지 간 의존성 해석)를 살펴본다.

다음: 03-워크스페이스-관리.md | 패키지 매니저로 이동: ../04-패키지-매니저/01-프론트엔드-프로젝트-구조.md