Monorepo와 lerna
Monorepo vs Polyrepo
☝️ Monorepo
Monorepo는 여러 프로젝트의 소스 코드를 관리하는 데에 하나의 저장소(repository)만 사용하는 것을 의미합니다. 예를 들어 Monorepo를 이용하면 웹 앱 프로젝트, 모바일 앱 프로젝트, 서버 프로젝트가 한 저장소에 있게 됩니다.
Monorepo와 대비되는 개념으로는 Polyrepo(혹은 Multirepo)가 있습니다.
🖐 Polyrepo
Polyrepo는 여러 프로젝트의 소스 코드를 관리하는 데에 여러 개의 저장소를 사용하는 것을 의미합니다. Monorepo와 달리 Polyrepo에서는 웹 앱 프로젝트, 모바일 앱 프로젝트, 서버 프로젝트가 각각의 저장소를 갖게 됩니다.
👍 Monorepo의 장점
통합적인 test, build, release 작업
한 저장소에서 관리되기 때문에 한 번의 커맨드로 여러 패키지의 스크립트(test
, build
, release
)를 실행할 수 있습니다.
코드의 통일성 증가
여러 개의 저장소로 관리될 경우 다른 저장소를 보게 될 기회가 많이 없기 때문에 전체적인 코드 스타일, 아키텍쳐 패턴, 테스트 방법 등에 통일성이 없이 코드가 중구난방이 됩니다. 혹여 통일성을 맞추려해도 통일성에 대한 문서화 작업과 복잡한 적용 과정을 거치게 되면서 많은 시간을 허비하게 됩니다. 또한 같은 기능을 가진 함수를 각자의 방식으로 10개의 저장소에서 사용되었다고하면 불필요한 공간을 차지한다고도 볼 수 있습니다. 그러나, Monorepo로 관리될 경우 이러한 통일성의 문제를 해결할 수 있습니다. 전체 프로젝트에 적용되는 eslint
로 코드 스타일을 맞추고 다른 프로젝트 코드를 보면서 아키텍쳐 패턴을 확인할 수 있습니다.
분산된 이슈의 통합
대주제에 해당하는 하나의 저장소에서 이슈를 처리하기 때문에 여러 저장소에서 이슈를 올리면서 논의가 분산되는 것을 막을 수 있습니다.
개별적 모듈 버전 관리
Monorepo로 관리되어도 내부의 프로젝트들은 각각 개별적인 모듈이기 때문에 각각 버전 관리를 할 수 있습니다.
쉬운 코드 공유
기존의 방식대로라면 npm
등의 패키지 매니저에 등록하고 해당 패키지를 설치하여 사용하는 방식이지만, Monorepo로 관리된다면 다음과 같이 패키지 매니저 등록 없이 코드를 공유할 수 있습니다.
// ./package.json
{
"name": "@foo/server",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@foo/common": "^1.0.1",
...
},
"scripts": {
"test": "echo testing server with version: $npm_package_version"
}
}
공유한 패키지 사용 방법은 다음과 같습니다.
// ./packages/server/*
const commonFunction = require("@foo/common");
commonFunction();
Monorepo | Polyrepo | |
---|---|---|
저장소 갯수 | 1개 | 패키지의 수만큼 필요 |
통일성 | 높음 | 낮음 |
이슈 관리 | 한 저장소에서 관리 | 각 저장소에서 관리 |
코드 재사용성 | 높음 | 낮음 |
🐉 lerna
lerna
lerna는 다중의 패키지가 있는 Monorepo 구조로 된 자바스크립트 프로젝트의 test
, build
, release
같은 작업을 최적화 시켜주는 툴입니다. lerna는 위에 언급했던 것처럼 여러 저장소의 의존성을 묶어주는 역할과 각 패키지별 버전 업데이트를 도와줍니다.
lerna 프로젝트 구성
lerna를 이용한 프로젝트는 다음과 같은 구조를 가집니다.
lerna-repo/
packages/
package_1/package.json
package_2/package.json
package.json
lerna.json
packages
packages
는 필요한 node 패키지들을 관리하는 폴더입니다. Polyrepo
에서 Monorepo
로 전환하는 경우 사용하던 node 패키지를 그대로 넣어서 사용 가능합니다.
package.json
최상위에 있는 package.json
는 기존의 package.json
처럼 script
를 추가하여 개별적으로 혹은 동시에 패키지의 스크립트를 실행할 수 있게 합니다.
lerna.json
lerna.json
에서는 lerna
관련 커맨드를 사용하는 옵션을 결정합니다.
{
"packages": [ "packages/*" ], // node 패키지가 들어갈 폴더
"npmClient": "npm", // npm 혹은 yarn 중 어떤 것을 사용할 지
"bootstrap": {
"ignore": // lerna bootstrap에서 제외되는 부분
"npmClientArgs": // npm install 명령 인자
},
"version": "0.0.0"
}
lerna 시작하기
lerna를 이용한 기본적인 프로젝트를 만들어봅시다.
우선, lerna관련 커맨드를 사용해야하기 때문에 lerna를 전역으로 설치합니다.
$ npm install --global lerna
새로운 git 저장소를 생성하고 해당 폴더로 들어갑니다.
$ git init lerna-repo && cd lerna-repo
해당 프로젝트를 lerna 기본 구조로 바꿉니다.
$ npx lerna init
위 작업까지 끝나면 최종적으로 다음과 같은 구조를 가진 프로젝트가 생성됩니다.
lerna-repo/
packages/
package.json
lerna.json
lerna에서 사용할 수 있는 커맨드
lerna init
새로운 lerna 저장소를 생성하거나 현재 저장소를 새로운 lerna 버전으로 업데이트합니다.
lerna bootstrap
각 패키지별로 겹치는 의존성(dependency)은 연결하면서 현재 lerna 저장소의 패키지들의 모든 의존성을 설치합니다. 예를 들어 @foo/server
와 @foo/client
에서 같은 lodash
라이브러리를 사용한다면, 겹치는 의존성은 연결되어서 루트 디렉토리의 node_modules
에 설치되고, 겹치지 않는 의존성은 각각의 패키지 프로젝트의 node_modules
에 설치됩니다.
lerna import <pathToRepo>
로컬에 위치하는 <pathToRepo>
에 해당하는 패키지를 커밋 히스토리와 함께 packages/<directory-name>
으로 import합니다.
lerna publish
업데이트된 패키지의 새로운 배포를 생성합니다. 새 버전으로 올리고 git과 npm에서 모든 패키지를 업데이트합니다.
lerna changed
지난 배포 이후 어떤 패키지에 변화가 있었는 지 확인합니다.
lerna diff [package?]
지난 배포 이후 개별 혹은 모든 패키지의 diff
를 보여줍니다.
lerna run [script]
해당 script
를 포함하는 각 패키지에 해당 npm script를 실행합니다. 각 프로젝트에 test
관련 script가 존재한다면, 루트 디렉토리에서 lerna run test
커맨드로 모든 프로젝트의 테스트 코드를 실행할 수 있습니다.
lerna ls
현재 lerna 저장소에 있는 모든 public 패키지를 나열합니다.
참고자료
- 📹How to Use Lerna
- 📹Better code sharing through monorepos?
- 📹Marcel Cutts - MonoRepos for the Masses | ReactNext 2018
- 📹Uber Technology Day: Monorepo to Multirepo and Back Again - 우버의 안드로이드 패키지가 Monorepo에서 시작해서 Multirepo로 바꿨다가 다시 Monorepo로 돌아오게 된 내용의 영상
- 📹Jacob Bass: Modularity and Monorepositories
- 📹Yarn Workspaces Tutorial
'Design Pattern' 카테고리의 다른 글
[디자인 패턴] 👆 Monorepo란? (0) | 2019.08.16 |
---|---|
[Design Pattern] Atomic Design (0) | 2019.05.30 |
댓글
이 글 공유하기
다른 글
-
[디자인 패턴] 👆 Monorepo란?
[디자인 패턴] 👆 Monorepo란?
2019.08.16 -
[Design Pattern] Atomic Design
[Design Pattern] Atomic Design
2019.05.30