패키지 매니저 너 이자식 !

nerdchanii·2023년 3월 7일
8

packagemanager

목록 보기
1/1

???: 패키지 매니저로 npm을 사용하셨는데, 이유가 있을까요?

인턴 면접을 보았을 때 이야기 입니다. yarn이나 pnpm에 대해서 들어보았지만 아무런 고민없이 npm을 사용하고 있던 때였습니다. 저는 이 질문에 대답할 수 없었습니다. 왜냐하면 npm을 사용했던 명분이 없기 때문입니다.

(명분이 없다 아닙니까, 명분이.)

이떄부터 언제가 한번 정리는 해야지... 하고 있었지만 자꾸만 뒤로 미루게 되었습니다. 그래서 더이상 미루지 말고 정리하고 넘어가자는 생각에 살펴보게 되었습니다.

누구나 한번쯤 들어보았을 이야기

ex) 귀만 열고 숨만 셨는데 귓구멍으로 들어본 이야기들 모음.txt
- npm 구립니다. yarn berry 쓰세요. pnpm쓰세요🥸
- npm 은 루트에 다 짱박아서 안좋아요. 🙁
- npm 용량 겁내 잡아먹음 🫤
- yarn 짱임 캐시도 조흠 🤓
- pnpm 짱임 용량 덜먹음 🤩

npm이 구리다는 이야기를 가끔 들어본적이 있습니다. 정확한 이유는 모른채 이런 이야기만 들으니 실제로는 아는 것이 하나도 없으면서도, 안다고 오인지하고 있었습니다. 그래서 오늘은 npm의 역사에 대해서 알아보면 좋을 것 같더라구요.

npm은 왜 등장했을까?

npm 이전의 이야기

npm 이전은 어떤 상황이었을까요?

일단 package manager없이 개발을 해야한다는 말은 사용하고 싶은 패키지가 있다면, 직접 패키지 다운로드 받아서 설치해야한다는 뜻이었어요.

그러면, 패키지들의 의존성들은 어떻게...?

상상은 여러분에 몫에 맡기겠습니다. 혹시 궁금하신 분은 아래 레포를 참고해보세요!

package manager없이 백엔드 만들기


자 여기서 한가지 상황을 더 가정해보겠습니다. 저희가 진행하던 프로젝트의 한 패키지가 버전이 업데이트 되면서, 버전을 올려달라는 요구를 받았습니다.

???: A개발자님, 이번에 some-blabla와 'mix-blabla', 'ddo-blabla' 라이브러리가 스테이블 버전이 나와서 업데이트를 진행해주세요. 🙆🏻‍♂️

🤦🏻‍♂️ ...

자 어떻게 하면 좋을까요?

릴리즈노트를 비교해가면서 업데이트를 하고, 새로운 버전의 코드를 다운로드 받아 직접 기존 버전과 바꾸는 등의 작업을 하면 되겠지만...

사용중인 패키지들을 이렇게 빈번히 업데이트 된다면 어떨까요?
만약 의존중인 패키지 라이브러리의 개발자가 악성코드를 심어놓는다면... 쉽게 확인해낼 수 있을까요?


npm 이야기

이렇게 절망스럽던 상황에 있던 속에서 우리를 구원해줄 투수가 나타났습니다. 바로 npm입니다.

npm은 패키지 관리를 자동화시켰습니다. 그리고 우리를 이 수동업데이트로부터 해방시켜주었습니다. npm 덕분에 이제는 간단 명령으로 패키지 레지스트리에 등록된 패키지들을 사용할 수 있게 되었고, 의존성의 업데이트까지 처리할 수 있게 되었습니다.

  • 패키지 매니저: 패키지 관리, 하위종속성 관리
  • 패키지 레지스트리: 패키지와 패키지의 메타데이터를 저장

npm이 가지고 있던 문제들

