Node Package Manager ; Software Registry (the world largest..)
이름이 그렇듯이 노드 기반으로 작동하기 때문에 노드도 설치해야하는데 nvm 이용해서 설치하기를 권장하네요
왜냐면 그냥 노드 인스톨러는 내부적으로 npm을 설치하는데 이 권한이 로컬 권한이라 전역 권한으로 사용할 때 오류날 수도 있어서 그렇다네요
노드 모듈 뿐만 아니라 노드모듈을 포함하는 패키지들도 있음
package에 대한 정보는 해당 패키지 내부의 package.json에 기록됨(그래서 패키지마다 꼭 필요)
얘를 포함해서 압축하고 걔를 npm registry에 게시하고 이름@버전
의 형태로 나타냄, 버전 없이 이름만 쓰면 latest
실제로 지금 만들고 있는 board만 봐도 node_modules/
안에 package.json이 많음 → 각 패키지마다 있음!!! 왜냐면 해당 패키지를 설명해줘야하니까
근데 그러면 루트에 package.json이 있는 나의 리액트앱도 일종의 패키지라고 볼 수 있을 것 같다.
그런 모듈들은 node_modules/
안에 설치가 되고 require() 로 불러올 수 있다 → 자바스크립트 파일이거나 package.json을 포함하는 폴더거나 둘 중 하나의 형태여야함
위와같은 이유로 모듈 ≠ 패키지 모든 모듈이 패키지는 아니고 저 json을 포함하는 경우에만 패키지라고 부름
scope도 지정할 수 있는데 이는 private package를 구성하도록 도와준다. unscoped → public, private → scoped
일단 내 리액트앱 패키지 파일을 한 번 봐보면 depth1의 key들은 다음과 같다
name, type, version, private, dependencies, script, browserslist, devDependencies
여기서 정말 필수적인 것은 두 개
npm init
로 해당 폴더를 패키지로 만들겠다는 선언을 할 수 있고 이러면 package.json 파일을 만들어 낼 수 있음, 질문 형식에 답하면서 구성할 수 있도록 도와주는데 뭔가 나만의 package.json을 구성하는 규칙이 있다면 ~/.npm-init.js
를 통해 커스텀 가능
다른 app에서 사용할 수 있는 모듈을 이제 만들어야하는데 이는 exports object를 이용하여 export할 수 있다.
exports.printMsg = function() {
console.log("This is a message from the demo package");
}
// 이제 이게 아주 많고 체계적이고 하나가 아니라 여러 개이고 객체로 묶이고 등등..
npm publish
를 이용해서 배포 가능
내가 패키지 또는 프로젝트가 의존하고 있는 패키지들은 dependencies와 devDependecies를 통해 열거
→ 이후 패키지 폴더(node_modules)를 통으로 공유하지 않고 이 package.json 을 통해 공유하고 이를 참조하여 npm install함
똑같은 패키지라면 둘다 설치할 필요는 없을 것. 하지만 버전을 다르게 하여 테스트하고싶다거나 하면 로컬실행에서 devDependecies로 테스트 해볼 수 있다.
<major>.<minor>.<patch>
^
: major를 변화시키지 않는 모든 버전을 포함 → npm install시에는 그 중 최신버전으로~
: minor 범위까지 유지한 채 더 상위 버전으로 사용하겠다 → patch 변화>
, >=
, <
, <=
: 해당 연산자 오른쪽에 명시된 버전보다 높은/높거나같은/낮은/낮거나 같은 버전-
: 양쪽에 명시된 버전 사이의 버전||
: 양쪽의 명시된 버전 중 하나-rc
: alpha, beta 같이 pre-release된 버전 명시x
: 모든 버전이 들어갈 수 있음. 1.2.x 같은 형태로 사용해당 버전의 패키지가 dependency하고있는 패키지들이 vulnerability한지 아닌지 알려주는 것. 문제가 생길 가능성이 있는지 알려줌
→ package.json과 package-lock.json 둘 다 있어야함
fix를 할 때 조심해야하는게 호환성 같은 것들이 같이 변경될 수도 있기 때문에 조심해야함 semver warning으로 알려줌
이런 의존성 취약점 관리를 직접 확인하며 수정할 수도 있겠지만 github dependabot에게 도움받을 수 있음
https://npm.github.io/how-npm-works-docs/npm3/duplication.html
일단 node_module/
폴더를 보면 package.json
에 명시된 패키지들 보다 더 많은 패키지들이 설치되어 있는 것을 알 수 있는데
이는 npm 이 종속성 패키지들을 설치하는 방식때문이다. 일반적으로 종속성 패키지들은 해당 패키지의 node_modules/
속에 다시 설치되는 것이 아니라 전부 끌어올려져서 root/node_modules/
속에 flat하게 설치된다.
그래서 만약 같은 버전의 종속성을 가진다면 추가로 내부에 설치하지 않고 해당 패키지를 공유하여 사용한다.
하지만 버전이 다르다면 추가로 해당 버전을 최상위에 설치할 수 없으므로 패키지 내부의 node_modules/ 에 따로 설치한다.
이것들이 업데이트 될 때도 만약 최상위에 설치된 버전의 모듈을 종속성으로 참조하는 패키지가 있다면 아예 새로 패키지를 설치한다. 만약 참조하는 모듈이 없다면 다시 최상위로 이동시켜 설치하게 된다.
package.json에 종속성이 다 표시되어있고,
해당 패키지 속의 package.json에 또 해당 패키지의 종속성이 다 표시되어 있을텐데 package-lock.json이 왜 필요한걸까?
그냥 단순히 말하면 package.json은 자세한 정보가 부족하고 생각보다 버전에 대해 관용적이다.
그냥 npm install <package name>
을 해봤다면 알겠지만 위에서 말한 semver calculator가 붙여져서 나오는 경우가 많고 버전을 지정해주게 되면 마이너 릴리즈나 버그 패치가 나왔을 때 일일히 또 수정해주는 것이 번거로워 해당 calculator들을 지우지 않고 유지하는 것이 일반적이다.
하지만 그런 작은 변화들이 오류를 불러올 때가 많고 내가 개발했던 환경과 점점 차이가 나게되면 그 사이에서 또 오류가 발생하게 될 것이다.
그니까 개발환경을 완벽하게 동일하게 만들어 주는 파일
npm install 할 때!! 그 시점에 설치된 패키지들의 정보로 업데이트된다. 만약 이 package-lock.json을 토대로 패키지를 설치하고 싶다면 npm ci
를 해주어야한다.
물론 위에서 말한 ^
, ~
등의 이유도 있고,
그 재귀적인 작업이 생각보다 번거롭다.