Flab 과정을 들으면서 멘토님이 나에게 패키지 매니저에 대해 질문했는데 제대로 답을 하지 못했었다..;;
써보기만 했지 그것의 개념들은 잘 알지 못한 상황이어서 멘토님께서 공부하기 좋은 아티클들을 주셨다. 해당 아티클을 보고 정리한 내용들을 블로그에 작성해보려고 한다! 밑에 참고한 아티클의 링크를 작성해놓았습니다.
1. 패키지 매니저란?
import axios from 'axios'
위의 코드를 작성했을 때 패키지 매니저는 axios라는 패키지를 올바르게 참조할 수 있도록 포장해주는 프로그램.
비유하자면 내가 만약 샌드위치(= 개발)를 만들고 싶은데 다양한 재료(=react, axios 같은 패키지 & 라이브러리) 가 필요함.
근데 어떤 재료가 필요한지 대신 사다주는 도우미(= 매니저)같은 것.
JavaScript 표준인 ECMAScript ⇒ 정확한 절대 경로 or 상대 경로로 import 할 수 있지만
간단하게 사용하고 싶다면??
import React from 'react';
import { sum } from '@toss/utils';
하지만 어떤 버전을 사용할건지 명시하지 않아 모호함.
때문에 package.json파일에 사용할 버전을 명시하는 것이다!
=> 그리고 npm install, yarn install을 할때 명시된 버전을 설치하게 되는것.
비유하자면 package.json은 장바구니 메모지 같은 것.
1.1 패키지 매니저가 동작하는 세가지 단계
(1) Resolution
(2) Fetch
(3) Link
⇒ 위 세 단계로 패키지 매니저는 동작함.
(1) Resolution
- 라이브러리 버전 고정
- 라이브러리의 다른 의존성 확인
- 라이브러리의 다른 의존성 버전 고정
⇒ 어떤 버전의 라이브러리를 사용할지 명확하게 정하는 과정.
1. package.json에서 라이브러리 버전 확인
"dependencies": {
"react": "^18.2.0"
}
// React는 18.2.0 이상, 19.0.0 미만 이면 가능!
// 패키지매니저는 범위 안에서 가능한 최신버전 사용하려고함.
2. 의존성의 의존성 문제
패키지끼리 의존성을 갖는 상황 ⇒ 패키지 간 의존성, 그리고 또다른 의존성을 갖는지 추적
3. 의존성의 버전 고정
ex )
- A 개발자의 PC에는 React 18.1.0
- B 개발자의 PC에는 React 18.2.0
→ "내 PC에선 잘 돼요" 현상 발생
따라서 모든 버전 결정 결과를 기록하는것이 필요
= yarn.lock, package-lock.json에 저장
(2) Fetch
- 결정된 버전의 파일을 다운로드 하는 과정
Resolution 결과로 결정된 버전을 다운로드하는 과정
→ yarn.lock에 명시된 패키지들
네트워크를 통해 필요한 파일들을 가져옴. (= Fetch)
(3) Link 단계
- Resolution/Fetch 된 라이브러리를 소스 코드에서 사용할 수 있는 환경을 제공하는 과
- 실제로 import/ require 구문을 사용하는 환경
아래의 사례를 통해 Link 단계 이해해보자!
- npm Linker (npm의 의존성 설치 방식)
- node_modules에 의존성(패키지들)을 직접 하나하나 넣는 방식
- If 패키지들이 또다른 패키지를 갖고 있음 → 그 안에 또 node_modules 만들어서 넣음.
- 계속 폴더 속에 폴더 , 반복 구조임.
my-service/
└─ node_modules/
| ├─ react/ <-- 1단계 의존성
| |
| └─ @tossteam/tds-mobile/ <-- 1단계 의존성
| └─ node_modules/
| └─ @radix-ui/react-dialog <-- 2단계 의존성
|
└─ src
└─ index.ts
위 방식의 문제점
- 찾기 느림.
- 폴더의 계층이 많아질수록 import/require 속도가 느려짐.
- 호이스팅을 사용한다해도 완전한 최적화를 기대하기 어려
2. pnpm Linker (pnpm의 의존성 설치 방식)
위 단점들을 개선하기 위해 만들어짐. (fast, disk space efficient 한 패키지 매니저)
Q. 어떻게 위 문제점을 개선했는지?
A. Hard Link , 파일 복사 대신 별칭을 만들어 연결만 해주는 방식으로 개선
⇒ But 기존 node_module 디렉토리 그대로 사용
그래서 대신 빠르고 용량최적화를 위해 Hard Link 방식(=별칭 alias 사용) 사용함.
비유하자면 아래와 같음.
npm 방식 (개인 창고)
각 집마다 같은 우유 따로따로 사서 냉장고 보관
pnpm 방식 (공유창고)
우유를 공유 창고에 1개만 두고 각 집에 “여기서 가져다 써” 라고 이름표 붙임
store/
└─ react@18.2.0/
my-project/node_modules/
└─ react → 📦 store/react@18.2.0 (하드 링크)
npm과 비교했을때 node_module이 같은 구조이지만 파일을 하나씩 복붙하지 않기때문에 속도는 빠르게 느껴짐.
3. PnP(Plug'n'Play)
node_modules 디렉토리 없이 의존성 처리!
PnP에서 패키지 import 할때 중요한 점
- “어떤 파일”에서 import하는지
- “무엇”을 import하는지
⇒ 명확한 타케팅, 더이상 node_modules 순회하는건 중요치 않음.
때문에 Javascript 객체로 처리
(1) yarn install 하고 난 후 .pnp.cjs 파일 생성
⇒ Javascript Map으로 의존성을 찾음.
["my-service", /* ... */ [{
// ./my-service에서...
"packageLocation": "./my-service/",
"packageDependencies": [
// React를 import 하면 18.2.0 버전을 제공하라.
["react", "npm:18.2.0"]
]
]
/* react 패키지 중에서 */
["react", [
/* npm:18.2.0 버전은 */
["npm:18.2.0", {
/* 이 위치에 있고 */
"packageLocation": "./.yarn/cache/react-npm-18.2.0-98658812fc-a76d86ec97.zip/node_modules/react/",
/* 이 의존성들을 참조한다. */
"packageDependencies": [
["loose-envify", "npm:1.4.0"]
],
}]
]],
(2) Node.js 프로세스, PnP Map 메모리에 로드
→ import, require 에서 Map 참조
yarn.lock 기반으로 파일만 만들면 되니 설치속도가 빨라짐.
메모리에 파일 로드 → Map 연산만 하면 끝 _ 디렉토리 순회할 필요 X
But 단점 존재..
- Node.js 프로세스 속도가 느림.
- node_modules 디렉토리와 호환성 낮음.
잠깐..! PnP 와 Zero-install의 차이
PnP
- 의존성 위지 정보를 Map 처럼 관리
- node_modules 없이 코드에서 import 하면 매핑 테이블에서 경로 찾아서 연결
- 해당 정보는 .pnp.cjs 파일에 저장.
⇒ 책방에 직접 가서 책 빌리는게 아니라 그냥 책 대여 어떤거 해야하는지만 보고 집에서 빌리는 느낌.
(1) 하나의 의존성만 설치되어 효율적, 속도향상, 용량적음.
하지만 .. 일부 툴들 (webpack, eslint) 과의 호환성 문제가 생길수 있음.
Zero-install
- yarn install 없이 바로 코드 실행할수있게 !
- 의존성 설치하고 그리고 그 결과물도 모두 저장 그리고 Git에 커밋
- 즉 협업자는 git clone만 해도 바로 실행 가능
npm, yarn도 사용 가능하지만 용량 부담이 큼..
but 레포 사이즈가 커지고 git 관리가 어려워 진다는 단점이 있음.
2. npm 정리
- Node.js의 기본 패키지 매니저, 최초의 패키지 매니저
- 폴더 구조
- node_modules에 의존성(패키지) 들이 폴더 트리 구조로 저장되어 있음.
- 같은 패키지가 중복 설치될수 있음.?
- 속도
- 구조상 속도가 많이 느림.
- 장점
- node.js 공식, 모든 환경에서 기본 지원
- 별다른 설정 없이 사용 가능
- 단점
- node_modules 폴더가 무거워지고 중복 저장이 많음.
- 대규모 프로젝트에서 설치/ 삭제/ 업데이트 속도가 느려질 수 있음.
3. yarn 정리
- Facebook이 개발, npm의 속도 & 안정성 문제를 해결하기 위해 만들어짐.
- 폴더 구조
- npm과 동일하게 node_modules 사용
- yarn berry(2.x)부터 PnP(Plug'n'Play) 방식 지원
- 속도
- npm 보다 빠른 설치 (병렬설치, 캐싱)
- 장점
- yarn.lock 파일로 정확한 버전 관리
- workspace, PnP 등 대형 프로젝트 지원.
- 단점
- 기본적으로 node_modules 구조는 npm과 비슷해서, 구조상의 한계가 있음.
- Yarn berry(PnP)는 도입하려면 세팅을 많이 해야하고, 호환성 이슈가 많음 (특히 구 라이브러리).
4. pnpm 정리
- node_modules의 비효율(용량, 속도, 중복) 해결을 위해 탄생.
- 폴더 구조
- Hard link 방식(→ 같은 패키지 여러 프로젝트에서 써도 디스크 하나만 차지)
- 패키지는 한번만 저장, 각 프로젝트는 "링크(바로가기)"만 만듦.
- 속도
- 빠르다는게 장점
- 디스크 적게 차지
Reference
https://toss.tech/article/lightning-talks-package-manager
패키지 매니저의 과거, 토스의 선택, 그리고 미래
토스는 왜 패키지 매니저로 Yarn을 선택했을까요? 이번 라이트닝 토크에서는 JavaScript의 패키지 매니저, 동작 방식, 그리고 토스의 선택과 앞으로의 방향성에 대해 이야기해 보려고 해요.
toss.tech
'공부 > 기술 개념 정리' 카테고리의 다른 글
| React 와 Vue 비교하기 (1) | 2026.01.29 |
|---|---|
| 단방향 vs 양방향 상태관리: React와 Vue의 핵심 차이 (0) | 2026.01.29 |
| 관심사 분리란? (SoC, separation of concerns) (0) | 2025.12.22 |
| OAuth 프로토콜 (7) | 2025.06.27 |
| Yarn Berry란? (1) | 2025.06.27 |