원문: https://docs.npmjs.com/cli/v8/configuring-npm/folders
번역: 양정석 (dasomoli@gmailREMOVETHIS.com)
설명
npm은 여러분의 컴퓨터 상에 다양한 것들을 둡니다. 이게 그게 하는 일이예요.
이 문서는 이게 어디에 무엇을 두는지 설명합니다.
요약
- 로컬 설치 (기본): 현재 패키지의 루트 디렉토리의
./node_modules
에 설치 - 글로벌 설치 (-g 옵션):
/usr/local
또는 노드가 설치된 곳에 설치 require()
를 한다면 로컬에 설치- 커맨드 라인에서 실행한다면 글로벌 설치
- 로컬과 글로벌 둘 다 필요하다면 양쪽 모두에 설치하거나
npm link
를 사용
prefix 설정
기본 prefix
설정은 노드가 설치된 곳입니다. 대부분 /usr/local
입니다. 윈도우즈에서는 %AppData%\npm
입니다. {prefix}/node.exe
가 아니라 {prefix}/bin/node
에 보통 설치되므로 유닉스 시스템에서는 한 레벨 더 들어갑니다.
global
플래그가 설정되면, npm은 이 prefix 내에 설치합니다. 설정되지 않았다면, 패키지 내에 없으면 현재 패키지 또는 현재 작업 디렉토리의 루트 디렉토리를 사용합니다.
노드 모듈
패키지들은 prefix
아래의 node_modules
폴더 내에 들어갑니다. 로컬에 설치될 때, 이는 main 모듈을 로드하기 위해 여러분이 require("packagename")
을 사용하거나 다른 모듈을 사용하기 위해서 require("packagename/lib/path/to/sub/module")
을 사용할 수 있다는 뜻입니다.
유닉스 시스템 상에서의 글로벌 설치는 {prefix}/lib/node_modules
로 진행됩니다. 윈도우즈 상에서 글로벌 설치는 {prefix}/node_modules
로 진행(즉, lib
가 없음)됩니다.
범위가 지정된 패키지들은 @ 기호가 붙는 범위 prefix의 이름과 연관된 node_modules
폴더의 하위 폴더 내에 함께 그룹지어지는 것을 빼면 같은 방식으로 설치됩니다. 예를 들어, npm install @myorg/package
는 그 패키지를 {prefix}/node_modules/@myorg/package
내에 설치합니다. 더 자세한 사항은 scope을 참고하세요.
패키지를 require()
하길 원한다면, 로컬에 설치하세요.
실행 파일
글로벌 모드에서 유닉스 상에서는 {prefix}/bin
, 윈도우즈 상에서는 {prefix}
에 직접 실행 파일이 링크됩니다. 여러분의 터미널의 PATH 환경 변수에 이를 실행할 수 있도록 이 경로가 들어가 있는지 꼭 확인하세요.
로컬 모드에서 실행파일은 ./node_modules/.bin
내에 링크되기 때문에 npm을 통해 스크립트 실행이 가능합니다. (예를 들어 npm test
를 실행할 때 그 경로 내에 테스트 러너가 있을 겁니다)
Man Pages
글로벌 모드에서 man page는 {prefix}/share/man
내로 링크됩니다.
로컬 모드에서는 man page는 설치되지 않습니다.
Man page는 윈도우즈 시스템 상에서 설치되지 않습니다.
캐시
npm cache를 보세요. 캐시 파일들은 Posix 상에서는 ~/.npm
내에, 윈도우즈 상에서는 %AppData%/npm-cache
내에 저장됩니다.
이는 cache
설정 파라미터에 의해 제어됩니다.
임시 파일
임시 파일은 기본 값인 TMPDIR, TMP, TEMP 환경변수, 또는 유닉스 상에서 /tmp
나 윈도우즈 상에서 c:\windows\temp
인 tmp
설정으로 지정된 폴더 내에 저장됩니다.
임시 파일들은 이 루트 디렉토리 안에 프로그램의 각각의 실행에 대한 유일한 폴더가 지정되고, 성공적으로 끝나면 지워집니다.
더 자세한 정보
로컬 설치 시에 npm은 먼저 적절한 prefix
폴더를 찾으려고 시도합니다. 이는 그래서 npm install foo@1.2.3
은 여러분이 다른 폴더로 cd를 이용해서 이동했었다 하더라도 여러분의 패키지의 합리적인 루트 디렉토리에 설치할 겁니다.
$PWD에서 시작해서 npm은 package.json
파일 아니면 node_modules
폴더를 갖는 폴더를 확인하면서 탐색합니다. 그런 것을 찾으면 npm 명령을 실행하는 목적에 맞는 실제적인 “현재 디렉토리”로 취급합니다. (이 동작은 git의 작업 디렉토리 내에서 git 명령을 실행했을 때 .git 폴더를 찾는 로직에서 영감을 받아 비슷합니다).
아무 패키지 루트도 찾지 못했다면, 현재 폴더가 사용됩니다.
npm install foo@1.2.3
을 실행하면, 그 패키지는 캐시 내에 로드된 후, ./node_modules/foo
내에 풀게 됩니다. 그 후 foo의 디펜던시들은 비슷하게 ./node_modules/foo/node_modules/...
에 풀게 됩니다.
./node_modules/.bin
에 심볼릭 링크된 바이너리 파일들은 npm 스크립트가 필요할 때 찾을 수 있습니다.
글로벌 설치
global
설정이 true로 설정되면, npm은 “글로벌”로 패키지를 설치합니다.
글로벌 설치에서 패키지들은 위에서 설명된 폴더를 사용해서 거의 같은 방식으로 설치됩니다.
순환, 충돌, 그리고 폴더의 중복 제거
순환은 node_modules
폴더를 찾는 디렉토리를 탐색하는 노드의 모듈 시스템 속성을 사용해서 처리됩니다.모든 단계에서 어느 패키지가 이미 그 상위의 node_modules
폴더에 설치되어 있다면 현재 위치에는 설치하지 않습니다.
foo -> bar -> baz
에서 위의 경우를 생각해 봅시다. baz가 bar에 의존한다고 상상해보면, foo -> bar -> baz -> bar -> baz ...
가 될 겁니다. 그러나 폴더 구조가 foo/node_modules/bar/node_modules/baz
가 되기 때문에 require("bar")
를 부르면, foo/node_modules/bar
내에 설치된 복사본을 얻을 것이므로 bar의 다른 복사본을 .../baz/node_modules
내에 둘 필요가 없습니다.
이 손쉬운 방법은 정확히 같은 버전이 중첩된 node_modules 폴더 내에 설치되었을 때만 사용됩니다. 두 “a” 패키지가 다른 버전이라면 a/node_modules/b/node_modules/a
가 되는 것이 여전히 가능합니다. 그러나 정확히 같은 패키지를 여러번 반복하는 일 없이 무한 회귀는 언제나 방지됩니다.
다른 최적화는 아래의 로컬라이즈된 “target” 폴더 아래에 가능한 한 가장 높은 레벨에 의존 모듈들을 설치해서 구성할 수 있습니다.
예제
이런 의존 그래프를 생각해보죠.
foo
+-- blerg@1.2.5
+-- bar@1.2.3
| +-- blerg@1.x (latest=1.3.7)
| +-- baz@2.x
| | `-- quux@3.x
| | `-- bar@1.2.3 (순환)
| `-- asdf@*
`-- baz@1.2.3
`-- quux@3.x
`-- bar
이 경우, 우리는 다음과 같은 폴더 구조를 기대할 수 있을 겁니다.
foo
+-- node_modules
+-- blerg (1.2.5) <---[A]
+-- bar (1.2.3) <---[B]
| `-- node_modules
| +-- baz (2.0.2) <---[C]
| | `-- node_modules
| | `-- quux (3.2.0)
| `-- asdf (2.3.4)
`-- baz (1.2.3) <---[D]
`-- node_modules
`-- quux (3.2.0) <---[E]
foo가 bar@1.2.3
와 baz@1.2.3
에 직접 의존하므로, 이들은 foo의 node_modules
폴더 내에 설치됩니다.
blerg의 최신본이 1.3.7임에도 불구하고, foo는 1.2.5 버전으로 지정된 의존을 갖습니다. 그래서 이는 [A]에 설치됩니다. blerg의 상위 설치가 bar의 blerg@1.x
의존을 만족하므로, [B] 아래에 다른 복사본을 설치하지 않습니다.
bar [B] 또한 baz와 asdf에 의존을 갖습니다. 그래서 이들은 bar의 node_modules
폴더에 설치됩니다. 이게 baz@2.x
에 의존하므로 그 상위의 node_modules
폴더 [D] 에 설치된 baz@1.2.3
을 재사용할 수는 없고, 그 자신의 복사본 [C]를 설치해야만 합니다.
bar 아래에 baz -> quux -> bar
의존은 순환을 만듭니다. 그러나 bar가 이미 quux의 조상 [B] 이므로, 그 폴더 내에 bar의 다른 복사본을 풀지 않습니다.
foo -> baz
[D] 아래에, quux의 [E] 폴더 트리는 비게 됩니다. bar 상의 그 의존이 [B] 에 설치된 상위 폴더 복사본에 의해 만족되기 때문입니다.
무엇이 어디에 설치되는지의 그래프 분석은 npm ls
를 사용하세요.
퍼블리싱
퍼블리싱 상에서 npm은 node_modules
폴더 안을 들여다 봅니다. 항목 들 중 어느 것도 bundledDependencies 배열에 들어있지 않으면, 그들은 패키지 tarball 내에 포함되지 않을 겁니다.
이는 패키지 메인테이너가 그들의 의존 모두를 로컬에 설치할 수 있도록 하지만, 다른 곳에서 찾을 수 없는 이들 항목만 다시 퍼블리싱 합니다. 더 자세한 정보는 package.json을 보세요.