Mono Repo 를 위한 Lerna 간단 정리하기
최근 Mono Repo 의 개념을 알게되어, 이를 간단하게 정리해보고자 한다.
Mono Repo 를 한마디로 정의하자면, 분산되어 관리되는 여러 Repository 를 한 Repository 안에 넣어서 관리하자 이다. 반대 말로 Multi Repo 가 있다.
여기에서 Repository 는 Git 의 Repository 와 같은 의미이다.
새로운 프로젝트를 시작하게 되면, 새로운 Git Repo 를 생성하고, 관리하기 시작한다.
새로 생성하는 Repo 는 각각의 프로젝트에 영향도가 없다는 장점이 생기지만, 기존에서 만들어둔 Code 를 재사용 하기 어렵다.
Git Submoudle 로 만들어서 재사용 할 수 있지만, Submodule 은 Master branch 만을 사용 하는등 여러 제약이 있다.
Web Site 의 Page 별로 Project 를 만들어서 사용하고 있었는데, Page 가 증가할 수록 관리해야하는 Project 가 늘어만 갔다. 중간 중간 react 등의 버전이 올라가면, 모든 프로젝트에 버전을 관리해주어야 하여, 관리 포인트가 증가했고, 비슷한 Component와 Logic 들이 많아졌지만, 이를 Submodule 만으로는 재사용 하는데, 어려움이 있었다.
Lerna 정의
“A tool for managing JavaScript projects with multiple packages.”
Lerna 는 여러 Pakcages (프로젝트) 를 관리하도록 도와주는 도구 이다.
Lerna 를 이용하면, Mono Repo 를 구성하는데, 도움을 받을 수 있다.
mono-repo/
packages/
package-1/package.json
package-2/package.json
package.json
lerna.json
Lerna 는 packages 폴더에 각각의 pakcage(프로젝트) 를 구성한다.
이 package 에 있는 package.json 을 참조하여, node_module 을 관리할 수 있도록 도와준다.
Lerna 시작하기
간단한 예제로 Lerna 에 대해서 알아보자.
아래 명령어로 lerna 를 세팅하면,
mkdir lerna-test
cd lerna-test
npx lerna init
아래 형태의 파일들이 생성된다.
packages/*
lerna.json
package.json
lerna.json 은 leran 의 세팅 정보 이다.
npmClient 로 npm 이나 yarn 을 세팅할 수 있고, bootstrap 으로 bootstrap 명령에 필요한 정보를 세팅할 수 있다.
packages 으로 package 의 위치를 설정할 수 있다.
{
"npmClient": "npm" || "yarn",
"bootstrap": {
"ignore": "bootstrap 제외" ,
"npmClientArgs": [ "npm install 명령 인자" ],
},
"packages": [ "packages/*" ],
"version": "0.0.0"
}
Lerna 에서는 packages 기준으로 각 폴더를 따라 package.json 을 파악하고 처리한다.
Lerna Bootstrap
lerna 에서 가장 중요한 명령어는 bootstrap 이다.
lerna bootstrap --hoist
를 실행하면, ignore 로 설정된 package 를 제외한 모든 package 의 npm install 을 실행한다.
이때 공통된 module 들은 root 의 node_modules 에 install 하고 각 package 들에 연결된다. 만약 각 package 별로 버전이 다를 경우, warning 메시지를 띄우고, package 의 node_modules 에 install 된다.
각 패키지별로 버전이 다른경우를 체크할 수 있으며, 하나의 버전으로 모을 수 있다.
가끔 설치가 꼬일수 있는데, 이 경우 lerna clean
으로 모든 package 의 node_modules 를 삭제하고, lerna bootstrap
다시 설치할 수 있다.
package.json 의 dev dependencies
lerna 에서는 제품에 포함되지 않는, dev dependencies 를 root 로 모을 수 있다.
lerna link convert
명령어를 실행하면, 모든 package 에 설정된 devDependencies 을 root devDependencies 으로 옮긴다.
그리고, dependencies 에 package 를 file:packages/package-1 형태로 연결한다.
"dependencies": {
"package-1": "file:packages/package-1",
"package-2": "file:packages/package-2",
}
이때 각 package 들의 devDependencies 은 모두 root 으로 이동해버렸기 때문에, package 에서 devDependencies 를 실행하면, 예를 들어 webpack 을 실행하면, 작동하지 않는다.
이경우 root 에서 lerna run --scope package-1 start
로 실행하면 root 에 있는 devDependencies 를 참조할 수 있게 된다.
여기에서 lerna run
명령어는 package.json 에 있는 script 를 실행시킨다. — scope 으로 package 를 선택할 수 있다.
Lerna 를 이용한 Mono Repo 장점 및 단점
Mono Repo 로 프로젝트를 구성하게되면, 각각 프로젝트 마다 설정하던, ESlint 나 Jest 등의 세팅을 더 이상 복붙할 필요가 없다.
한 repo 에 모든 코드가 포함되어 있기 때문에, 코드 재사용도 용이해 진다.
하지만 관련없는 Repo 를 합치면, 오히려 관리해야하는 포인트가 증가 한다.
기존의 Repo 로 관리하던 코드를 합치면, history 를 잃어버릴 수도 있다.
lerna import 으로 합칠 수 있지만, 코드의 history 가 복잡하게 꼬여 있다면, 실패할 수 도 있다.