imch.devabout

pnpm, 플랫하지 않은 패키지 매니저

pnpm 이라는 새로운 패키지 매니저가 있다. 새롭다고 표현하기엔 벌써 메이저 버전이 4지만, 여전히 자바스크립트를 새로 시작하는 사람들에게 npm이 익숙한 상황에서 새로운 패키지 매니저라는 표현은 틀리지 않다.

pnpm?

pnpm은 2017년에 처음 소개되었으며, npm을 대체하기 위한 더 빠르고 효율적인 패키지 매니저를 목표로 한다. pnpm는 패키지를 설치할 때 직접적으로 설치하는 방법 대신 심링크_(하드링크)_를 사용한다.

lodash를 사용하는 패키지 100개가 있다고 가정하였을 때, npm이나 yarn을 사용할 경우, 각 폴더별로 lodash 패키지가 100개가 복사된다.

라고는 하는데… 최악의 케이스를 가정하는 것 같고, 내 생각에는 semvar에 따라 그보다 적게(~100개) 나올 것 같다고 생각한다.

반면에 pnpm은 lodash를 단 한번만 설치하고, 다른 100개의 프로젝트에는 심링크로 연결하여, 용량 측면에서 효율적으로 패키지를 관리한다.

또한 yarn이나 lerna 처럼 모노레포를 위한 기능이나, pnpmfile.js 파일을 작성해서 패키지 설치 과정에 대한 훅_(Hook)_도 작성할 수 있다.

pnpm의 특징

pnpm은 performant npm의 약자로, npm보다 낫고 yarn보다 빠른 패키지 매니저의 특징을 갖고 있다. yarn이 보다 빠르기 위해서 pnpm은 node_modules를 플랫하게 만들지 않는다.

npm@~2 일 때는 굉장히 알기 쉬운 방법으로 node_modules 내부를 채웠다. 예를 들어 A->B->C로 종속 관계를 이루고 있다면, node_modules/A/…/node_modules/C 처럼 채워진다.

이 경우, 종속 관계에 따라 폴더 깊이가 깊어질 수 있다. 또한 동일한 패키지가 여러번 복사될 수도 있어서, 100개의 lodash가 존재할 가능성이 있다.

그래서 npm@3~부터 node_modules를 플랫하게 만든다. 아까와 같은 종속 관계가 있다면 node_modules 기준 최상위에 A,B,C 폴더를 만들고 복사한다.

근데 이 작업은 간단하지 않다. 대개 하나의 프로젝트를 진행하면 적어도 하나 이상의 패키지를 설치해야 한다. 그러면 여러 패키지간의 종속 관계를 이해하고 그걸 풀어내서 플랫하게 만들어야 한다. 예를 들면, 같은 lodash를 사용하더라도 semvar에 따라 각각의 패키지를 설치해야 한다.

pnpm은 이러한 이유 때문에, 같은 방법으로 종속 관계를 해결하는 yarn은 npm보다 조금 더 나아졌을 뿐이라고 한다.

pnpm은 yarn처럼 모든 종속을 위로 올려서 플랫하게 만들지 않는다. npm@~2의 방식을 사용하되, 각 패키지(및 버전)별로 격리된 공간 내에서 플랫하게 만든 뒤, 이를 심링크로 연결한다.

사용할 수 있을까?

사용 해 보니 확실히 패키지를 설치하는 속도가 빠르다. 특히 재설치할 때, yarn과 비교해도 빠른 느낌이다. 그런데 지금 운영하는 블로그는 pnpm으로 설치하면 작동하지 않는다. yarn에서는 잘 되지만, pnpm install을 실행하고 나면 몇몇 패키지가 없다고 뜬다.

정확히는, yarn은 플랫한 구조를 만들기 때문에 작동하는 것이고, pnpm은 그렇지 않기 때문에 발생한다. pnpm을 사용했을 때 yarn처럼 작동하기 위해서는 —shamefully-hoist 플래그를 사용해서 설치해야 한다. 그 외에는 누락된 패키지를 직접 설치하거나, pnpm 훅을 작성해서 해결하는 방법이 있긴 하다.

그래서, 당장 rush를 사용하여 모노레포를 구축할 계획이 없다면, 계속 yarn을 사용해도 될 것 같다. npm에서 yarn으로 넘어갈 때와 달리, 별도로 수정해야 하는 부분도 있기 때문에 현업보다는 개인 프로젝트에 시도 해 보는 것을 추천한다.

이찬희

프론트엔드 엔지니어 이찬희 입니다. 리액트와 타입스크립트를 주로 사용합니다. 현재 당근에서 재직중입니다.

© 2023 iamchanii