0-3. 모노레포(Monorepo)

wooseok·2026년 2월 19일

머먹지

목록 보기
3/4
post-thumbnail

😬 이번에는 프로젝트에 앞서서 학습하기로 한 내용 중에 제일 낯설었던 개념인 모노레포(Monorepo)와 이와 관련된 개념들을 학습해봤습니다..!

🤔 모노레포란?

❓ 모노레포 vs 멀티레포(폴리레포)

모노레포가 왜 필요한지 알기 위해 나에게 익숙한 방식인 멀티레포 방식과 어떤 차이점이 있는지 알아보았다.

멀티레포모노레포

사진에서 볼 수 있듯이 멀티레포 방식은 여러 개의 레포지토리를 만들고 필요에 따라 서로를 참조하는 형태다.
이와는 다르게 모노레포는 그것들을 하나의 레포지토리 안에 포함시키는 형태라고 할 수 있다.

👎 멀티레포의 문제점

1. 코드 공유가 어려움

📂 레포A — 웹 서비스 (Next.js)
📂 레포B — 모바일 앱 (React Native)
📂 레포C — 디자인 시스템 (Button, Input 등 공용 컴포넌트)

이런 상황에서 웹과 앱에서 디자인 시스템의 Button 컴포넌트를 사용하려면 디자인 시스템을 배포한 뒤에 웹, 앱에 각각 설치해야함.
진짜 문제는 디자인 시스템에서 수정사항이 발생했을 경우.

  • 재배포하기 전까지 변경사항을 테스트가 어렵다는 문제가 있음. (npm link로 가능은 한 듯..?)
  • 배포를 한 뒤에도 레포A와 레포B에 이를 모두 반영해야 하기 때문에 중복 작업이 발생 ☠️

➡️ 모노레포에서는 Button 컴포넌트 파일 하나만 수정하면 끝

2. 변경 사항 추적이 불편

  • 각 레포의 작업자가 다를 경우 사용하는 버전이 각각 달라 문제가 발생할 수 있음 (버전 불일치 문제)
  • 문제가 발생했을 때 어떤 레포가 또 다른 어떤 레포에 영향을 끼쳤는지 각 레포를 오가며 파악해야 하는 불편함.

➡️ 모노레포에서는 모든 커밋이 한 곳에 있기 때문에 git 히스토리 하나만 보면 파악 가능

3. 중복되는 설정 파일

  • 각 레포마다 ESLint, Prettier 등의 설정을 따로 관리해야 함.
  • 설정 하나를 바꾸려면 레포 수 만큼 수정을 반복 ☠️

❓ 그럼 모노레포는 단점이 없나? 그건 아님 🙅

  • 프로젝트가 커질 수록 빌드 및 테스트 속도가 느려질 수 있음
  • 명령어 딸깍으로 바로 시작할 수 있는 멀티레포와 달리 모노레포는 구조를 직접 잡아야 하기 때문에 초기 설정이 복잡하다고 느낄 수 있음

💡 그럼 모노레포를 사용하면 좋은 경우는 언제?! ➡️ 여러 앱/패키지가 코드를 공유해야 할 때!


🤔 워크스페이스(Workspace)란?

💡 하나의 레포지토리 안에 있는 여러 패키지를 패키지 매니저가 인식하고 연결해주는 기능

// 모노레포 구조 예시

my-monorepo/
├── apps/
│   └── web/            ← Next.js 앱
├── packages/
│   └── ui/             ← 공용 Button 컴포넌트
└── package.json        ← 루트 설정 파일

web 앱에서 ui 패키지의 Button 컴포넌트를 사용하고 싶을 때 워크스페이스를 설정하면 ui 패키지를 마치 배포된 외부 라이브러리처럼 인식하게 해줌.

따라서 다음과 같이 npm에 배포하지 않고, 버전을 맞출 필요도 없이 import 할 수 있음

import { Button } from '@my-org/ui'

❓ 워크스페이스에 pnpm을 사용하는 이유

