• TIL

package.json 과 package-lock.json 차이

man_on 2021. 9. 23. 22:44
반응형

 

1. 패키지를 공유할 때, 그 안의 node_modules 디렉토리는 공유하지 않는다.

하나의 패키지는 여러 명의 개발자가 협력해서 만드는 게 일반적입니다.

그럼 이때 협력하는 개발자들끼리는 패키지를 어떻게 공유할까요?

패키지는 package.json 파일이 있는 디렉토리니까 이 디렉토리를 서로 주고받으면 되는데요. 이때 중요한 점이 하나 있습니다.

패키지를 공유할 때, 패키지 안에 있는 node_modules 디렉토리는 보통 공유하지 않는다는 점입니다.

 

node_modules 디렉토리가 뭐였죠? 현재 작업 중인 패키지에서 이런저런 패키지들을 설치하면 그것들이 설치되는 곳이었습니다. 그런데 이렇게 중요한 node_modules 디렉토리를 왜 공유하지 않는 걸까요? 왜냐하면 보통 패키지를 몇 개 정도만 설치해도 node_modules 디렉토리 내부의 용량은 매우 커지게 되고, 이것들을 매번 공유하는 것은 비효율적(용량 문제)이기 때문입니다.

 

하지만 그렇다고 해서 현재 패키지가 의존하는 다른 패키지들이 없으면, 현재 패키지가 정상적으로 실행될 수 없을텐데 대책이 있는 걸까요? 바로 이때 package.json 파일이 필요합니다.

패키지를 공유할 때는 그 안의 package.json 파일만 제대로 공유하면 됩니다.

그리고 공유받은 측은, 해당 패키지 안에서 npm install 이라고 쓰고 실행하면, npm이 package.json 파일의 dependencies 필드에 적힌

  • 의존 패키지들의 이름과
  • Semantic Version / Version Range Syntax를 보고

알맞은 패키지들을 자동으로 설치해줍니다.

이전에 우리가 배운 것처럼 package.json 파일에는

현재 패키지가 의존하는 패키지들(dependencies)들의 정보가 이렇게 잘 나와있기 때문에 npm이 이 정보를 기반으로 필요한 패키지들을 설치할 수 있는 겁니다. 한마디로 정리하면, 패키지를 공유할 때 무거운 용량의 node_modules 디렉토리는 굳이 직접 공유하지 않고, 패키지를 공유받는 사람이 npm install 명령어를 실행해서 공유받은 package.json 파일을 기반으로 직접 생성하는 것입니다.

2. package.json 파일과 package-lock.json 파일

방금 package.json 파일을 기반으로 한 패키지 공유 방식에 대해 설명했습니다. 그런데 가끔 이 방식이 문제가 될 때가 있습니다. 그건 바로 개발자 A가 갖고 있던 패키지를 받아서 개발자 B가 npm install 명령어로 그 안의 node_modules 디렉토리를 재현해도, 그 내부의 패키지들이 동일하지 않을 때가 있기 때문입니다. 이런 일이 발생하는 가장 주된 원인은 우리가 배운 Version Range Syntax 때문입니다. package.json 파일의 dependencies 필드를 보면 버전 부분에 3.5.2 이런 식으로 딱 Semantic Version만 적혀있는 부분도 있지만 우리가 배운 Tilde Range(~3.5.2), Caret Range(^3.5.2) 같은 Version Range Syntax가 적혀있는 경우도 많습니다. 그리고 이런 경우에는 해당 패키지의 특정 버전 뿐만 아니라 일정한 버전 범위 내에 있는 패키지면 설치가 가능하기 때문에 문제가 되는 겁니다.

예를 들어,

  • 개발자 A가 sample이라는 패키지에 관한 작업을 할 때,
  • 그것이 의존하는 helper라는 패키지의 Version Range가 ^3.5.2였다고 생각해봅시다.

그럼 3.5.2≥ <4.0.0 버전 안의 패키지들은 모두 설치가 가능하겠죠?

A가 sample 패키지를 만들 때는 helper 패키지의 최신 버전이 3.5.4였다고 해봅시다. 그리고 시간이 지나 helper 패키지의 3.6.0 버전이 나왔다고 생각해보세요. 이 시점에 만약 개발자 B가 이 패키지를 공유받는다면 어떻게 될까요? 위에서 말한 대로 node_modules 디렉토리는 공유하지 않고 package.json 파일만 공유하기 때문에, 이제 개발자 B의 경우에는 npm install을 실행했을 때 3.6.0 버전의 helper 패키지가 설치될 겁니다. 분명, 둘 다 sample 패키지를 갖고 작업을 하고 있는데

  • 개발자 A는 3.5.4 버전의 helper 패키지,
  • 개발자 B는 3.6.0 버전의 helper 패키지

를 갖고 작업하게 되는 겁니다.

