라이브러리를 설치할 때 yarn add ~ , npm install ~ 를 항상 사용하면서 이 yarn과 npm이 무엇인지 제대로 모르고 있다는 생각이 문득 들었다.
그래서 yarn과 npm을 톺아보려고 했는데 "패키지 관리자"라는 말의 패키지가 무엇인지부터 이해가 되지 않았다.
그래서 yarn과 npm을 톺아보려다가 거슬러 올라간 과정에서 공부한 모든 것을 정리해보려고 한다.
보통 모듈을 레고 블럭, 패키지를 레고 블럭의 집합으로 정의한다.
Recoil에서 Recoil이 패키지라면, module이 useSetRecoilState이며 보통의 경우 패키지와 라이브러리가 엄격하게 구분되지 않을 수 있으니 이 경우에서는 Recoil이 패키지이자 라이브러리이다. (Recoil이라는 라이브러리 안에 Package가 하나만 있다고 생각해도 되겠다.)
모두 자바스크립트 런타임 환경 Node.js의 기본 패키지 관리자이며, node_modules에 모든 모듈을 저장한다.
참고로 node_modules에는 package.json에 명시된 모듈 뿐만 아니라 해당 모듈이 의존하고 있는 모듈까지 모두 들어가기 때문에 크기가 굉장히 큰 폴더가 된 것이다.
node.js 설치할 때 자동으로 설치됨
npm은 필수 단계를 순차적으로 수행하기 때문에 한 개의 패키지 다운로드 완료해야 다음 패키지를 다운로드 할 수 있음.
대표적인 명령어
병렬적으로 여러 패키지를 동시에 설치할 수 있고, 다운받은 패키지 데이터를 캐시(cache)에 저장하여, 중복된 데이터는 다운로드하지않고, 캐시에 저장된 파일을 활용함으로써 npm에 비해 패키지 설치속도가 매우 빠르다.
npm의 부족한 부분들을 개선하기 위해 Facebook에서 개발되었다.
대표적인 명령어
패키지들을 사용하기 위해서는 다운로드, 설치, 업데이트, 의존성 관리, 제거 등 복잡한 상황들이 많이 생기는데 패키지 매니저는 이러한 과정들을 자동화하여 편리하고 안전하게 수행할 수 있도록 해준다.
패키지 관리자가 하는 역할에는 크게 2가지가 있다.
//리액트 프로젝트에서 react-cookie를 사용하고 싶을 때 다음과 같이 설치했다.
yarn add react-cookie
npm install 모듈이름 -g
해당 코드를 이용하면 프로젝트마다 모듈을 설치할 필요없이 내 컴퓨터 안에 글로벌한 공간에 모듈을 설치해 프로젝트마다 같은 모듈을 공유해서 사용할 수 있다.
하지만
이에 대한 해결책으로 등장한 것이 npx이다.
모듈을 로컬에 저장하지 않고, 매번 최신 버전의 파일만을 임시로 불러와 실행 시킨 후에, 다시 그 파일은 없어지는 방식으로 모듈이 작동한다.
따라서 npx로 설치한 모듈의 경우 node_modules에 들어가지 않는다.
모듈의 변화가 많은 CRA와 같은 경우, npx로 모듈을 설치하고 실행하면 좋다.
Node.js는 설치하는 경우 npm이 같이 설치되는데 이를 통해 React 개발에 필요한 다양한 모듈들을 다운받아 사용할 수 있다.
그렇다면 npm만 설치하면 되지 왜 굳이 번거롭게 node.js를 통해 npm을 설치하는 것일까??
React는 클라이언트 기반 라이브러리기 때문에 npm만 설치하여도 React와 react-dom 라이브러리를 사용할 수 있다.
하지만 node.js가 있으면 바벨이라는 컴파일러 도구를 추가로 다운받아 자바스크립트 대신 JSX를 사용하는 것이 가능하기 때문이다.
Package.json은 개발자가 배포한 패키지에 대해, 다른 사람들이 관리하고 설치하기 쉽게 하기 위한 문서이다.
npm에 패키지를 배포하고 npm registry에 올리기 위해서 반드시 필요한 문서파일이다.
패키지 배포가 아닌 개발의 측면에서는,
해당 프로젝트가 어떤 라이브러리를 가지고 있어야 제대로 구동될 수 있는지 명시하고, 협업을 할 때와 같이 여러사람이 동시에 작업을 해야할 때, 팀 내에서 동일한 개발환경을 빠르게 구축할 수 있도록 해준다.
ex. yarn install을 통해 package.json에 나열된 모든 의존성 파일을 설치한다.
{
//✅ name : 패키지의 이름
"name": "my-app",
//✅ version : 패키지의 버전 (주로 범위로)
"version": "^0.1.0",
//✅ private : 패키지를 npm 레지스트리로 publish 할 수 없도록 하는 설정
"private": true,
//✅ dependencies : 배포 환경에서 필요한 패키지
"dependencies": {
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
},
//✅ scripts : 반복 작업을 수행할 때 실행해야하는 명령어를 미리 스크립트로 만들어 놓는 것
//✅ yarn start도 여기에 등록되어 있어 사용이 가능한 것
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
"packageManager": "yarn@3.3.1",
//✅ devDependencies : 로컬 개발 및 테스트에만 필요한 패키지
"devDependencies": {
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-react": "^1.1.7",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.11",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.8.1",
"webpack-cli": "3"
},
"msw": {
"workerDirectory": "public"
}
}
yarn.lock, package.lock.json과 같은 패키지 잠금 파일은 프로젝트에서 사용하는 패키지들의 버전을 고정시키는 역할을 한다.
package.json에는 버전이 ^나 ~를 통해서 범위로 지정된 경우가 많기 때문에, 모든 개발자가 정확히 같은 시각 동시에 패키지를 설치하지 않는 이상, 개발자들은 서로 상이한 패키지를 설치할 확률이 발생하게 된다.
패키지의 버전이 달라지면 협업에서 어떤 개발자는 버그가 있고, 어떤 개발자는 문제가 없는 등의 혼선이 발생할 수 있다.
따라서 npm과 yarn에서 모두 해당 시점의 버전을 잠금(lock)할 수 있는 기능을 지원하는 것이다.
협업에 무조건 필요한 파일이기에, 소스저장소에 반드시 commit을 해야하는 파일이다.
저도 가장 기본적이게 많이 사용하게 되는 패키지 관리자에 대해서 무심코 사용했던 것 같은데 너무 도움되는 글이었어요! 특히 npm과 npx의 차이가 흥미롭네용! npx는 항상 최신 패키지를 가져다 쓰는 1회성 설치를 할 때(ex. CRA), 또는 자주 사용하지 않는 패키지를 사용할 때 사용한다고 하네요! 깔끔한 글 잘 읽었습니당 :))