npm/yarn, 이제는 알고쓰자

PinkTopaz·2023년 3월 18일
2
post-thumbnail
post-custom-banner

라이브러리를 설치할 때 yarn add ~ , npm install ~ 를 항상 사용하면서 이 yarn과 npm이 무엇인지 제대로 모르고 있다는 생각이 문득 들었다.
그래서 yarn과 npm을 톺아보려고 했는데 "패키지 관리자"라는 말의 패키지가 무엇인지부터 이해가 되지 않았다.
그래서 yarn과 npm을 톺아보려다가 거슬러 올라간 과정에서 공부한 모든 것을 정리해보려고 한다.


1. 모듈 vs 패키지 vs 라이브러리

  • 모듈 : 프로그램을 구성하는 소스코드가 들어 있으며 만들어 놓은 모듈은 불러와서 재사용이 가능 (by import)
  • 패키지 : 여러 모듈의 묶음으로, 특정 기능과 관련된 여러 모듈을 하나의 상위 폴더에 넣은 것
  • 라이브러리 : 모듈과 패키지의 묶음

보통 모듈을 레고 블럭, 패키지를 레고 블럭의 집합으로 정의한다.
Recoil에서 Recoil이 패키지라면, module이 useSetRecoilState이며 보통의 경우 패키지와 라이브러리가 엄격하게 구분되지 않을 수 있으니 이 경우에서는 Recoil이 패키지이자 라이브러리이다. (Recoil이라는 라이브러리 안에 Package가 하나만 있다고 생각해도 되겠다.)


2. npm vs yarn

모두 자바스크립트 런타임 환경 Node.js의 기본 패키지 관리자이며, node_modules에 모든 모듈을 저장한다.
참고로 node_modules에는 package.json에 명시된 모듈 뿐만 아니라 해당 모듈이 의존하고 있는 모듈까지 모두 들어가기 때문에 크기가 굉장히 큰 폴더가 된 것이다.

npm

  • node.js 설치할 때 자동으로 설치됨

  • npm은 필수 단계를 순차적으로 수행하기 때문에 한 개의 패키지 다운로드 완료해야 다음 패키지를 다운로드 할 수 있음.

  • 대표적인 명령어

    • npm install : package.json 파일 및 해당 종속성에 나열된 모든 모듈을 설치
    • npm init : package.json 생성

yarn

  • 병렬적으로 여러 패키지를 동시에 설치할 수 있고, 다운받은 패키지 데이터를 캐시(cache)에 저장하여, 중복된 데이터는 다운로드하지않고, 캐시에 저장된 파일을 활용함으로써 npm에 비해 패키지 설치속도가 매우 빠르다.

  • npm의 부족한 부분들을 개선하기 위해 Facebook에서 개발되었다.

  • 대표적인 명령어

    • yarn install : package.json 파일 및 해당 종속성에 나열된 모든 모듈을 설치
    • yarn add package-name : 의존성 모듈 설치

3. 패키지 관리자의 역할이 무엇인가?

패키지들을 사용하기 위해서는 다운로드, 설치, 업데이트, 의존성 관리, 제거 등 복잡한 상황들이 많이 생기는데 패키지 매니저는 이러한 과정들을 자동화하여 편리하고 안전하게 수행할 수 있도록 해준다.
패키지 관리자가 하는 역할에는 크게 2가지가 있다.

  1. 패키지의 dependency를 관리하는 역할
    • dependency(의존성) : 많은 패키지들은 다른 패키지가 설치되어 있어야만 제대로 동작한다. 이 경우에 기존 패키지를 제대로 동작시키기 위해 필요한 다른 패키지를 dependency라고 한다.
    • npm과 yarn은 package.json을 통해서 프로젝트 정보와 패키지의 의존성을 관리한다.
  1. Software repository (패키지를 저장하고 관리하는 저장소이다. 다른 말로는 repos라고 부른다. 패키지의 앱스토어 같은 느낌이라고 생각하면 쉽다. )로부터 패키지를 찾고, 다운로드하고, 설치하고, 업데이트하는 역할
