npm workspaces 번역해드려요
이 글은 npm 공식 문서를 이해할 목적으로, 제가 이해할 수 있는 언어로 바꾸어 쓴 글입니다.
TMI
현재 개발하고 있는 멀티 클라우드 플랫폼, 스페이스원(SpaceONE) 콘솔 웹 어플리케이션은 내부적으로
- 스페이스원 디자인 시스템
- 스페이스원 콘솔 서비스 내에서 전반적으로 사용되는 코어 라이브러리
를 패키지로 설치하여 사용하고 있습니다.
그리고 이렇게 멀티레포 방식으로 사용하는게 개발 효율을 무척 떨어뜨리더군요.
(이전 글 우리 팀 FE 파트에서는 멀티레포가 왜 벅찰까 참고)
그래서 모노레포를 PoC 로 적용하려고 찾아다니다가, 간편하게 해결할 수 있는 npm workspaces를 찾아냈습니다.
설명
워크스페이스(workspaces)는 npm cli의 단일 최상위 루트 패키지 내에서 로컬 파일 시스템의 여러 패키지 관리를 지원하는 기능을 나타내는 용어입니다.
이 기능은 로컬 파일 시스템에서 연결(link)된 패키지를 처리하는 훨씬 더 간소화된 워크플로우를 구성합니다.
npm install
의 일부로 연결(link) 프로세스를 자동화합니다.- 현재
node_modules
폴더에 심볼릭 링크되어야 하는 패키지에 대한 참조를 추가하기 위해npm link
를 수동으로 사용하지 않아도 됩니다.
워크스페이스는 package.json
의 workspaces
에 명시적으로 정의된 현재 로컬 파일 시스템 내의 중첩 패키지들이며, npm install
을 하는 동안 자동으로 심볼릭 링크되어 마치 단일 워크스페이스인 것처럼 여겨집니다.
workspace 정의
워크스페이스는 package.json
파일의 workspaces
속성을 통해 정의됩니다.
예:
{
"name": "my-workspaces-powered-project",
"workspaces": [
"packages/a"
]
}
현재 작업 디렉토리(.
) 에
- 위의 예시 파일(
package.json
)이 있고 - Node.js 패키지를 정의하는
package.json
파일을 가지고 있는packages/a
폴더가 있는 경우
아래와 같이 표현할 수 있습니다.
.
+-- package.json
`-- packages
+-- a
| `-- package.json
이 현재 작업 디렉토리(.
) 에서 npm install
을 실행했을 때 예상되는 결과는, 폴더 packages/a
가 현재 작업 디렉토리의 node_modules
폴더에 심볼릭 링크된다는 것입니다.
예상되는 결과를 아래와 같이 표현할 수 있습니다.
.
+-- node_modules
| `-- a -> ../packages/a
+-- package-lock.json
+-- package.json
`-- packages
+-- a
| `-- package.json
workspace 시작하기
npm init 를 사용하여 새 워크스페이스를 정의하는 데 필요한 단계를 자동화할 수 있습니다.
예를 들어 이미 package.json
가 정의된 프로젝트에서 다음을 실행할 수 있습니다.
npm init -w ./packages/a
이 명령은 필요한 경우 package.json
이나 누락된 폴더들을 생성하는 동시에, 루트 프로젝트의 package.json
에 workspaces
속성을 적절하게 구성하는지 확인합니다.
workspace에 종속성 추가
workspace
config를 사용하여 워크스페이스의 종속성을 직접 추가/제거/업데이트하는 것이 가능합니다.
다음 구조로 예를 들어볼게요.
.
+-- package.json
`-- packages
+-- a
| `-- package.json
`-- b
`-- package.json
workspace
config를 사용하여 npm installer에게 어느 워크스페이스의 종속성으로 해당 패키지가 추가되어야 하는지를 알릴 수 있습니다.
아래는 a
워크스페이스에 abbrev
패키지 종속성을 추가하려는 경우에 대한 예시입니다.
npm install abbrev -w a
참고: uninstall
, ci
등과 같은 다른 명령도 동일하게 동작합니다.
워크스페이스 사용
Node.js가 모듈 확인을 처리하는 방법을 감안할 때, 정의된 package.json
의 name
을 워크스페이스의 이름으로 사용할 수 있습니다.
위에서 정의한 예제에 이어, a
워크스페이스 모듈이 필요한 Node.js 스크립트도 만들어 보겠습니다.
예:
// ./packages/a/index.js
module.exports = 'a'
// ./lib/index.js
const moduleA = require('a')
console.log(moduleA) // -> a
다음과 같이 실행: node lib/index.js
node_modules
resolution의 특성은, 워크스페이스들이 개별 워크스페이스를 요구(require)할 수 있는 portable한 워크플로우가 가능하게 해줍니다.
또한 중첩된(nested) 워크스페이스들을 다른 곳에서도 사용할 수 있도록 배포할 수 있게 합니다.
워크스페이스 컨텍스트에서 명령 실행
workspace
설정 옵션을 사용하여, 구성된 워크스페이스의 컨텍스트에서 명령을 실행할 수 있습니다.
npm run
다음은 중첩된 워크스페이스의 컨텍스트에서 명령 을 사용하는 방법에 대한 간단한 예입니다.
여러 워크스페이스를 포함하는 프로젝트의 경우, 예:
.
+-- package.json
`-- packages
+-- a
| `-- package.json
`-- b
`-- package.json
workspace
옵션을 사용하여 명령을 실행하면, 해당하는 특정 워크스페이스의 컨텍스트에서 지정된 명령을 실행할 수 있습니다.
예:
npm run test --workspace=a
그러면 ./packages/a/package.json
파일 내에 정의된 test
스크립트가 실행됩니다.
여러 워크스페이스를 대상으로 하기 위해 명령줄에서 이 인수를 여러 번 지정할 수도 있습니다.
예:
npm run test --workspace=a --workspace=b
workspaces
(복수형) 옵션을 사용하여, 구성된 모든 워크스페이스의 컨텍스트에서 해당 명령을 실행할 수도 있습니다. 예:
npm run test --workspaces
./packages/a
및 ./packages/b
모두에서 test
스크립트를 실행합니다 .
명령은 각 package.json
에서 나타나는 워크스페이스 순서대로 실행됩니다.
{
"workspaces": [ "packages/a", "packages/b" ]
}
아래 케이스의 실행 순서는 위 케이스의 실행 순서와 다릅니다.
{
"workspaces": [ "packages/b", "packages/a" ]
}
누락된 스크립트 무시
모든 workspace가 npm run
명령으로 실행되는 스크립트를 구현할 필요는 없습니다.
--if-present
플래그 와 함께 명령을 실행하면 npm은 대상 스크립트가 없는 workspace는 무시합니다.
npm run test --workspaces --if-present