티스토리 뷰

나는 왜 이 내용을 글로 쓰는가?

얼마 전에 친구가 package-lock.json에 대해 쉽게 설명을 해달라고 물어보더군요.
하지만, package-lock.json이 어떤 일을 하는지도 모르고, 해당 파일을 발견하면 무조건 지우고 봤던 제가 설명할 수 있을리가요..
그래서 이번 기회에 한 번 관련 내용들을 정리해볼까 합니다.

아니, 그 전에 package.json은 뭔데?

package.json은 npm에서 핵심적인 역할을 하는 친구입니다!
이름에 걸맞게 각종 npm 패키지들에 대한 정보들과, 의존하고 있는 버전에 대한 정보를 담고 있는...그냥 프로젝트에 대한 전체적인 정보를 담고 있는 JSON 형태의 파일이라고 할 수 있습니다.
필수적으로 name과 version에 대한 정보가 명시되어야 하며, 이 항목들이 누락될 시 패키지는 설치될 수 없습니다!
이외에 description, keywords, license, bugs, dependencies, devDependencies 등과 같은 여러 내용들로 구성되어 있습니다.

우리는, 크고 작은 여러 프로젝트들을 진행하면서 다양한 패키지들을 사용(의존)하게 됩니다.
패키지들의 버전이 빠르게 변화하다보니 관리가 힘든 경우가 많은데, 이 때 package.json이 의존중인 패키지들의 버전을 세 가지 종류로 기록해주며, 그 두 가지가 바로 dependencies와 devDependecies(+ peerDependencies)입니다.
이름에서 유추할 수 있듯이, 전자는 일반적인 경우, 후자는 개발 모드일 때만 의존하고 있다는 것을 알려줍니다.

흔히 npm install을 할 때 뒤에 붙이는 --save나 --save-dev를 보신적이 있으실텐데요?
다른 포스트에도 설명한 적이 있었던 것 같은데, 간단히 정리하고 넘어가겠습니다!
일단! 두 키워드 모두 기본적으로 install할 시 node_modules 디렉터리에 패키지 설치를 함과 동시에 package.json까지 업데이트를 해주지만,
--save의 경우 dependencies, --save-dev와 같은 경우 devDependencies에 등록이 됩니다. (아래 그림 참고!)
devDependencies의 경우 dependencies와 다르게 --production으로 빌드 시 해당 플러그인이 포함되지 않는다는 특징을 가지고 있기 때문에
  • 어플리케이션에 실질적으로 필요한 것들은 --save
  • 실제 배포할 때 Mocha, Jest와 같이 필요하지 않은 테스트 도구나, 웹팩, 바벨 등은 --save-dev
로 npm install하면 좋을 것 같습니다

다시 돌아와서 package-lock.json이란?

자, 서론이 길었는데요! 이제 package-lock.json이란 무엇인지 적어보겠습니다.
우리가 npm install 명령을 실행할 시, package.json(= Input)을 통해 node_modules 폴더(트리 = Output)를 생성하게 됩니다.
package.json에 명시된 의존성 패키지들을 폴더 안에 설치하며, 생성된 node_modules 폴더의 정보를 package-lock.json 안에 담습니다.

이상적인 npm install은 동일한 package.json에 동일한 node_modules가 작성되는 것인데 크게
  1. 현재 사용하고 있는 npm의 버전이 다른 경우
  2. 의존성을 가진 패키지의 버전이 업데이트 됐을 경우
  3. 의존성을 가진 패키지가 의존하는 패키지의 버전이 업데이트 됐을 경우
다음과 같은 이유들로 실현되지 못하는 경우가 많습니다.
말이 좀 헷갈렸을텐데요...예시를 한 번 들어보겠습니다.

상우는 주말에 심심하여 A라는 이름을 가진 패키지를 개발하고 있습니다.


상우는, 원하는 기능 개발을 위해 B라는 패키지를 install한 상황입니다!
그럼 B의 패키지는 어떻게 구성되어 있는지 볼까요?


