패키지 매니저란?
💡 자바스크립트 프로젝트에서 사용되는 의존성 관리 도구입니다
- 패키지 매니저는 프로젝트에 필요한 외부 라이브러리, 모듈, 플러그인 등을 손쉽게 설치하고 관리하는 역할을 합니다
패키지 매니저의 역할
- 패키지 설치
npm install react@latest
- 패키지 매니저를 사용하여 프로젝트에 필요한 패키지를 설치할 수 있습니다. 패키지는 일반적으로 오픈소스 라이브러리이며, 패키지 매니저를 통해 패키지의 이름 또는 버전을 지정하여 설치할 수 있습니다.
- 버전 관리
npm install react@18.0.5
- 패키지 매니저는 패키지의 다양한 버전을 관리합니다. 이를 통해 특정 버전의 패키지를 설치하거나 업데이트 할 수 있으며, 프로젝트가 정확한 버전의 패키지를 사용하도록 보장할 수 있습니다.
- 스크립트 실행
아래와 같이 package.json에 script 내용을 입력하고, 패키지매니저를 활용해 해당 스크립트를 실행시킬 수 있습니다.npm start
- { "name": "moyeota-webview", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite --host", "build": "tsc && vite build", "preview": "vite preview", "svgr": "npx @svgr/cli -d src/assets/svg --ignore-existing --typescript --no-dimensions public/svg" }, }
- 패키지 매니저는 프로젝트에 미리 정의된 스크립트를 실행하는 기능을 제공합니다. 이를 통해 프로젝트 빌드, 실행, 테스트, 배포 등 자동화된 작업을 수행할 수 있습니다.
패키지 매니저가 동작하는 세 단계
Resolution 단계
- 라이브러리 버전 고정
- package.json 파일에 명시된 버전 범위에 따라 정확한 버전을 결정합니다.
- 예를 들어, “react: ^18.2.0” 이라고 명시되어 있으면, ^이 나타내는 규칙에 따라 ≥ 18.2.0, <19 사이의 어떤 버전이든 사용할 수 있습니다.
- 패키지 매니저는 저 범위를 만족하는 선에서 가능한 최신 버전을 사용하려고 합니다.
- 즉, 최신 버전인 18.3.1을 선택할 수 있습니다.
- 라이브러리의 다른 의존성 확인
- 예를 들어서, @toss/use-overlay 는 react 를 사용합니다.
- 그런데 react도 의존성을 가지고 있습니다. 그래서 의존성이 또 어떤 의존성을 가지는지 확인하는 작업이 필요합니다.
- 라이브러리의 다른 의존성 버전 고정
- 마지막으로 그 의존성의 버전도 고정해야 합니다.
- JavaScript에서는 위와 같이 의존성의 버전을 범위로 명시하고, 패키지 간에도 의존성을 가지기 때문에, 똑같은 package.json에 대해서도 사용하는 의존성 버전이 완전히 달라질 수 있습니다.
- 예를 들어 어떤 기기에서는 Next.js 13.1 버전과 React 18.1.0 버전을 사용하고, 다른 기기에서는 Next.js 13.2, React 18.2.0 을 사용할 수 있습니다.제 PC에서는 잘 돼요 라고 하는 상황이 이럴 때 생깁니다.
- 이러한 의존성 고정 문제를 전부 해결하는 것이 Resolution 단계입니다.
- 사실 버전마다 동일한 동작을 하면 너무 좋겠지만 그럴순 없고, 이에 따른 버그가 생길 수도 있습니다.
<aside> 💡 Resolution 단계는 모든 기기에서 고정된 버전을 사용할 수 있도록 의존성 버전을 전부 고정시키고, 의존성의 의존성을 다 찾아 그 버전도 고정시키며, 결과물을 package-lock.json 혹은 yarn.lock에 저장합니다.
</aside>
Fetch 단계
- 결정된 버전의 파일을 다운로드 하는 과정
- Resolution의 결과로 결정된 버전을 실제로 다운로드하는 과정입니다. package-lock.json에 명시된 패키지를 네트워크를 통해 파일들을 가져옵니다. 이 과정을 Fetch 단계라고 합니다.
- 일반적으로 99% npm 레지스트리에서 다 받아옵니다.
Link 단계
- Resolution/Fetch 된 라이브러리를 소스 코드에서 사용할 수 있는 환경을 제공하는 과정
npm Linker
- npm Linker은 node_modules 기반의 Linker입니다. 우리에게 가장 익숙한 Linker 이기도 합니다.
- npm Linker은 package.json에 명시하는 모든 의존성읠 node_modules 디렉토리 밑에다가 하나하나씩 쓰는 것이 npm Linker의 역할입니다.
- 예를 들어만일 TDS 모바일 패키지에도 node_modules가 있다면 @radix-ui/dialog를 또 그 밑에 깔아주는 게 npm Linker가 하는 일입니다.
- 소스 코드에서 React와 TDS 모바일 라이브러리를 사용한다면, my-service의 node_modules 하위의 React와 TDS 모바일 패키지를 추가합니다.
- 단점
- 패키지를 찾으려고 하면 node_modules를 계속 타고 올라가면서 파일을 여러 번 읽어야 합니다.
- 그래서 import나 require 하는 속도가 느려집니다. 또한 디렉토리의 크기도 너무 커집니다. 실제로 파일 시스템에서 디렉토리와 파일을 하나하나 만들고 쓰기 때문입니다.
- 만일 100개의 프로젝트에서 React 18.2.0 버전을 쓴다고 한다면, 정말 100번씩 React 18.2.0이 추가되는 것입니다. 그래서 호이스팅이라는 방법을 쓰기도 하지만, 최적화가 완전히 되는 것도 아니고 불안정하기도 해서 좋은 방법은 아닙니다.
- 이렇게 파일 구조를 호이스팅 할 경우, 나는 설치한 적이 없지만 사용하는 패키지가 의존하고있다는 이유만으로 사용하지 않느 패키지도 설치하게 됩니다. 이러한 현상을 유령 의존성이라고 합니다.
pnpm Linker
- 이러한 단점으로 인해 pnpm이 만들어졌습니다. performanted npm 이라고 이해하시면 됩니다.
- npm의 문제인 node_modules를 하나씩 쓰는 것 때문에 느리고, 용량도 많이 차지하는 것을 개선한 패키지 매니저입니다.
- 어떻게?
- pnpm Linker은 기존의 node_modules 디렉토리를 그대로 사용합니다. 대신 보다 빠르고, 용량을 최적화하는 방식으로 사용합니다.
- Hard link 방식 덕분인데, 쉽게 말해 alias를 걸어주는 것입니다. npm처럼 단순히 복붙만 하는 거이 아닌, alias가 생기면 바로 거기에 접근하는 것입니다.
- 그래서 의존성이 디스크 하나만 설치가 됩니다.
- node_modules를 쓸 때도 파일을 하나하나 쓸 필요가 없어지고, 속도도 훨씬 빠릅니다.
- node_modules 디렉토리의 크기 또한 무척 작아집니다. 뒤에 나오는 PnP보다 약간 느리지만, npm처럼 파일을 하나씩 쓰는 것은 아니기 때문에 훨씬 빠르고, 호환성 또한 좋습니다.
- 단점
- node_modules 디렉토리는 그대로 유지하기 때문에 require, imoort 시 파일 읽기가 많이 발생해서 중간중간 멈추기도 합니다.
Yarn Classic
- npm이 가지고 있던 일관성, 보안, 성능 문제를 해결하기 위해 나온 패키지 매니저입니다.
- npm기반으로 프로세스를 설계하였고, 당시 문제점 중 하나였떤 설치 프로세스의 속도를 높이기 위해 작업을 병렬화하였습니다.
PnP Linker (Yarn berry)
- node_modules 디렉토리를 벗어난 패키지 매니저, node_modules 없이 의존성을 처리하는 방법입니다.
- PnP는 패키지를 import 할 때 중요한 것은 단 두 가지 라는 관점에서 접근합니다.
- “어떤 파일”에서 import 하는가, 그리고 “무엇”을 import 하는가
- 즉, 앞의 npm과 pnpm처럼 node_modules를 순회하는 것이 중요하지 않다고 생각한 것입니다.
- 그래서 node_modules 디렉토리가 아닌 Javascript 객체로 똑똑하게 처리합니다.
- PnP는 JavaScript Map으로 관리합니다. 따라서 Yarn을 실행하는 순간 Node.js 프로세스가 이 PnP Map을 메모리에 전부 로드하고, import와 require문에서 이 Map을 참조합니다.
- 장점
- 설치 속도가 빠릅니다. yarn.lock 기반으로 .pnp.cjs 파일만 만들어서 쓰면 끝납니다.
- 파일 하나만 쓰기 때문에 설치 속도는 빨라지고, 그러니 import, require하는 속도도 빠릅니다.
- node_modules 디렉토리를 순회할 필요도 없기 때문에 파일 설치 속도가 빨라집니다. 그러나 pnp는 Node.js 프로세스가 뜨는 속도가 느리고, node_modules 디렉토리와의 호환성이 낮습니다.
'⚓️ 개발환경' 카테고리의 다른 글
[⚓️Webpack] Webpack 커스터마이징을 통해 Vite 속도 따라잡기 (1) | 2025.03.12 |
---|---|
[⚓️Webpack] CRA 없이 웹팩 프로젝트 만들기 | 웹팩의 시대는 끝났나 ? | 웹팩 커스터마이징 (0) | 2025.03.11 |
[⚓️개발환경] 바벨이란 무엇인가? (2) | 2024.08.12 |
[⚓️개발환경] 웹팩이란 무엇인가 (6) | 2024.07.08 |
[⚓️개발환경] 프론트엔드 개발에 Node.js가 필요한 이유 (8) | 2024.06.25 |