npm, yarn도 워크스페이스 기능이 있지만 알아보니 많은 사람들이 pnpm을 선호하는 이유가 있었다.

  • 디스크 공간 절약

    • npm은 패키지를 설치할 때 각 프로젝트마다 중복으로 저장
    • 이에 반해 pnpm은 컴퓨터 한 곳에 딱 한 번만 저장하고, 각 프로젝트에서는 그걸 심볼릭 링크(Symbolic Link)로 참조하는 방식

    ➡️ 모노레포에서는 패키지가 많아질수록 중복 설치가 심해지는데, 이 문제점을 pnpm이 해결해주는 거지! 🙌

  • 유령 의존성 차단
    npm은 패키지A가 패키지B를 의존하면, B도 내 코드에서 설치 없이 import 할 수 있음.
    이는 나중에 A가 B를 제거하면 에러가 발생할 위험이 있음.
    ➡️ pnpm은 엄격해서 내가 직접 설치한 것만 import가 가능하기 때문에 훨씬 안전!! 🙌


🤔 Nx는 뭐고 Turborepo는 또 뭐야?

규모가 작을 때는 pnpm만으로도 괜찮을 수 있지만 점점 프로젝트 규모가 커지다 보면 빌드에 관한 문제가 생긴다고 한다.

// 모노레포 구조 예시

my-monorepo/
├── apps/
│   ├── web/          ← Next.js 앱
│   └── admin/        ← 어드민 페이지
└── packages/
    ├── ui/           ← 공용 컴포넌트
    └── utils/        ← 공용 유틸 함수

문제점1. 순서를 사람이 신경써야 함.

  • webui를 사용한다면 ui가 먼저 빌드되어야 함. 하지만 pnpm은 이 순서를 자동으로 파악하지 못함.
  • 따라서 사람이 'ui를 먼저 빌드한 다음, web을 빌드해.'라고 신경써야 함.

문제점2. 바뀐 게 없어도 매번 전체를 다시 빌드함.

  • utils에서만 수정사항이 있었어도 상관없는 web, admin, ui 모두를 다시 빌드함.
  • 이는 패키지가 많아지면 많아질수록 오랜 시간이 소요됨.

➡️ 이 문제들을 해결하기 위해 빌드 도구를 추가로 사용함

⚒️ 빌드 도구가 하는 일

다양한 빌드 도구들이 있지만 공통적으로 있는 핵심 기능은 다음과 같다.

1. 의존성 순서 자동 파악 (Task Orchestration)

  • 문제점1에서 다뤘던 '패키지 간의 관계'를 분석해서 올바른 순서로 자동 실행시켜줌

2. 병렬 실행 (Parallel Execution)

  • 의존 관계가 없는 패키지들은 동시에 실행시켜줌

3. 캐싱 (Caching)

  • 바뀐 패키지만 다시 실행하고, 바뀌지 않은 패키지는 저장된 결과를 재사용

📌대표적인 빌드 도구

1. Turborepo

Vercel에서 만든 도구. 설정이 매우 단순하다는 특징 (turbo.json 파일 하나로 대부분의 설정 가능)

// turbo.json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"]
    }
  }
}
  • 파이프라인(pipeline)
    • package.json에 있는 각각의 스크립트를 실행할 때 "어떤 순서로, 캐싱을 할지?, 동시에 실행시킬지?" 등 어떻게 실행할지 정의한 규칙 모음
    • 위의 예시 코드는 build 스크립트를 실행할 때의 규칙
  • ^ : 내가 의존하는 패키지를 가리키는 기호
    • ^build"내가 의존하는 패키지들의 build가 먼저 끝나야 함"을 의미
    • 워크스페이스가 파악한 패키지들이 의존하는 관계를 바탕으로 이 규칙들이 적용 됨

2. Nx

Turborepo보다 오래된 도구, 기능이 매우 많음. Turborepo와는 다르게 코드 생성 기능이 존재.
(명렁어 하나로 컴포넌트, 페이지 등의 보일러 플레이트 자동 생성 가능)


📺 참고 자료 📺
2022 우아콘 모노레포 영상
Turborepo 공식문서

0개의 댓글