Yarn Berry Workspace
Yarn Berry WorkSpace란?
모노레포 방식으로 여러 프로젝트(패키지)를 단일 레포지토리에서 관리하는 방식
의존성 관리를 한 곳에서 관리하기 때문에 공통된 의존성 모듈을 재사용하고, 중복되는 의존성 설치 문제를 피할 수 있다.
workspace: 모노레포의 패키지를 의미
Yarn Berry
Yarn v2 에서 사용하는 패키지 매니저
기본적으로 명시적인 의존관계를 나타내야 사용 가능
node_modules
에 패키지를 저장하는 방식이 아닌 패키지를 압축하여 한개의 파일을.yarn/cache/
폴더에 수평적으로 저장한다. 이러한 방식을 Plug'n'Play(PnP) 라 한다.수평적으로 존재하여 빠르게 탐색 가능
압축파일을 설치하기 때문에 파일 개수가 감소하여 설치가 빠름
Zero Install을 이용하여 저장소에서 함께 관리 가능
저장소에 올라가기 때문에 저장소 자체가 매우 커지게 될 수 있음 (push, pull등 느리게 됨)
Zero Install이 아예 설치하지 않는것은 아님, 여러 환경에서 새로운 파일을 만들어내는 경우 때문에 설치 필요
Phantom Dependency가 발생하지 않음
PnP 모드를 기본적으로 지원
PnP 방식은 IDE에서 직접 사용하는 많은 도구들을
SDK
를 통해 우회 호출할 수 있도록 추가적인 설정 필요
workspaces plugin
지원
node_modules 문제점
의존성 탐색 알고리즘 비효율
모듈을 검색할 때 의존성 경로의 깊이 만큼 상위
node_modules
를 검색하게 된다.
node_modules
폴더 아래에 수 많은 패키지가 저장되어 공간을 많이 차지하게 되고 그만큼 설치하는데 오래 걸린다.유령 의존성이란 프로젝트에 실제로 사용하지 않지만 lock 파일에는 존재하는 의존성 패키지
의존성 중복 방지를 위한 호이스팅 기법의 Side Effect
불필요한 공간을 차지하고 느리게 만든다.
Plug & Play
패키지 의존성을 설치할 때,
node_modules
폴더를 생성하지 않고, 의존성 패키지들을.yarn/cache
에 수평적으로 압축파일로 설치하여 필요한 패키지를 빠르게 가져와서 사용하는 방식
여러 패키지에서 중복되는 의존성 패키지들을 전역으로 설치해서 재사용하는 방식
해당 모듈을 사용하기 전 메모리에서 ZipFS라는 도구를 사용해서 압축을 해제하고 필요한 부분만 추출하여 가져오는 방식으로 효율적으로 접근한다.
의존성이
.yarn/cache
에 수평적으로 설치되므로 모든 패키지에 대한 접근 시간이 O(1)호이스팅 방식을 사용하지 않기 떄문에 유령 의존성이 발생하지 않는다.
압축파일로 된 의존성을 git으로 관리하게 되면 설치 과정을 생략(zero-install)할 수 있다.
Monorepo 환경 세팅하기
NVM
Node Version Manager, 여러 노드 버전을 스위칭하여 관리할 수 있게 도와주는 도구
여러 프로젝트에서 서로 다른 Node 버전을 사용할 수 있게 도와준다.
각 프로젝트마다 Node를 관리할 필요가 없게 된다.
brew install nvm
환경변수 설정하기
mkdir ~/.nvm
vi ~/.zshrc
export NVM_DIR="$HOME/.nvm"
[ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh" # This loads nvm
[ -s "/usr/local/opt/nvm/etc/bash_completion" ] && . "/usr/local/opt/nvm/etc/bash_completion" # This loads nvm bash_completion
source ~/.zshrc
설치된 Node version list 확인
nvm ls
'abumalick.vscode-nvm' vscode extension 추가
vscode에서 nvm을 사용하기 쉽도록 도와주는 확장 프로그램
프로젝트 루트경로에 .nvmrc
설정 파일을 추가하여 사용할 노드 버전을 지정하면 nvm use
명령어를 실행하지 않고도 특정 노드 버전을 자동으로 사용할 수 있도록 관리해준다.
.nvmrc
.nvmrc
// galium 이란 별칭으로 사용되는 버전 16.20.0을 사용하겠다 선언
lts/gallium
해당 프로젝트의 vscode가 열리면 자동으로 nvm use 명령어가 실행되어 지정한 노드버전을 사용하도록 변경해준다.
nvm use
는 로컬에 설치된 특정 노드 버전을 사용하도록 설정하는 명령어이다.

.vscode/extensions.json
에 추가
.vscode/extensions.json
에 추가
.vscode/extension.json
에 추가하여 자동으로 해당 익스텐션을 설치할 수 있도록 설정하자.
{
"recommendations": ["abumalick.vscode-nvm"]
}
Yarn Berry Workspace
yarn이 기본적으로 설치되어 있다고 가정
yarn version 변경하기
// yarn 버전 확인
yarn -v
// yarn berry 버전 활성화
yarn set version berry
// yarn 버전 확인
yarn -v // 현 시점 4.0.2
Yarn workspace 생성하기
루트 워크스페이스는 모든 프로젝트에 공통적으로 사용되는 패키지 의존성을 한번에 관리할 수 있다.
즉, 하위 워크스페이스에서
yarn install
명령어를 통해 루트에 설치된 패키지들을 사용할 수 있다.
yarn init -w
명령어는 yarn을 이용해서 프로젝트를 생성하는 명령어이다.
-w
옵션은 현재 디렉토리를 루트 워크스페이스 디렉토리로 설정 (package.json 생성됨)
yarn init -2 -w
yarn cache 확인하기
yarn config enableGlobalCache

yarn config set enableGlobalCache false

enableGlobalCache
설정은.yarnrc.yml
파일 내부에 설정 되있는것을 확인해 볼 수 있다.
apps/ 디렉토리 생성
실제로 서비스할 어플리케이션들을 모아놓는 디렉토리
mkdir apps
package.json
추가한 apps 디렉토리를 워크스페이스 디렉토리의 package.json에 등록
{
"name": "mono-test",
"packageManager": "yarn@3.5.1",
"private": true,
// 워크스페이스에서 관리할 패키지 디렉토리 경로를 설정
"workspaces": [
"apps/*", // 생성한 apps/ 디렉토리를 추가
"packages/*"
]
}
프로젝트 패키지 추가해보기
apps/
디렉토리 내에서 프로젝트를 생성해보자.
yarn init
프로젝트 생성이 완료되었다면 해당 프로젝트의 package.json
을 수정
package.json
패키지의 범위를 설정하기 위해 프로젝트의 네임을
@
접두어를 붙힌@org/package
형식으로 변경
{
"name": "@jtwjs/web",
"version": "0.1.0",
"private": true,
//...//
}
워크스페이스로 돌아가서 상태를 갱신
프로젝트가 추가되면 워크스페이스로 돌아가서 상태를 갱신 해주어야 한다.
해당 정보는
.pnp.cjs
에서 관리 된다.
yarn workspace [package name] [scripts]
로 워크스페이스 특정 패키지의 명령어를 사용하여 간단하게 실행할 수 있다.
cd ../../
yarn // 상태 갱신
yarn workspace @jtwjs/web run dev // 실행 확인
Typescript 설정하기
타입스크립트 코드에 빨간줄이 생기면서 인식을 못하는 에러가 발생한다.
yarn berry는
node_modules
대신 패키지 의존성을zip
파일 형태로.yarn/cache
에 저장하여 관리하는plugin & play
모드를 사용한다.이런 방식의 차이 때문에 추가적인 설정이 필요하다.
yarn add -D typescript
yarn dlx @yarnpkg/sdks vscode
'arcanis.vscode-zipfs' vscode extension 추가
Yarn SDK와 함께 사용하면 캐시에서 파일을 원활하게 열고 편집할 수 있다.
.vscode/extensions.json
에 추가
.vscode/extensions.json
에 추가{
"recommendations": [
"abumalick.vscode-nvm",
"arcanis.vscode-zipfs"
]
}
공통 패키지를 만들어보기
여러 패키지에서 공유하여 사용할 유틸 함수나 라이브러리를 관리하기 위해
packages/lib
폴더를 생성
// lib 폴더 이동
cd packages/lib
// pacakge.json 파일 생성
yarn init
// typescript 설치
yarn add typescript
package.json
name 수정
package.json
name 수정{
"name": "@jtwjs/lib",
"main": "./src/index.ts",
}
tsconfig.json 설정
touch tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"strict": true,
"useUnknownInCatchVariables": true,
"allowJs": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"newLine": "lf",
"module": "ESNext",
"moduleResolution": "node",
"target": "ESNext",
"lib": ["ESNext", "dom"],
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"baseUrl": "./src",
"noEmit": false,
"incremental": true,
"resolveJsonModule": true,
"paths": {}
},
"exclude": ["**/node_modules", "**/.*/", "./dist", "./coverage"],
"include": ["**/*.ts", "**/*.js", "**/.cjs", "**/*.mjs", "**/*.json"]
}
다른 패키지에 의존성 추가하기
루트 워크스페이스 경로로 돌아가서 A 패키지에 B 패키지 의존성을 추가해보자.
// @jtwjs/web 패키지에 @jtwjs/lib 패키지를 추가
yarn workspace @jtwjs/web add @jtwjs/lib
@jtwjs/web 패키지를 확인해보면 아래와 같이 의존성이 추가된걸 확인할 수 있다.
개발환경 설정 공유하기
tsconfig 설정 공유하기
프로젝트에서 공통적으로 사용되는 타입스크립트 설정을 한 곳에서 관리하여 중복되는 설정을 최소화한다.
워크스페이스 경로에
tsconfig.base.json
파일을 생성하여 공통적으로 사용할 설정각 프로젝트 패키지의
tsconfig.json
에서 extends 속성을 사용하여 재사용한다."extends": "../../tsconfig.base.json",
// tscofnig.base.json
{
"compilerOptions": {
"strict": true,
"useUnknownInCatchVariables": true,
"allowJs": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true,
"newLine": "lf"
},
"exclude": ["**/node_modules", "**/.*/"]
}
eslint & prettier 설정 공유하기
여러 패키지에서 공통적으로 사용되는 eslint & prettier 규칙을 공유하여 재사용하자.
yarn add prettier eslint eslint-config-prettier eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks eslint-import-resolver-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser -D
yarn dlx @yarnpkg/sdks
기타 vscode 설정 추가
Eslint & Prettier설정
모든 프로젝트에 공통적으로 실행할 명령어
workspace-tools
플러그인 설치각 패키지 마다 공통적으로 동일한 네이밍의 스크립트를 일괄적으로 실행 시킬 수 있다.
yarn plugin import workspace-tools
"scripts": {
//g:는 global 관례이다.
"g:typecheck": "yarn workspaces foreach -pv run typecheck"
},
typecheck
"scripts": {
"typecheck": "tsc --project ./tsconfig.json --noEmit"
},
Deploy
Github actions
.github/workflows
디렉토리 내에서 워크플로우(.yml
)를 생성하여 배포 작업을 정의한다.모노레포의 경우 각 하위 프로젝트에 대해 배포 작업을 개별적으로 정의해야 한다.
배포하기 전 관련 의존성을 모두 설치하는 작업이 추가 되어야 한다.
관련 의존성을 설치하는 작업은 각 배포 워크플로우에서 공통으로 사용되기 때문에 composite actions를 사용하여 액션을 재사용해보자.
Menual Deploy (수동으로 배포하기)
workflow dispatch를 사용하여 깃헙 저장소에서 수동으로 workflow를 실행할 수 있다.
여러 워크스페이스를 관리하는 상황에서는 수동으로 배포할 워크스페이스를 선택하는 방식도 꽤 유용해 보인다.

default branch에 적용되있어야만 작동한다.
Last updated