icon

메티의 블로그

PNPM 카탈로그 기능으로 의존성 분류하기
PNPM 카탈로그 기능으로 의존성 분류하기

PNPM 카탈로그 기능으로 의존성 분류하기

Tags
Frontend
DX
날짜
May 30, 2025
상태
공개

개요

PNPM 카탈로그 기능으로 의존성 마다 태그를 두어 의존성을 명확히 분류해놓는 방법이 제가 구독하고 있는 프론트엔드 아티클 서비스에서 소개되어 제가 개발 중인 블로그에 적용하였습니다. 마침 제가 사용하는 패키지 매니저도 pnpm 이고, 이러한 기능들을 마음대로 적용해 보기 좋은 프로젝트도 있어서 쉽게 적용할 수 있었습니다. 적용은 아주 간단하지만, 생각보다 효과가 좋은 것 같습니다. 이 기회에 내가 더이상 사용하지 않는 패키지들을 정리하고, 이런 패키지들은 왜 설치했더라? 하는 것을 다시 정리해보게 되었습니다.

pnpm 카탈로그 기능이란?

(docs 를 보면 pnpm 카탈로그 프로토콜 이라는 표현을 사용합니다.) pnpm의 카탈로그 기능은 모노레포 안에서 다른 프로젝트들끼리의 의존성을 관리 할 때 일관성을 유지하기 위해 만들어졌습니다. 모노레포 안에서 각 프로젝트들의 의존성 버전은 통일 되는 것이 좋을 확률 높습니다. 그래서 의존성 버전을 미리 매핑해두고, 이를 각 프로젝트에서 미리 끌어다 쓰도록 의도하였습니다. 이를 통해서, 모노레포에서 아래와 같은 부분이 관리하기 쉬워집니다.
  • 의존성의 특정 버전이 꼭 필요한 경우를 관리하기 쉽다.
  • 의존성 업그레이드를 모든 프로젝트에 일괄 적용하기 쉽다.
  • package.json 의 파일에는 변화가 없으므로, 머지 컨플릭트가 적어진다.

pnpm 카탈로그 기능 사용법

사용법은 정말 간단합니다. pnpm-workspace.yaml 파일에 catalog 또는 catalogs 라는 데이터를 정의하고, 이를 pacakge.json 에서 끌어 쓰면 됩니다. 복수의 카탈로그를 사용할 때 catalogs 로 yaml 에 정의하며, package.json 에서는 catalog 로 통일해 사용합니다.
# ... catalogs: "react": "^18" "next": "14.2.25" # ...
pnpm-workspace.yaml 파일 예시
// ... "dependencies": { "react": "catalog:", "next": "catalog:", } // ...
pacakge.json 파일 예시
그리고, 이 기능은 각 카탈로그에 이름을 다는 기능이 존재합니다.
# ... catalogs: # Can be referenced through "catalog:react17" react17: react: ^17.0.2 react-dom: ^17.0.2 # Can be referenced through "catalog:react18" react18: react: ^18.2.0 react-dom: ^18.2.0 # ...
pnpm-workspace.yaml named catalog 사용 예시
// ... "dependencies": { "react": "catalog:react18" "react-dom": "catalog:react18" } // ...
package.json named catalog 사용 예시
이는 각 의존성 카탈로그에 이름을 다는 용도로 만들어 진 것으로, depth 를 더 깊게하는 계층적인 사용은 할 수 없습니다. (실험 해봤음)
그리고 이 카탈로그는 pnpm publishpnpm pack 등으로 배포할 때는 실제 카탈로그에 적힌 버전으로 교체됩니다.

카탈로그 사용시 유의할 점

현재 작성일자인 2025년 5월 29일 기준으로, pnpm update 커맨드를 지원하지 않습니다. (사실, pnpm add 에 맞춰서 pnpm-workspace.yaml 파일이 변화하지도 않습니다.) 그래서, update 가 필요하다면, 카탈로그에 정의된 버전을 업데이트하는 것이 필요합니다.

카탈로그 기능으로 의존성 분류

package.json 파일은 한번 설정하면 다시 볼 일이 상대적으로 줄어듭니다. 오랜만에 package.json 의존성들을 보면 이걸 왜 설치했는지, 어떤 역할을 하는지 잊을 때도 있습니다. 이런 일을 방지하기 위해 새로운 아티클은 카탈로그 기능으로 의존성을 분류하고, 간단하게 태그를 달아 관리하는 방식을 소개합니다. 그리고, 이 관리 방식을 좀 더 가시적으로 좋게 보여주기 위해 아티클에서는 하나의 플러그인을 소개합니다.

소개된 vscode 플러그인

