패키지 잠금 파일(package-lock.json, yarn.lock)이 도대체 무엇일까?

남양주개발자

·

2021. 10. 29. 08:36

728x90
반응형

패키지 잠금 파일(package-lock.json, yarn.lock)이 도대체 무엇일까?

자바스크립트 프로젝트에서 개발을 하는 개발자분들은 package-lock.json 또는 yarn.lock 파일이 굉장히 익숙할 것입니다. 직접 생성한 파일은 아니기 때문에 무심코 그냥 지나갈 수 있는 부분이지만 프로젝트 관리 및 협업을 위해서 굉장히 중요한 부분이기 때문에 제대로 이해해야되는 부분입니다. 이번 포스팅에서는 패키지 잠금 파일은 무엇인지, 왜 패키지 잠금 파일이 중요한지에 대해서 다뤄보도록 하겠습니다.

자동으로 생성되는 패키지 잠금 파일(package-lock.json, yarn.lock)

자바스크립트 패키지 매니저

자바스크립트로 개발하는 개발자라면 npm과 yarn 두 가지 패키지 매니저가 굉장히 익숙할 것입니다. 

자바스크립트 패키지 매니저 양대산맥, yarn과 npm

yarn과 npm은 자바스크립트에서 사용하는 패키지들을 관리하는 도구입니다. 패키지라고 하면 프론트엔드 개발에서 활용하는 React, Vue 같은 라이브러리와 ant-design, bootstrap과 같은 UI 프레임워크도 모두 자바스크립트 패키지입니다.

프론트엔드 자바스크립트 라이브러리 React, Vue

yarn과 npm은 사용하는데 크게 차이점은 없고, 같은 제품에 브랜드만 다르다고 간단하게 이해하고 넘어가시면 될 것 같습니다. 이 두가지 패키지 매니저는 프로젝트에서 사용되는 패키지들을 설치/삭제/업데이트를 통해 관리하는데요. 추가적으로 패키지 잠금 파일(.lock)을 통해 프로젝트에서 사용하는 패키지들의 버전을 고정시키는 기능도 제공하고 있습니다. (npm을 사용한다면 package-lock.json, yarn을 사용한다면 yarn.lock!)

패키지 관리 방법

자바스크립트 프로젝트에서 패키지는 아래와 같이 package.json 파일에 관리되고 있습니다. 이 package.json 파일에는 해당 프로젝트가 의존하고 있는 모든 패키지 이름과 버전이 나열되어 있습니다. 프로젝트에서 기본적으로 설치되어야 하는지 패키지들은 dependencies 항목에, 그리고 개발할 때만 필요한 패키지들은 devDependencies 항목에 명시됩니다.

아래와 같은 예시에선 Next.js 관련 프로젝트라서 next, react, react-dom 패키지가 기본적으로 설치된 모습입니다.

{
  "name": "stockpo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev --port 4000",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "prepare": "husky install"
  },
  "dependencies": {
    "next": "11.1.2",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@types/react": "17.0.31",
    "@typescript-eslint/eslint-plugin": "^5.1.0",
    "@typescript-eslint/parser": "^5.1.0",
    "eslint": "8.0.1",
    "eslint-config-next": "11.1.2",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "prettier": "^2.4.1",
    "typescript": "4.4.4",
    "husky": "^7.0.0"
  }
}

이렇게 프로젝트에서 사용하는 모든 패키지들이 package.json 파일에 등록이 되어 있으면, 프로젝트 유관자들이 해당 프로젝트 코드를 clone하고 패키지 매니저의 설치 명령어 한번으로 종속된 모든 패키지들을 설치받을 수 있습니다. 

// 패키지 설치 방법
npm install // npm
// or
yarn // yarn

설치가 끝나면 프로젝트에서 필요한 모든 패키지들이 node_modules 폴더에 존재하는 것을 확인할 수 있습니다.

프로젝트에서 사용되는 전체 패키지들이 설치된 모습

하지만 세상은 그렇게 아름답지 못했다

