본문 바로가기
etc

패키지 매니저 npm, yarn, pnpm 비교해보기

by 최인호호 2023. 3. 13.
반응형

개요

요즘 프론트엔드 monorepo에 관심이 생겨, 공부를 하는 중 패키지 매니저에 대해서 상세히 알고 넘어가면 좋을 것 같아서 이에 대해 작생해보고자 한다.

먼저, 프론트엔드 모노레포를 구성하기 위해서 요즘 관심있게 보는 기술이 Vercel에서 인수한 Turbo Repo 이다.

Turbo Repo의 공식문서에서는 패키지 매니저를 pnpm을 사용하기를 권장하고 있는데, 처음에 보았을 때 pnpm이 뭐지? 라고 생각이 들었다.

내가 알고 있는 패키지 매니저는 보편적으로 사용하고 있는 npm과, yarn 정도 뿐이였다.

하지만 npm과 yarn에 대해서도 자세히 어떠한 차이가 있는지 몰랐다.

그래서 이번 글에서는 모노레포에 대해서 다루지 않을 것이고 패키지 매니저에 대해서만 알아보도록 할 것이다.

모노레포에 대해서는 추 후에 작성 해 볼 것 이다.

패키지 매니저란?

Package Manager (패키지 매니저)란 정의를 하면 다음과 같다.

개발에 필요한 패키지를 설치, 업데이트, 수정 삭제 하는 작업을 편리하고 안전하게 수행하기 위해 사용 되는 도구라고 정의 할 수 있다.

Javascript로 개발을 하다보면 프로젝트내에서 사용하는 패키지가 많을 것인데, 이러한 패키지들을 쉽게 설치 및 관리하고 서로간의 의존성을 관리해주는 도구가 패키지 매니저 이다.

패키지 매니저를 사용하는 방법은 약간의 차이들이 있지만, 중요한 컨셉은 비슷하고 다음과 같은 주요 기능을 수행한다.

  • 모든 의존성을 일괄 설치 또는 업데이트
  • 의존성 추가 및 업데이트, 제거
  • 스크립트 실행
  • 패키지 배포
  • 등등

이렇게 패키지 매니저에 대해서 간단하게 정의 해 보았다.

그렇다면 자바스크립트의 패키지 매니저인 npm, yarn, pnpm에 대해서 조금 더 자세히 알아보도록 하자.

1. NPM

images

npm은 2010년에 만들어졌으며, 자바스크립트의 패키지 매니저의 선구자라고 이야기 할 수 있다.

2010년 이전에는 프로젝트의 의존성은 수동으로 다운로드하고 관리되었기 때문에 npm의 등장은 혁명적이였다고 할 수 있다.
메타 데이터 필드가 포함된 package.json 파일, node_modules에 의존성 저장, 사용자 지정 스크립트, 공용 및 개인 패키지 레지스트리 등의 모든 개념은 npm에 의해 도입 되었다.

이러한 npm은 현재까지도 많은 개발자들이 가장 널리 사용하고 있다.

다음 이미지는, google trends로 자바스크립트의 대표적인 패키지 매니저로 비교하여, 관심도에 따른 비교 그래프이다.

images

위와 같이 npm은 아직까지도 널리 이용되고 있는것을 확인할 수 있다.

이러한 npm의 탄생은 혁명적인것은 분명하지만 모든 개발자들에게 만족감을 줄 수는 없다.
그 문제중 하나가 의존성 지옥 이다.

Dependency Hell (의존성 지옥) 에 대해서 npm의 공식문서를 보면 더 자세히 알 수 있다. NPM 문서 참고

만약 A, B, C라는 세가지 모듈이 있고,
A는 B의 v1.0이 필요하고 C는 B의 v2.0를 필요한다고 생각해보자.

images

이제 모듈 A와 C가 모두 필요한 프로젝트를 만들어 볼 것 이다.

images

그렇다면, 패키지 관리자는 모듈 B의 어떤 버전을 가져와야 할까?

이러한 문제가 바로 의존성 지옥이다.

여기서 의존성 지옥을 npm2와 npm3가 해결해준다.

npm2

의존성 지옥을 해결하기 위해 npm2는 다음과 같이 의존성을 관리한다.

images

위 이미지와 같이 B 모듈은 각각의 버전을 모두 트리에 넣는 방식이다. 하지만 이러한 방식은 중복으로 생기는 모듈이 생길 수 있다. 만약에 D라는 패키지가 B v1.0을 필요로 할때, A에서도 아래에 두게 되고, D에서도 동일한 모듈을 두게 된다.

npm3

npm3에서는 npm2와 다르게 동작한다.
위 설명과 같이 npm2는 중첩된 방식으로 모든 종속성을 설치하지만, npm3는 이러한 중첩으로 인해 발생하는 깊은 트리와 중복성을 완화 하려고 시도 하였다.

images

위 이미지와 같이 npm3는 모든 모듈을 트리의 높이를 깊게 두는 것이 아닌, 평평하게 둔다. 하지만 이미 설치한 모듈의 다른 버전이 새롭게 필요하다면 해당 모듈을 필요로 하는 상위 모듈 아래에 두는 방식이다.