//리액트 프로젝트에서 react-cookie를 사용하고 싶을 때 다음과 같이 설치했다. 
yarn add react-cookie

4. npm vs npx

npm install 모듈이름 -g

해당 코드를 이용하면 프로젝트마다 모듈을 설치할 필요없이 내 컴퓨터 안에 글로벌한 공간에 모듈을 설치해 프로젝트마다 같은 모듈을 공유해서 사용할 수 있다.

하지만

  • 한 번 설치한 모듈을 계속 사용하기 때문에 업데이트 확인이 어렵고
  • 서로 다른 프로젝트에서 같은 모듈의 다른 버전이 필요할 경우가 있을 수 있고
  • 모듈 변경이 잦은 CRA에서는 자주 업데이트를 해줘야해서 귀찮다.

이에 대한 해결책으로 등장한 것이 npx이다.
모듈을 로컬에 저장하지 않고, 매번 최신 버전의 파일만을 임시로 불러와 실행 시킨 후에, 다시 그 파일은 없어지는 방식으로 모듈이 작동한다.
따라서 npx로 설치한 모듈의 경우 node_modules에 들어가지 않는다.

모듈의 변화가 많은 CRA와 같은 경우, npx로 모듈을 설치하고 실행하면 좋다.


5. React를 처음 시작할 때 node.js는 왜 설치해야하는가?

결론 : Babel과 npm 사용을 위함이다!

Node.js는 설치하는 경우 npm이 같이 설치되는데 이를 통해 React 개발에 필요한 다양한 모듈들을 다운받아 사용할 수 있다.

그렇다면 npm만 설치하면 되지 왜 굳이 번거롭게 node.js를 통해 npm을 설치하는 것일까??

React는 클라이언트 기반 라이브러리기 때문에 npm만 설치하여도 React와 react-dom 라이브러리를 사용할 수 있다.
하지만 node.js가 있으면 바벨이라는 컴파일러 도구를 추가로 다운받아 자바스크립트 대신 JSX를 사용하는 것이 가능하기 때문이다.


6. Package.json

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"
  }
}

7. 패키지 잠금 파일의 역할은 무엇인가?

yarn.lock, package.lock.json과 같은 패키지 잠금 파일은 프로젝트에서 사용하는 패키지들의 버전을 고정시키는 역할을 한다.
package.json에는 버전이 ^나 ~를 통해서 범위로 지정된 경우가 많기 때문에, 모든 개발자가 정확히 같은 시각 동시에 패키지를 설치하지 않는 이상, 개발자들은 서로 상이한 패키지를 설치할 확률이 발생하게 된다.

패키지의 버전이 달라지면 협업에서 어떤 개발자는 버그가 있고, 어떤 개발자는 문제가 없는 등의 혼선이 발생할 수 있다.
따라서 npm과 yarn에서 모두 해당 시점의 버전을 잠금(lock)할 수 있는 기능을 지원하는 것이다.

협업에 무조건 필요한 파일이기에, 소스저장소에 반드시 commit을 해야하는 파일이다.


참고자료

모듈 vs 패키지 vs 라이브러리 vs 프레임워크
npm, yarn
npm과 npx의 차이에 대해서

profile
🌱Connecting the dots🌱
post-custom-banner

2개의 댓글

comment-user-thumbnail
2023년 3월 24일

저도 가장 기본적이게 많이 사용하게 되는 패키지 관리자에 대해서 무심코 사용했던 것 같은데 너무 도움되는 글이었어요! 특히 npm과 npx의 차이가 흥미롭네용! npx는 항상 최신 패키지를 가져다 쓰는 1회성 설치를 할 때(ex. CRA), 또는 자주 사용하지 않는 패키지를 사용할 때 사용한다고 하네요! 깔끔한 글 잘 읽었습니당 :))

답글 달기
comment-user-thumbnail
2023년 3월 26일

헉! 패키지 잠금이 버전을 고정시키는 것이라는 걸 처음 알았어요! 역할에 대해 고민해본 적이 없던 것 같은데 왜 npm과 yarn을 혼용했을때 .lock을 삭제하라고 했는지 이제야 이해가 되네요!!

답글 달기