모노레포의 실행, 버전, 배포 관리를 쉽게하고싶다면 Lerna를 사용해보자

현우
  1. 라이브러리
  2. 프론트엔드
여러 NPM 패키지를 하나의 저장소에서 함께 관리하는 방식을 모노레포라고 합니다. 예를 들어 디자인 시스템, 공통 유틸리티, API 클라이언트가 서로 다른 패키지지만 함께 개발된다면 하나의 루트에 관리하는 모노레포 구조가 좋은 선택지이기도 합니다. Lerna 는 이 환경에서 여러 패키지에 명령을 시행하고, 버전을 관리하고, NPM 배포를 편리하게 해주는 도구입니다.

시작하기

아래 명령어를 통해 Lerna 세팅을 손쉽게 할 수 있습니다.
npx lerna init
Lerna 는 기본적으로 패키지 매니저의 workspace 설정을 재사용합니다. NPM 기준 루트 package.json 은 다음처럼 구성할 수 있습니다.
1234567{
  "name": "my-monorepo",
  "workspaces": ["packages/*"],
  "devDependencies": {
    "lerna": "^9.0.0"
  }
}
그리고 자동으로 추가된 lerna.json 파일에서 아래와 같이 구성을 합니다. 기본적으로는 version 과 npmClient 정도만 명시를 해주어도 되지만 각 패키지가 개별적으로 관리되어야하고 깃 커밋 메세지를 통해 버전 제어도 해야하기 때문에 conventionalCommits 를 추가해주었습니다.
123456789{
  "version": "independent",
  "npmClient": "pnpm",
  "command": {
    "version": {
      "conventionalCommits": true
    }
  }
}

여러 패키지 명령 한번에 실행해보기

각 패키지에 build 스크립트가 있다고 가정해보겠습니다.
12345{
  "scripts": {
    "build": "tsc -p tsconfig.json"
  }
}
루트에서 아래 명령어를 통해 모든 패키지의 빌드를 실행할 수 있습니다.
npx lerna run build
Lerna 는 패키지 간 의존 관계를 고려하여 적절한 순서로 실행되며, 가능한 작업들을 병렬 처리합니다. 대규모 모노레포에서 매번 패키지를 직접 이동하며 빌드할 필요가 없다는 점이 장점이기도 합니다.
특정 패키지를 실행하거나, 변경된 패키지에 한해서도 실행이 가능합니다.
npx lerna run test --scope @my-organization/ui // 특정 패키지
npx lerna run build --since 브랜치명 // 변경된 패키지만 (브랜치명을 생략하면 가장 최근 Git 태그 기준으로)

버전 쉽게 관리해보기

모노레포로 프로젝트나 모듈들을 관리하게 되면 점차 많아지는 경우 버전 관리를 일일히 하는 것도 많은 공수가 발생합니다. Lerna 의 대표적인 기능은 여러 패키지의 버전을 쉽게 관리하고 배포하는 일입니다.

버전 : Fixed 모드

모든 패키지가 같은 버전을 공유하게 됩니다.
@my-organization/ui  > 1.4.0
@my-organization/utils > 1.4.0
@my-organization/api-client > 1.4.0
패키지들이 하나의 제품처럼 함께 릴리즈될 때 관리하기가 용이하며, 해당 방식이 Lerna 의 기본 방식이기도 합니다.

버전 : Independent 모드

패키지마다 독립적으로 버전을 가지게 됩니다.
@my-organization/ui  > 1.1.0
@my-organization/utils > 1.2.2
@my-organization/api-client > 1.4.0
패키지별 변경 주기와 배포 주기가 뚜렷하게 다를 때 적합하며, 버전 변경을 시작할 때는 보통 아래 명령어로 시작합니다. 변경된 패키지를 찾아 버전 범위를 선택하게 하고, 필요한 의존성 버전 갱신, 깃 커밋, 태그 생성까지 처리할 수 있습니다. 이후 NPM에 그대로 배포를 진행할 수 있습니다.
npx lerna version // 버전 변경 시작
npx lerna publish // NPM 라이브러리 배포

빌드스크립트로 명시하기

위에서 정리한 내용들은 모두 cli 환경에서 테스트를 진행해보았다면, package.json 에 이와 같은 명령어들을 정의해놓는다면 CI/CD 환경에서도 사용할 수 있을 뿐만 아니라 매번 긴 명령어를 입력할 필요가 없습니다.
12345678{
  "scripts": {
    "build": "pnpm -r run build",
    "build:changed": "lerna run build --since",
    "changed": "lerna changed",
    "version:changed": "lerna version --conventional-commits"
  } 
}
•
build : 모든 워크스페이스 패키지의 build 스크립트를 실행합니다.
•
build:changed : 가장 최근 Git 태그 이후 변경된 패키지만 빌드합니다.
•
changed : 최근 Git 태그 이후 변경된 패키지 목록만 출력합니다. 빌드나 파일 수정은 하지 않습니다.
•
version:changed : 변경된 패키지를 찾고, Conventional Commit 메세지를 기준으로 버전을 올립니다.
悠悠自適
유유자적한 블로그 주인장 김현우입니다.
오늘도 안녕하신가요?
Subscribe
👍