이 방식은 모듈이 어떤 순서로 설치 하는가에 따라 의존성 구조가 달라지는 문제가 발생하고, 이 외에도 npm은 보안의 위험이 있다.

이러한 문제들로 인하여 yarn이라는 패키지 매니저가 나오게 되었다.

2. yarn

images

yarn은 npm을 사용하는 개발자들이, 프로젝트의 규모가 커질수록 일관성, 보안 성능의 문제를 해결하고자 페이스북, 구글, Exponent(현재의 Expo.dev), Tilde(Ember.js)에서 협업하여, 개발 되었다.

npm과의 비교되는 기능은 다음과 같다.

  • yarn은 로컬 캐시로부터 패키지를 설치할 수 있다.
  • yarn은 패키지 버전을 강력하게 바인딩한다.
  • yarn은 데이터 무결성 보장을 위해 체크섬을 사용하는 반면 npm은 SHA-512를 사용하여 - 다운로드된 패키지의 데이터 무결성을 검사한다.
  • yarn은 병렬로 패키지를 설치하는 반면 npm은 한 번에 하나의 패키지를 설치한다.

당시 npm과 비교하여 yarn의 가장 큰 강점은 yarn.lock파일을 통해 패키지 버전 잠금을 지원하는 것이였다.

npm에서는 동일한 모듈에 대해서 각각의 버전을 설치하기에, 이는 모듈에 대해서 일관성도 떨어질 뿐만 아니라, 모듈의 설치 순서에 따라서 의존성 구조가 달라지는 문제가 발생한다고 했었다.

이를 위해, yarn은 lock파일을 자동으로 생성하고, 의존 모듈들을 순서대로 적어 놓고, 특정 버전만 설치가 가능하게 해, 의존하는 모든 패키지를 어느 환경에서든 동일한 버전으로 의존성을 가지도록 하였다.

이러하여 yarn.lock 파일은 npm에서 발생하였던, 일관성 및 보안문제를 해결 할 수 있게 되었다.

또한, yarn은 npm과 달리, 패키지를 가져와서 설치 할 때 병렬적으로 설치를 한다. 만약 여러개의 패키지를 설치할때 npm은 순차적으로 설치를 하게 되지만 yarn은 병렬적으로 설치를 하게 되어 훨씬 빠르게 설치를 할 수 있게 된다.

이렇게 병렬적으로 설치하는 부분은 npm보다 성능적인 문제도 해결하게 되었다.

3. pnpm

images

yarn은 npm에 대해 좋은 대체자 였지만, 두 패키지 매니저는 주요 문제가 있었다.

그 문제는 프로젝트 전체에서 사용되는 의존성의 중복된 저장소를 가지는 것 이였다.

극단적으로 예를 들어 100개의 React로 구성된 프로젝트가 있다고 가정 하였을 때, npm 이나 yarn으로 패키지 매니징을 할 경우에 100개 프로젝트 내부에 node_modules 에 flat하게 패키지를 설치하여 관리 하게 된다.

이는, 동일한 패키지 일 경우에 똑같은 라이브러리가 100개 만큼 중복적으로 설치를 하게 되는 것이다.

위와 같은 문제로 yarn에 실망한, Zoltan Kochan이라는 개발자가 2017년에 pnpm을 공개하게 되었다.

pnpm은 npm과 yarn과 달리, 여러 프로젝트에서 여러개의 중복적인 패키지를 설치하는 것이 아닌, 하나의 패키지를 가지고 여러 프로젝트로 hard link를 하기 때문에, 훨씬 효율 적이며 속도도 빠르고 공간도 훨씬 덜 차지하게 된다.

이에 대해 조금 더 자세히 알아보자.

pnpm은 호이스팅 대신 의존성 해결 전략의 대안책으로 content-addressable storage를 도입 하였다.

이 방식을 사용하면 home 폴더의 글로벌 저장소 ("~/.pnpm-store") 에 패키지를 저장하는 중첩된 node_modules 폴더가 생성된다. 따라서 의존성의 모든 버전은 해당 폴더에 물리적으로 한 번만 저장되어 단일 정보 소스를 구성하고 상당한 디스크 공간을 절약할 수 있다.

이는 node_modules 레이아웃을 통해 달성되고, 심볼릭 링크를 사용하여 의존성의 중첩 구조를 생성한다. 여기서 폴더 내의 모든 패키지의 모든 파일은 저장소에 대한 hard link로 구성 되어 있다.

images

마치며

우리가 개발하면서 주로 사용하는 패키지 매니저인 npm 및 yarn 에 대해서 조금 자세히 알아 보았고, 나아가 패키지를 조금 더 효율적으로 관리하기 위한 pnpm에 대해서 알아보았다.

이제는 패키지 매니저에 대해서 조금 더 자세히 알게 되었고, 또한 패키지 매니지의 종류들이 어떠한 차이가 있는지를 알고 사용할 수 있을 것 같다. 또한 패키지를 설치하고 의존성을 어떻게 띄고 있는지에 대해서도 이해를 하게 되었다.

참고

https://npm.github.io/how-npm-works-docs/theory-and-design/dependency-hell.html
https://pnpm.io/ko/motivation
https://doppelmutzi.github.io/packageManagers/

반응형

댓글