저런! 상우가 사용하고자 하는 B 패키지 역시 C라는 패키지를 사용하고 있군요!
C는 어떤 형태로 구성되어 있는지 볼까요?


다행히도 C 패키지는 따로 디펜던시를 가지고 있지 않은 상황입니다~
위 3개의 모듈이 저장소에 올라간 유일한 버전인 경우, npm install A를 할시 node_modules의 output 트리는 다음과 같이 출력이 될 것입니다.


이와 같은 상황에서 위에 나열했던 2번과 3번은 아래와 같이 발생하게 됩니다.

2. 의존성을 가진 패키지의 버전이 업데이트 됐을 경우
만약 B의 패키지의 버전이 새로 publish되어 0.0.2가 되었다고 가정해봅시다.
이렇게 되면, npm install을 할 시 0.0.1버전의 B 패키지가 아닌 0.0.2버전의 B 패키지를 받아오게 되고, node_modules Output 역시


다음과 같은 형태로 변하게 됩니다.
뭐 2번은 사용자가 package.json에서 사용하는 B 버전을 완전히 고정하면 문제가 되질 않습니다.
다만,

3. 의존성을 가진 패키지가 의존하는 패키지의 버전이 업데이트 됐을 경우
는 앞서 말한 1, 2번 보다 좀 더 복잡하다고 할 수 있습니다.
만약 B에 종속되어 있는 C 패키지가 0.0.2버전으로 되었다고 가정할 시, npm install을 하면 0.0.2버전의 C 패키지를 받아오게 됩니다.

B 패키지의 개발자가 A 개발자와 다르다고 가정했을 시, A 개발자는 B 패키지의 package.json을 수정할 수 없게 됩니다.
다시 말해, A, B, C 패키지의 개발자가 모두 다른 상황인 경우, A 개발자는 자신의 package.json에서 B의 버전을 고정할 수는 있어도 B 자체의 package.json이나, B에 종속된 C 패키지까지 건들 수는 없다 이 말입니다! ( 실제 패키지들을 사용할 때는 그 단계가 훨씬 복잡하겠죠?? )
"패키지들은 계속해서 버전을 갱신하고 있기 때문에 똑같은 조건하에서의 설치가 거의 불가능하며, 같은 버전의 패키지라도 그것이 의존하는 패키지에는 다른 버전들이 존재할 수 있다"로 이해하시면 좀 더 편할 것 같습니다.

뭐 어쨌든, 이러한 잠재적 문제들을 방지하기 위해서 package-lock.json이 등장하였습니다!


다음과 같이 정확하게 재현할 수 있는 node_modules 트리를 설명하며, 해당 폴더의 스냅샷을 저장하는 방식을 통해 기존 package.json이 가지고 있는 약점을 보완한다고 할 수 있습니다.
package-lock.json이 존재하게 되면 이후 npm install시 package.json이 가지고 있는 종속성을 다시 계산하지 않고, package-lock.json에 명시된 의존 패키지들을 통해 node_modules를 생성합니다.
이러한 특징 때문에 당연히 소스 저장소에 package-lock.json을 포함시켜야 하며, 프로젝트를 진행하는 모든 개발자가 같은 node_modules를 가지고 작업하기 위해 필수라고 할 수 있습니다.

마지막으로

package-lock.json은 node_modules나 package.json이 생성되거나 수정될 때 자동적으로 만들어지며, 종속성 업데이트에 관계없이 동일한 트리를 생성하여 개발자들이 같은 의존성을 설치할 수 있도록 보장해줍니다.
팀 프로젝트를 진행할 때 배포나 지속적인 통합이 이뤄져야 하는 상황에서 package-lock.json은 단순히 불필요한 파일이 아니라, 개발자들이 통일성 있는 환경에서 개발할 수 있도록 해주는 일종의 연결고리라고 할 수 있겠습니다!


글 봐주셔서 정말 감사하고, 수정이나 추가해야할 내용이 있을 시 언제든 코멘트 부탁드립니다!


'Web' 카테고리의 다른 글

Lazy Loading과 기타 이야기  (5) 2018.11.15
댓글