npm은 자바스크릡트 패키지매니저의 선구자 답게 가장 먼저 패키지 매니저가 해결해야만 하는 문제에 직면했었습니다.

Dependency Hell 😈😈

  • 설치한 두 패키지가 같은 라이브러리를 의존할 때, 두 라이브러리의 버전이 다른 상황에서 생기는 문제

패키지 매니저는 패키지들간의 종속성을 관리했습니다. 하위 종속성을 관리하는데 있어서 발생하는 문제는 Dependency Hell이라는 문제가 있습니다. 이 의존성 지옥은 패키지를 설치해서 사용하는 다른 언어들에서도 유명해 'DLL Hell', 'jar Hell' 이라고도 부르기도합니다.

디테일한 설명은 여기를 참고하세요!

그러면...! nested 하면 되지 💡

npm은 dependency Hell 문제를 해결하기 위해 처음에는 중첩된(nested) 구조를 사용해 문제를 해결했습니다. 패키지안에 node_modules를 중첩시켜서 해결하는 방법이었습니다. 트리구조로 나타내면 다음과 같습니다.
참고

# 트리구조는 이렇게 됩니다.
$ my-app
  |-- package.json
  |-- myapp.js
  |-- node_modules
    |-- mod-a
      |-- node_modules
        |-- mod-c@v1
    |-- mod-b
      |-- node_modules
      	|-- mod-c@v2
중첩구조를 통해서 문제를 잘 해결하는 듯 했습니다. but... 다른 문제가 도사리고 있었습니다. ...

Windows의 path길이 제한 😯

window의 path길이제한으로 인해서 npm install을 수행할 수 없게 되었어요. 해당 이슈 참고

nested 멈춰! 평탄화 하자 ✋🏻

그래서 npm은 이 문제를 해결하기위해 평탄화된(flatten) node_modules 구조로 npm3에서 업데이트했습니다. 중첩은 한 라이브러리의 두 버전을 사용하게 될 때에만 중첩이 생기도록 만들었습니다. 이 방법을 통해서 path제한 문제를 해결하면서도, 의존성 지옥이나 의존성 충돌에 빠지지 않도록 구조를 잡을 수 있었습니다. 좀더 자세히 보고싶다면 여기를 참고하세요!

$myapp 
  |--package.json
  |--myapp.js
  |-node_modules // 해당 디렉토리의 
    |--mod-a
    |--mod-b
      |--node_modules
        |-mod-c@v2
    |--mode-c@v1

그 이후...

평탄화된 노드모듈을 구조로 릴리즈가 v3.0.0(2016-05-05)에서 릴리즈 되었습니다. 이때쯤 npm의 보안성과 포퍼먼스, 디스크 효율성등의 문제로 yarnpnpm이 등장하게 되었습니다.

yarn v1(classic)도 평탄화 된 구조를 선택했습니다.Yarn과 npm을 사용할 경우, node_modules가 평탄화되면서 패키지들의 호이스팅이 일어나게됩니다. 그러나, 호이스팅도 완벽한 해결책이 아니었습니다. 유령 의존성(Phantom Dependency)문제를 일으킬 수 있는 문제가 있기때문입니다.

  • 유령의존성: 직접 명시적으로 의존하지 않고 있는 라이브러리가 호이스팅으로 인해 프로그램에서 require혹은 import 할 수 있는 문제

다음이시간에...

다음 시간에는 yarn, pnpm을 살펴보고 npm@v3 이후의 npm 이야기들을 소개할 수 있는 시간을 마련해보겠습니다.

번외

  • npm은 node package manager가 맞지만 npm은 Node Package Manager의 약자가 아닙니다. 굳이 약어로 간주하고 싶다면, Node pm 혹은 New pm의 약어라고 보는게 맞다고 합니다.
  • pm(pkgmakeinst)은 bash 유틸에서 유래
    참고
profile
이해할 수 있을때까지 🏃🏻

0개의 댓글