Monorepo 환경에서 npm to pnpm 마이그레이션 후기(feat.lerna)

소일로·2025년 2월 12일
0
post-thumbnail

🚀 Monorepo 환경에서 npm → pnpm 마이그레이션 & lerna-lite를 활용한 배포 경험 정리

최근 약 40개의 패키지로 구성된 모노레포(monorepo) 프로젝트에서 npm + lerna 조합에서 pnpm + lerna-lite로 마이그레이션을 진행했습니다.

이 과정에서 왜 pnpm을 선택했는지, 마이그레이션을 진행하면서 겪은 이슈들, 그리고 배포 도구로 lerna-lite를 선택한 이유까지 정리해보려 합니다.


1️⃣ 왜 pnpm으로 마이그레이션 했는가?

기존에는 npm + lerna 조합을 사용하여 모노레포를 관리해왔습니다.

npm 자체적으로는 모노레포 지원이 없기 때문에, lerna를 활용하여 패키지 간 의존성을 관리하고 lerna bootstrap을 통해 빌드와 publish를 진행했습니다.

📌 기존 lerna의 장점 중 하나는 공통 의존성을 최적화하여 중복 설치를 방지하는 것이었습니다.

그러나 몇 가지 이유로 인해 pnpm이 가진 여러 가지 장점들을 고려하여 마이그레이션을 결정했습니다.


2️⃣ pnpm을 선택한 이유

✅ 1. pnpm모노레포를 네이티브로 지원

pnpmpnpm workspaces 기능을 통해 별도의 도구 없이 모노레포를 효과적으로 관리할 수 있습니다.

기존 npm에서는 lerna 없이 모노레포를 관리하기 어려웠지만, pnpmpnpm workspaces를 사용하여 의존성 설치 및 패키지 간 링크를 자동으로 처리해 줍니다.

pnpm install

lerna bootstrap 없이도 한 번의 pnpm install로 모든 패키지가 설정됩니다. 🎯


✅ 2. 더 빠른 의존성 설치 속도

pnpm하드 링크(Hard Link) + 심볼릭 링크(Symbolic Link) 방식을 사용하여 설치 속도를 획기적으로 개선했습니다.

한 번 설치한 패키지는 공유 스토리지(~/.pnpm-store)에서 재사용되기 때문에 중복 설치를 방지하고 디스크 사용량도 줄어듭니다.

🔥 실제 성능 비교 예시

Package ManagerFirst InstallReinstall
npm1m 30s50s
yarn1m 20s40s
pnpm30s5s

최대 5배 빠른 속도를 체감할 수 있었습니다! 🚀


✅ 3. 공통 의존성 최적화 (lerna보다 효율적)

lerna는 공통 의존성을 최적화하여 중복 설치를 방지하지만, 여전히 node_modules 내부에서 일부 중복이 발생할 수 있습니다.

반면, pnpm은 의존성을 전역 .pnpm-store에 저장하고, 각 패키지는 심볼릭 링크를 통해 참조하는 방식을 사용합니다.

📌 pnpm의 최적화 방식

📂 ~/.pnpm-store/
   ├── lodash@4.17.21/
   ├── react@18.2.0/
📂 node_modules/
   ├── @myorg/utils -> ~/.pnpm-store/utils
   ├── @myorg/app -> ~/.pnpm-store/app

의존성 중복을 완전히 제거하여 lerna 없이도 최적화된 설치가 가능!


✅ 4. 더 강력한 의존성 격리 제공

npmyarnnode_modules 내부에서 패키지가 중복 설치될 가능성이 높습니다.

하지만 pnpm은 패키지별로 의존성을 격리하여 설치하므로 패키지 간 의존성 충돌을 방지할 수 있습니다.

📌 pnpm의 의존성 관리 방식

📂 node_modules/
   ├── .pnpm/
   │   ├── lodash@4.17.21
   │   ├── lodash@4.16.0
   ├── @myorg/utils (uses lodash@4.17.21)
   ├── @myorg/app (uses lodash@4.16.0)

프로젝트의 안정성을 높이고, 버전 충돌 문제를 줄일 수 있음!


🛠 5. 호환성 및 유지보수 문제 해결 (lerna의 유지보수 문제)

  • lerna는 2022년 이후로 **더 이상 적극적으로 유지보수되지 않고있습니다.
  • 반면, pnpm은 꾸준히 업데이트되고 있으며, *커뮤니티 지원도 활발합니다.
  • lerna 없이도 pnpm workspaces로 대부분의 기능을 대체 가능하기 때문에 더 좋은 선택이라고 생각합니다

3️⃣ lerna-litepublish 용도로 선택한 이유

✅ 1. pnpmpublish 기능이 부족함

  • pnpm은 모노레포 관리 및 설치 속도 최적화에는 강력하지만, 버전 관리 및 배포(publish) 기능이 없음.
  • 따라서, 모노레포에서 개별 패키지를 효과적으로 배포하기 위해서는 별도의 publish 도구가 필요.
  • 기존 lerna는 기능이 너무 많아서 무거웠고, 유지보수도 중단됨.

해결책: lerna-lite를 활용하여 패키지 버전 관리 및 배포를 간단하게 처리


✅ 2. lerna-litelerna의 핵심 기능만 유지한 경량화 버전

  • lerna-litelerna에서 필요한 기능만 유지한 가벼운 버전으로, 특히 publish 기능에 최적화됨.
  • 기존 lerna보다 빠르고 가벼우며, 유지보수도 활발하게 진행 중.

📌 lerna-lite의 특징

기존 lernalerna-lite
패키지 설치 & 관리 (bootstrap) 포함패키지 설치 기능 없음 (pnpm이 담당)
버전 관리 + 배포 기능 포함버전 관리 및 배포(publish) 기능만 유지
유지보수 중단됨경량화 & 지속적인 업데이트

pnpm과 함께 사용하면 최적의 조합!


✅ 3. lerna-litegitnpm publish를 자동화하여 배포 최적화

기존 배포 방식:

  1. 패키지별 version 업데이트
  2. 변경사항 커밋 & 태그 생성
  3. npm publish 실행
  4. GitHub Push

📌 lerna-lite로 간단하게 해결 가능

<bash
lerna version
lerna publish from-package

버전 관리 + Git 커밋 + 태그 + 배포까지 처리

4️⃣ 트러블슈팅: workspace 개념을 몰라 발생한 이슈

마이그레이션 과정에서 개발 환경에서 코드를 변경해도, local 저장소의 레포를 참조하는 것이 아니라 install 시 가져오는 레포를 계속 참조하는 문제가 발생했습니다.

이 때문에, 로컬에서 변경한 코드가 즉시 반영되지 않는 이슈가 있었습니다.

✅해결 과정

  • 공식 문서를 참고하면서 pnpm의 workspace 개념을 이해하게 되었습니다.
  • ^workspace:를 사용하면, publish 시 자동으로 버전이 변경되고, 현재 작업 중인 패키지를 참조하도록 설정된다는 것을 알게 되었습니다.
  • 즉, 기존에는 node_modules을 참조하던 방식과 다르게, 현재 작업 중인 패키지를 직접 참조하도록 되어 있었습니다.

이 과정에서 pnpm이 패키지 간의 의존성을 더 효율적으로 관리할 수 있다는 점을 확실히 이해하게 되었습니다. 🚀

결론: 공식문서를 잘 읽자 + 앞으로 pnpm 위주로 사용할것 같습니다(만족도 높음).

profile
백엔드 개발자

0개의 댓글