일반적인 경우에는 이러한 것들이 별 문제가 없을 수도 있습니다. 하지만

  • sample 패키지를 공동 개발하는 중이라 모든 개발자가 똑같은 환경을 보장받아야하는 경우
  • helper 패키지의 새 버전에 버그 등은 없는지 점검한 후에 써야하는 경우

등에는 공유하는 측과 공유받는 측에서 이렇게 dependency의 차이가 발생해서는 안 됩니다.

그럼 이 문제를 어떻게 해결할 수 있을까요? 그렇다고 node_modules 디렉토리를 통째로 공유하는 건 용량 때문에 너무 비효율적인데 말이죠.

정답은 바로 package-lock.json 파일에 있습니다. package-lock.json 파일에 대해서는 배운 적이 있는데요.

잠깐 저의 nodeStudy 패키지 내부를 보겠습니다.

지금 보면 package-lock.json 파일과 pakcage.json 파일이 보이는데요. 각각 어느 시점에 생긴 파일들인지 기억나시나요?

  • package-lock.json 파일은 맨 처음 패키지를 설치했을 때(당시에는 패키지를 배우기 전이라 '서드파티 모듈'이라고 불렀었죠?) 생겼던 파일이고(참조)
  • package.json 파일은 제가 npm init 명령어를 사용해서 nodeStudy 디렉토리를 하나의 패키지로 만들었을 때 생긴 파일인데요.(참조)

package-lock.json 파일에는 dependencies 필드에, 현재 패키지 안에 어떤 패키지들이 설치되어 있는지 그 정보가 담겨있다고 배웠습니다. package.json 파일도 마찬가지로 dependencies 필드가 있고, 여기에는 어떤 패키지들이 설치되어야 하는지에 대한 정보가 있다고 했습니다.

혹시 방금 위의 설명에서 둘 간의 미묘한 차이를 눈치채셨나요?

package-lock.json에는 현재 패키지 안에 '실제로 설치된' 패키지들의 정확한 버전들이 기록되어 있습니다.

위 이미지에 나온 package-lock.json 파일의 dependencies 필드를 보면, '실제로 설치된' 패키지들의 이름과 '정확한' 버전들을 볼 수 있습니다.

반면에 packag.json 파일의 내용을 보면

dependencies 필드에 보이는 패키지의 이름 옆에는 Version Range Syntax가 존재하는 경우도 있다는 것을 알 수 있습니다. 즉, 이 dependencies 필드가 의미하는 것은 특정 패키지의 특정 버전이 아니라(특정 버전이 적혀있는 경우도 물론 있습니다) Version Range Syntax를 만족하는 버전의 패키지라면 언제든지 업데이트된 버전의 패키지가 설치되어도 괜찮다는 뜻입니다.

그러니까

  • package.json 파일의 dependencies 필드에는 '현재 패키지가 동작하기 위해 필요한 다른 패키지들의 버전 범위'가 적혀있는 것이고,
  • package-lock.json 파일의 dependencies 필드에는 '현재 패키지에 실제로 설치되어 있는 다른 패키지들의 버전'이 적혀있는 것입니다.

 

그리고 바로 이 package-lock.json 파일이 아까 말한 'package.json 기반의 패키지 공유 방식'이 발생시킬 수 있는 문제에 대한 해결책입니다. 패키지를 공유할 때, 이 package-lock.json 파일도 package.json 파일과 함께 공유하면 npm install 을 실행했을 때 npm은 package-lock.json 파일의 dependencies를 보고, 특정 버전의 패키지들을 정확히 동일하게 설치합니다. 그럼 어느 상황에서든 해당 패키지를 공유받는 사람이나 공유해준 사람은 동일한 버전의 dependency들을 설치하게 됩니다. 즉, 동일한 node_modules 디렉토리를 갖게 되는 것입니다.

 

그러니까 만약 패키지를 공유할 때 정확히 똑같은 패키지를 상대방도 가져야 할 때는 반드시 이 package-lock.json 파일도 package.json과 함께 공유해줘야 합니다. 그 정도까지는 아니고 공유받는 측에서 패키지가 동작만 잘 해도 되는 경우라면 package.json 파일만 공유해줘도 되고요.

 

[정리]

패키지를 공유할 때는 보통 그 안의 node_modules 디렉토리를 제외하고 공유합니다.

이때 패키지 안의 package.json 파일 내용 중 dependencies 필드의 정보가 공유받는 측에서 node_modules 디렉토리를 재생성(npm install)하는 데 사용되며

이때 공유해준 사람과 공유받은 사람 간에 node_modules 디렉토리 내부의 차이가 발생하지 않도록 방지하려면 package-lock.json 파일도 package.json 파일과 함께 공유해줘야 합니다.

 

 

 

반응형

'• TIL' 카테고리의 다른 글

[TIL] Plug-in?  (0) 2021.12.07
[TIL] Strapi  (0) 2021.11.18
[VSC] Prettier 적용방법  (0) 2021.10.16
export / export default  (0) 2021.10.02
--save-dev ?  (0) 2021.09.25