역시나 개발의 삶은 생각처럼 쉽게 해결되지 않습니다. 패키지 매니저에 패키지를 설치할 경우 설치 시점에 따라 패키지 버전이 달라집니다. package.json 파일에 등록된 패키지의 버전이 ^나 ~ 등을 이용해서 범위로 지정된 경우가 많기 때문인데요. 패키지 버전이 틸드(~)나 캐럿(^)으로 설정되어 있다면 버전은 각 명시된 방식에 따라서 패키지를 설치합니다. 틸드(~)를 이용하면 ~0.0.1로 버전이 정의되었다면 >=0.0.1 <0.1.0 사이 버전의 패키지가 설치될 것이고, 캐럿(^)으로 명시되어 있다면, ^1.0.2 버전 패키지는 >=1.0.2 <2.0 기준에 맞는 패키지가 설치될 것입니다.

예를 들어, react 패키지가 "react": "^17.0.2"처럼 설정되어 있다고 한다면 아래 예시와 같이 설치 시점에 따라서 모두 다른 버전의 패키지로 설치될 수 있습니다.

  • package.json: ^17.0.2 (2021년 9월 1일 init)
  • 개발자 A: 17.0.2 (프로젝트 첫 생성자)
  • 개발자 B: 17.0.3 (2021년 9월 11일 합류)
  • 개발자 C: 17.1.0 (2021년 9월 21일 합류)
  • 개발/상용 서버: 17.1.3 (2021년 9월 30일 배포)

17.1.0 버전부터 React 라이브러리에 useHello라는 새로운 Hook이 생성되었다고 가정해봅시다. 개발자 C와 개발/사용 서버에 배포할 때는 나타나지 않던 버그가 개발자 A, 개발자 B 로컬 서버에는 에러라고 뜨면서 버그가 발생할 것입니다. 왜냐하면, 개발자 A와 개발자 B의 버전은 17.0.2, 17.0.3 버전으로 리액트에 useHello 훅이 없거든요. 이렇게 골때리는 경우를 사전에 방지하기 위해서 존재하는 것이 바로 패키지 잠금 파일(.lock)입니다.

패키지 잠금

패키지 잠금 파일(.lock)을 살펴보면 프로젝트에서 사용되는 모든 패키지들의 버전들이 고정되어 있는 것을 확인할 수 있습니다. package-lock.json이나 yarn.lock과 같은 패키지 잠금 파일에는 프로젝트에 패키지에 최초로 추가하는 시점에 정확히 어떤 버전이 설치가 되었는지를 기록한다고 이해하시면 됩니다.

패키지 잠금 파일

이처럼 패키지 잠금 파일을 기준으로 패키지들의 버전이 고정된 채 관리가 되고 있다면 또 다른 개발자가 합류해서 프로젝트를 클론하고 패키지를 설치할 때 버전이 꼬이는 경우가 없겠죠.

그렇기 때문에

Github나 Gitlab과 같은 버전 관리 시스템에 프로젝트를 업로드할 때 꼭 패키지 잠금파일(.lock)을 포함해서 올려서 프로젝트에 참여한 개발자들 모두 패키지 잠금 파일 기준으로 패키지를 설치할 수 있도록 해야합니다. 절대 .gitignore에 패키지 잠금 파일(.lock)을 추가하지 마세요.

그리고 가장 중요한 부분은 패키지 잠금 파일을 직접 강제로 수정하지 않도록 합니다. npm이나 yarn을 활용해 패키지를 설치하거나 삭제할 경우 패키지 매니저는 자동으로 패키지 잠금 파일에 반영하기 때문에 잠금 파일을 셀프로 건드리다가 오히려 꼬여버리는 불상사가 일어날 수 있으니 직접 수정하지 맙시다. 만약 .lock 파일에 Git conflict가 난다고 하면 같이 협업하는 누군가 제대로 관리하고 있지 않는 것이기 때문에 바로잡고 넘어가야 합니다.

728x90
반응형
그리드형

이 포스팅은 쿠팡파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

💖 저자에게 암호화폐로 후원하기 💖

아이콘을 클릭하면 지갑 주소가자동으로 복사됩니다