JS 패키지 매니저

안녕하세요, 헥토데이터 서비스 개발팀 Jetty입니다. 자바스크립트로 개발을 시작하면서 패키지 관리 도구에 대해 알고 사용을 해봤을 겁니다! 가장 많이 쓰이고 있는 npm, Yarn Berry 그리고 pnpm 등 다양한 도구들이 있는데요, 이 도구들은 우리의 개발 라이프를🌈  편리하게 만들어줍니다.

그런데 이 도구들의 차이점은 무엇일까요?  이 글에서는 JavaScript로 개발할 때 사용되는 패키지 관리 도구들에 대해 살펴보고, 어떤 것을 선택하는게 좋을지 알아보겠습니다.

🧐 패키지 매니저란?

패키지 매니저를 소개하기에 앞서 패키지 매니저가 생겨나기 전 상황에 대해 알아보겠습니다.

먼저 이전에 글에서 자바스크립트 모듈에 대한 내용을 담은 글을 담은적이 있었는데요, 혹시 아직 자바스크립트 모듈에 관련하여 잘 모르시겠다면 아래의 글을 읽어 보시는 걸 추천합니다!

💡 자바스크립트의 모듈 시스템의 배경 부분을 참고하시면 좋을 것 같습니다.

Bonjour, Vite! (Vite 실무 적용기)

간단히 말하자면, 자바스크립트 모듈이 등장하면서 여러 모듈을 조합하여 개발하는 것이 보다 일반적이 되었고, 이로 인해 모듈 관리의 어려움이 증가했습니다. 이런 상황에서 패키지 매니저인 npm이 등장하여 여러 모듈을 관리하고 배포할 수 있게 되었습니다.

📑 패키지 관리자의 주요 역할

  • metadata 작성 및 관리
  • 모든 dependencies 일괄 설치 또는 업데이트
  • dependencies 추가, 업데이트, 삭제
  • 스크립트 실행
  • 패키지 publish
  • 보안 검사

🫡 패키지 관리자 3대장 (npm, yarn berry, pnpm)

🐞 npm

npm은 가장 초기에 나온 패키지관리자로 Node.js의 기본 패키지관리자입니다.

특징:

  1. 가장 많이 사용되고 있으며 방대한 패키지 저장소를 호스팅하여 개발자에게 다양한 선택권을 제공한다.
  2. Node.js에서 제공하는 기본으로  패키지 관리자이기 별도의 설치가 필요없다.
  3. 버전 잠금 파일의 제공한다. (package-lock.json)

차이점:

  1. node_modules에 패키지들이 같은 레벨에 flat하게 들어있어 종속성에 문제가 발생할 수 있다. (유령의존성)
  2. 순차적 패키지 설치로 속도가 느릴 수 있다.
  3. 과거에 보안문제가 있었지만 현재는 보안문제에 신경을 써서 내부 알고리즘을 적용하여 보안을 강화 하였다고 한다.

👻유령의존성이란?

  • NPM 및 Yarn v1에서는 중복해서 설치되는 node_modules를 아끼기 위해 끌어올리기(Hoisting) 기법을 사용합니다.
  • 직접 의존하고 있지 않은 라이브러리를 require() 할 수 있는 현상을 유령 의존성(Phantom Dependency)이라고 부릅니다.
  • 즉 package.json에 직접 선언되지않은 패키지에 접근하여 불러와지는게 가능해집니다. 이러한 시스템은 의존성 관리 시스템을 혼란스럽게 만듭니다.

🐳 yarn berry

다음으로 소개할 yarn berry는 기존의 yarn classic 버전의 업데이트가 중지되면서 새롭게 출시된 버전입니다.

특징:

  1. 병렬적 패키지 설치로 속도가 빠르다.(yarn classic)
  2. zero-install을 제공하는 plug’n’Play (Pnp) 모드를 제공하여 install 과정을 생략한다.
  3. 패키지를 압축하고 저장하여 관리함으로써 다운로드 및 캐시 성능을 향상시켰음
  4. 유령 의존성 문제를 해결하였음

차이점:

  1. yarn berry는 기존의 classic 버전과 호환성을 보장하지 않을 수 있어 기존 프로젝트를 업그레이드 할때 일부 문제가 생길 수 있음
  2. zero-install로 버전 관리에 포함해야 하는 파일 수가 많다 보니 commit 시간이 지연 될 수 있으며,  Pull Request 내 diff가 길어질 수 있음 (확인필요)

Plug ‘n’ Play 모드?

