😬 이번에는 프로젝트에 앞서서 학습하기로 한 내용 중에 제일 낯설었던 개념인 모노레포(Monorepo)와 이와 관련된 개념들을 학습해봤습니다..!
모노레포가 왜 필요한지 알기 위해 나에게 익숙한 방식인 멀티레포 방식과 어떤 차이점이 있는지 알아보았다.
| 멀티레포 | 모노레포 |
|---|---|
![]() | ![]() |
사진에서 볼 수 있듯이 멀티레포 방식은 여러 개의 레포지토리를 만들고 필요에 따라 서로를 참조하는 형태다.
이와는 다르게 모노레포는 그것들을 하나의 레포지토리 안에 포함시키는 형태라고 할 수 있다.
📂 레포A — 웹 서비스 (Next.js)
📂 레포B — 모바일 앱 (React Native)
📂 레포C — 디자인 시스템 (Button, Input 등 공용 컴포넌트)
이런 상황에서 웹과 앱에서 디자인 시스템의 Button 컴포넌트를 사용하려면 디자인 시스템을 배포한 뒤에 웹, 앱에 각각 설치해야함.
진짜 문제는 디자인 시스템에서 수정사항이 발생했을 경우.
npm link로 가능은 한 듯..?)➡️ 모노레포에서는 Button 컴포넌트 파일 하나만 수정하면 끝
➡️ 모노레포에서는 모든 커밋이 한 곳에 있기 때문에 git 히스토리 하나만 보면 파악 가능
💡 그럼 모노레포를 사용하면 좋은 경우는 언제?! ➡️ 여러 앱/패키지가 코드를 공유해야 할 때!
💡 하나의 레포지토리 안에 있는 여러 패키지를 패키지 매니저가 인식하고 연결해주는 기능
// 모노레포 구조 예시
my-monorepo/
├── apps/
│ └── web/ ← Next.js 앱
├── packages/
│ └── ui/ ← 공용 Button 컴포넌트
└── package.json ← 루트 설정 파일
web 앱에서 ui 패키지의 Button 컴포넌트를 사용하고 싶을 때 워크스페이스를 설정하면 ui 패키지를 마치 배포된 외부 라이브러리처럼 인식하게 해줌.
따라서 다음과 같이 npm에 배포하지 않고, 버전을 맞출 필요도 없이 import 할 수 있음
import { Button } from '@my-org/ui'
npm, yarn도 워크스페이스 기능이 있지만 알아보니 많은 사람들이 pnpm을 선호하는 이유가 있었다.
디스크 공간 절약
npm은 패키지를 설치할 때 각 프로젝트마다 중복으로 저장pnpm은 컴퓨터 한 곳에 딱 한 번만 저장하고, 각 프로젝트에서는 그걸 심볼릭 링크(Symbolic Link)로 참조하는 방식➡️ 모노레포에서는 패키지가 많아질수록 중복 설치가 심해지는데, 이 문제점을 pnpm이 해결해주는 거지! 🙌
유령 의존성 차단
npm은 패키지A가 패키지B를 의존하면, B도 내 코드에서 설치 없이 import 할 수 있음.
이는 나중에 A가 B를 제거하면 에러가 발생할 위험이 있음.
➡️ pnpm은 엄격해서 내가 직접 설치한 것만 import가 가능하기 때문에 훨씬 안전!! 🙌
규모가 작을 때는 pnpm만으로도 괜찮을 수 있지만 점점 프로젝트 규모가 커지다 보면 빌드에 관한 문제가 생긴다고 한다.
// 모노레포 구조 예시
my-monorepo/
├── apps/
│ ├── web/ ← Next.js 앱
│ └── admin/ ← 어드민 페이지
└── packages/
├── ui/ ← 공용 컴포넌트
└── utils/ ← 공용 유틸 함수
web이 ui를 사용한다면 ui가 먼저 빌드되어야 함. 하지만 pnpm은 이 순서를 자동으로 파악하지 못함.ui를 먼저 빌드한 다음, web을 빌드해.'라고 신경써야 함.utils에서만 수정사항이 있었어도 상관없는 web, admin, ui 모두를 다시 빌드함.➡️ 이 문제들을 해결하기 위해 빌드 도구를 추가로 사용함
다양한 빌드 도구들이 있지만 공통적으로 있는 핵심 기능은 다음과 같다.
Vercel에서 만든 도구. 설정이 매우 단순하다는 특징 (turbo.json 파일 하나로 대부분의 설정 가능)
// turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"]
}
}
}
package.json에 있는 각각의 스크립트를 실행할 때 "어떤 순서로, 캐싱을 할지?, 동시에 실행시킬지?" 등 어떻게 실행할지 정의한 규칙 모음^ : 내가 의존하는 패키지를 가리키는 기호^build는 "내가 의존하는 패키지들의 build가 먼저 끝나야 함"을 의미Turborepo보다 오래된 도구, 기능이 매우 많음. Turborepo와는 다르게 코드 생성 기능이 존재.
(명렁어 하나로 컴포넌트, 페이지 등의 보일러 플레이트 자동 생성 가능)
📺 참고 자료 📺
2022 우아콘 모노레포 영상
Turborepo 공식문서