제가 읽은 아티클 작성자는 아마도 이 플러그인의 제작자인 것 같습니다. 에디터의 package.json 에서 이러한 카탈로그 이름을 적는 방식은 관리하기 참 좋지만, 사실 실제 버전을 보기 힘들다는 단점이 있습니다. 사실 일반적으로는 그리 중요하지 않지만, 그래도 의존성들의 버전관리를 할 때, 카탈로그를 확인하는 것과, 바로 볼 수 있는 것은 문제를 파악할 때 차이가 분명 있을 것이라 생각합니다.
PNPM Catalog Lens 라는 포스트 글의 원작자 분이 만든 vscode 플러그인을 사용하면 다음과 같이 볼 수 있습니다. (당연히 커서에서도 사용 가능합니다.)
PNPM Catalog Lens 적용 전과 후의 package.json
PNPM Catalog Lens 적용 전과 후의 package.json
이 플러그인은 가시성 좋게 버전을 보여주는 것 뿐만 아니라, 색깔도 구분해주어, package.json 에서의 의존성 구분을 할 수 있도록 해줍니다.

분류 방식

이제 package.json 에서도 쉽게 버전과 카탈로그 구분을 동시에 할 수 있게 되었으니 필요에 맞게 사용하면 되겠습니다. 분류 방식은 사용자 또는 팀의 필요와 기호에 맞게 분류하여 사용하는 것이 결국 정답이지만, 사용 예시를 공유하는 것도 도움이 되겠다 생각이 되어, 제가 사용한 방식을 공유하고자 합니다. 제 블로그는 next.js 로 개발이 되어있는 풀스택 프로젝트 입니다. 그래서 어떤 라이브러리 api 는 클라이언트에서는 사용이 불가하기도 하고, 어떤 라이브러리는 서버에서 사용이 불가하기도 하고, 어떤 라이브러리는 둘 다 사용 가능합니다. 이런 구분이 제일 도움이 될 것 같아서 다음과 같이 구분하였습니다.
블로그 의존성 카탈로그
블로그 의존성 카탈로그
  • core: 코어 부분을 담당하는 라이브러리들, 여기서 sharp 는 next.js 에서 이미지 최적화를 위해 설치를 권장하는 라이브러리로, 기본으로 들어가있지 않는 것은 너무 무겁기 때문이라고 합니다. 저는 next.js 에서 사용하는 것 이외에 제가 따로 사용하지는 않으므로, core 에 두었습니다.
  • shadcn/ui: shadcn/ui 는 특이한 디자인 시스템입니다. 코드를 직접 주입받는 방식으로 추가되며, 이때 필요한 라이브러리들이 제가 의존성을 직접 추가하지 않는 상황에서 추가됩니다. shadcn/ui 에 의해서 의존성이 추가되는 경우 제가 의도적으로 추가하는 것이 아닌 라이브러리가 생각보다 많이 추가되기 때문에, 따로 카탈로그를 추가하였습니다. 해당 라이브러리 기능만 보고 제거하는 것을 막기 위해서 입니다.
  • frontend: 클라이언트(브라우저) 환경에서만 사용할 수 있는 라이브러리들을 분류하였습니다. 풀스택 프로젝트다 보니, 환경에 맞지 않는 잘못된 사용을 하여 에러가 나게되더라구요. import 할 때도 이런 카탈로그 태그를 볼 수 있다면 정말 좋을 것 같네요.
  • backend: 서버 환경에서만 사용할 수 있는 라이브러리들을 분류하였습니다. 클라이언트에서는 사용할 수 없는 node 의존성이 섞여있는 경우로, 이 또한 클라이언트에서 사용하려고 하면 에러가 납니다.
  • shared: 순수 JS 로 개발되어 클라이언트 서버 환경 상관 없이 사용할 수 있는 경우입니다. 네이밍을 util 로 하려고도 했었는데, notion 관련된 라이브러리는 단순 util 기능이 아닌 도메인 관련 함수들이 있기 때문에, shared 로 정했습니다.
  • monitoring: 모니터링 할 수 있는 라이브러리 입니다. 아직은 vercel 에서만 사용하는 간단한 모니터링 라이브러리만 사용하고 있습니다.
  • lint: 린트 관련 의존성(dev)들 입니다.
  • test: 테스트 관련 의존성(dev)들 입니다. 테스트 관련 라이브러리들은 환경적으로 시뮬레이션 해주어야할게 많기 때문에, 많은 의존성이 있습니다.
  • types: 타입스크립트의 타입만 따로 제공하는 경우가 많기 때문에 분류했습니다.
  • build: 빌드 관련 의존성(dev)들 입니다.

결론

의존성을 분류해 따로 관리하는 것의 장점에 대해서 한번 더 확인하고, 유용한 플러그인이 있어 적용해 보았습니다. 이 의존성 분류를 해보면서, 린트 규칙으로 하나 추가해보고 싶은 것이 생겼습니다. 이참에 한번 시도 해봐야겠네요.

출처