Plug'n'Play는 yarn berry가 제공하는 새로운 패키지 관리 시스템이다.

기존의 무거웠던 node_modules 대신, 패키지들에 대한 정보는 .zip 파일로 압축하여 .yarn 폴더 아래에 보관하게 됩니다.

yarn 2버전 이상부터는 pnp 모드를 기본으로 하며 yarn을 실행하면 pnp.cjs라는 파일이 생성 됩니다.

아래의 예시와 같이 pnp.cjs는 지도와 같은 역할로 패키지, 버전, 위치, 의존성 등의 정보가 담기게된다.

/* react 패키지 중에서 */
["react", [
  /* npm:17.0.1 버전 */
  ["npm:17.0.1", {
    /* 이 위치에 있음 */
    "packageLocation": "./.yarn/cache/react-npm-17.0.1-98658812fc-a76d86ec97.zip/node_modules/react/",
    /* 이 의존성들을 참조한다. */
    "packageDependencies": [
      ["loose-envify", "npm:1.4.0"],
      ["object-assign", "npm:4.1.1"]
    ],
  }]
]],

패키지의 위치를 정확히 알 수 있기 때문에 시간도 단축되고, 중복 설치를 방지하며, node_modules를 만들고 패키지들을 호이스팅시킬 필요가 없는 Plug'n'Play의 특성 덕분에 유령 의존성 문제를 해결할 수 있습니다.

🐝  Pnpm

특징:

  1. npm과 달리 pnpm은 심볼릭 링크를 사용하여 패키지를 저장하고 가상의 중복된 패키지를 설치하지 않아 저장 공간과 네트워크를 절약할 수 있다.
  2. 새 버전이 나올 때 전체 패키지를 복사하는 대신 변경된 파일만 저장소에 추가하여 디스크를 효율적으로 사용.
  3. 전체 패키지를 다시 복사하는 대신 변경된 파일만 저장소에 추가하기 때문에 패키지를 업데이트할 때 속도가 빠르다.

차이점:

  1. 최근 pnp모드를 지원하지만 아직 zero-install 기능은 불가능함
  2. pnpm은 npm이나 yarn에 비해 상대적으로 새로운 패키지 매니저이며, 아직까지 개발 및 커뮤니티 지원이 부족 할 수 있음. (에러 발생시 대응)

node_modules 폴더아래에 생긴 .pnpm의 심볼링 링크가 저장되어있음

Cotent-addressable 저장소

pnpm은 의존성을 content-addressable 저장소에 저장합니다. 이는 같은 버전의 의존성을 여러 프로젝트에서 공유할 수 있도록 해줍니다. 새로운 버전이 나올 때 저장소에 변경된 파일만 추가됩니다.

정리

확실히 Yarn Berry와 Pnpm이 npm의 한계를 극복하고 발전된 것을 느꼈습니다. npm은 리소스 사용이 간편하고 문제 해결이 비교적 쉽겠지만, 성능 측면에서는 Yarn과 Pnpm을 사용하는 것이 더 효율적인 것 같습니다.

특히 배포 속도나 커뮤니티의 규모를 고려한다면 Yarn을 선택하는 것이 좋을 것으로 생각됩니다.여러 프로젝틍에서 공통으로 사용되는 패키지가 많다면 pnpm을 사용하는 것도 좋은선택 일 것 같습니다.

하지만, 실제 프로젝트에 적용하려면 기존의 잘못된 종속성을 찾아내어 마이그레이션 하는데 조금의 시간이 들 수도있다고  공식문서에도 나와있어 이런점을 고려하여 비교적 규모가 작은 프로젝트부터 마이그레이션 해보는 것을 추천합니다!

헥토데이터는 데이터 기반 다양한 서비스를 지원하는 기업입니다. 온라인에 분산된 데이터를 실시간으로 제공하기 위해 클라이언트 엔진과 웹 API를 활용합니다. 유수의 비대면 대출 핀테크 서비스가 선택한 헥토데이터의 CODEF API. 꼼꼼한 보안과 빠른 대응으로 기업이 자사 서비스에만 집중할 수 있도록 돕는 CODEF API에 대해 아래 배너를 눌러 확인해 보세요.

본 페이지 내의 모든 콘텐츠는 저작권법에 의해 보호받는 저작물로서, 모든 사용 권리는 ㈜헥토데이터에게 있습니다. 별도의 저작권 표시 없이 무단으로 사용하는 것을 금지하며, 자세한 저작권 정책은 해당 링크를 참고하시기 바랍니다. Copyright 2024.㈜헥토데이터 All rights reserved.