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 지원

workspaces plugin이란 yarn의 workspace를 좀 더 쉽게 관리하기 위해 제공되는 플러그인

yarn workspace 명령어를 사용해서 워크스페이스에 속한 패키지들에 대해 일괄적으로 작업을 수행할 수 있다.

node_modules 문제점

  • 의존성 탐색 알고리즘 비효율

    • 모듈을 검색할 때 의존성 경로의 깊이 만큼 상위 node_modules 를 검색하게 된다.

  • node_modules 폴더 아래에 수 많은 패키지가 저장되어 공간을 많이 차지하게 되고 그만큼 설치하는데 오래 걸린다.

  • 유령 의존성이란 프로젝트에 실제로 사용하지 않지만 lock 파일에는 존재하는 의존성 패키지

    • 의존성 중복 방지를 위한 호이스팅 기법의 Side Effect

    • 불필요한 공간을 차지하고 느리게 만든다.

패키지 매니저(npm, yarn)에서 중복되는 의존성 설치를 방지하기 위해 호이스팅기법을 사용한다.

Plug & Play

패키지 의존성을 설치할 때, node_modules 폴더를 생성하지 않고, 의존성 패키지들을 .yarn/cache에 수평적으로 압축파일로 설치하여 필요한 패키지를 빠르게 가져와서 사용하는 방식

  • 여러 패키지에서 중복되는 의존성 패키지들을 전역으로 설치해서 재사용하는 방식

  • 해당 모듈을 사용하기 전 메모리에서 ZipFS라는 도구를 사용해서 압축을 해제하고 필요한 부분만 추출하여 가져오는 방식으로 효율적으로 접근한다.

  • 의존성이 .yarn/cache에 수평적으로 설치되므로 모든 패키지에 대한 접근 시간이 O(1)

  • 호이스팅 방식을 사용하지 않기 떄문에 유령 의존성이 발생하지 않는다.

  • 압축파일로 된 의존성을 git으로 관리하게 되면 설치 과정을 생략(zero-install)할 수 있다.

PnP 모드를 지원하지 않는 라이브러리를 사용하게 된다면 의존성 관리 방식을 node_modules 방식으로 변경해서 사용해야 한다.

Monorepo 환경 세팅하기

NVM

Node Version Manager, 여러 노드 버전을 스위칭하여 관리할 수 있게 도와주는 도구

  • 여러 프로젝트에서 서로 다른 Node 버전을 사용할 수 있게 도와준다.

  • 각 프로젝트마다 Node를 관리할 필요가 없게 된다.

환경변수 설정하기

설치된 Node version list 확인

'abumalick.vscode-nvm' vscode extension 추가

vscode에서 nvm을 사용하기 쉽도록 도와주는 확장 프로그램

프로젝트 루트경로에 .nvmrc 설정 파일을 추가하여 사용할 노드 버전을 지정하면 nvm use 명령어를 실행하지 않고도 특정 노드 버전을 자동으로 사용할 수 있도록 관리해준다.

.nvmrc

해당 프로젝트의 vscode가 열리면 자동으로 nvm use 명령어가 실행되어 지정한 노드버전을 사용하도록 변경해준다.

nvm use는 로컬에 설치된 특정 노드 버전을 사용하도록 설정하는 명령어이다.

.vscode/extensions.json에 추가

.vscode/extension.json 에 추가하여 자동으로 해당 익스텐션을 설치할 수 있도록 설정하자.

Yarn Berry Workspace

yarn이 기본적으로 설치되어 있다고 가정

yarn version 변경하기

Yarn workspace 생성하기

루트 워크스페이스는 모든 프로젝트에 공통적으로 사용되는 패키지 의존성을 한번에 관리할 수 있다.

즉, 하위 워크스페이스에서 yarn install 명령어를 통해 루트에 설치된 패키지들을 사용할 수 있다.

yarn init -w 명령어는 yarn을 이용해서 프로젝트를 생성하는 명령어이다. -w 옵션은 현재 디렉토리를 루트 워크스페이스 디렉토리로 설정 (package.json 생성됨)

yarn berry cli 명령어 참고

yarn cache 확인하기

  • enableGlobalCache 설정은 .yarnrc.yml 파일 내부에 설정 되있는것을 확인해 볼 수 있다.

apps/ 디렉토리 생성

실제로 서비스할 어플리케이션들을 모아놓는 디렉토리

packages/apps/에서 사용할 공통 라이브러리 패키지를 모아놓는 디렉토리

package.json

추가한 apps 디렉토리를 워크스페이스 디렉토리의 package.json에 등록

프로젝트 패키지 추가해보기

apps/ 디렉토리 내에서 프로젝트를 생성해보자.

프로젝트 생성이 완료되었다면 해당 프로젝트의 package.json 을 수정

package.json

패키지의 범위를 설정하기 위해 프로젝트의 네임을 @ 접두어를 붙힌 @org/package 형식으로 변경

워크스페이스로 돌아가서 상태를 갱신

프로젝트가 추가되면 워크스페이스로 돌아가서 상태를 갱신 해주어야 한다.

해당 정보는 .pnp.cjs 에서 관리 된다.

yarn workspace [package name] [scripts] 로 워크스페이스 특정 패키지의 명령어를 사용하여 간단하게 실행할 수 있다.

.pnp.cjs란? yarn berry pnp 관련 정보를 모아놓은 캐시 파일로 모든 의존성의 메타 정보(zip 경로, 의존성)와 ZipFS에 대한 처리 코드가 들어있다

Typescript 설정하기

타입스크립트 코드에 빨간줄이 생기면서 인식을 못하는 에러가 발생한다.

  • yarn berry는 node_modules 대신 패키지 의존성을 zip 파일 형태로 .yarn/cache에 저장하여 관리하는 plugin & play 모드를 사용한다.

  • 이런 방식의 차이 때문에 추가적인 설정이 필요하다.

yarn dlx @yarnpkg/sdks vscode

  • yarn dlx 명령어를 통해 @yarnpkg/sdks 패키지를 vscode 환경에 설치

  • yarn에서 제공하는 플러그인 중 하나인 yarn sdk는 yarn을 이용해서 설치한 프로그램을 실행할 수 있도록 도와준다.

  • 즉, vscode가 zip 파일로 된 패키지들을 읽어올 수 있게끔 설정하는 것

  • typescript, eslint, prettier 이 패키지들은 .yarn/sdks 내에 설치된다.

'arcanis.vscode-zipfs' vscode extension 추가

Yarn SDK와 함께 사용하면 캐시에서 파일을 원활하게 열고 편집할 수 있다.

.vscode/extensions.json에 추가

Next.js 모노레포 Typescript 이슈

다른 패키지(React.js)에서 내보내는 컴포넌트를(ts) 사용할 때 ts 해석을 하지 못한다.

  1. javascript로 변환시켜 주는 툴 설치

  1. next.config.json 수정

공통 패키지를 만들어보기

여러 패키지에서 공유하여 사용할 유틸 함수나 라이브러리를 관리하기 위해 packages/lib 폴더를 생성

package.json name 수정

tsconfig.json 설정

패키지를 추가했다면 워크스페이스로 돌아가서 yarn 명령어를 입력해 갱신해주자.

다른 패키지에 의존성 추가하기

루트 워크스페이스 경로로 돌아가서 A 패키지에 B 패키지 의존성을 추가해보자.

@jtwjs/web 패키지를 확인해보면 아래와 같이 의존성이 추가된걸 확인할 수 있다.

개발환경 설정 공유하기

tsconfig 설정 공유하기

프로젝트에서 공통적으로 사용되는 타입스크립트 설정을 한 곳에서 관리하여 중복되는 설정을 최소화한다.

  1. 워크스페이스 경로에 tsconfig.base.json 파일을 생성하여 공통적으로 사용할 설정

  2. 각 프로젝트 패키지의 tsconfig.json 에서 extends 속성을 사용하여 재사용한다.

eslint & prettier 설정 공유하기

여러 패키지에서 공통적으로 사용되는 eslint & prettier 규칙을 공유하여 재사용하자.

기타 vscode 설정 추가

.vscode/settings.json
.vscode/extensions.json

Eslint & Prettier설정

eslint 설정 공유하기

eslint 잘 활용하기

Eslint 설정

가장 최상위 eslint 설정에 root: true 설정하고 커스텀을 위한 하위 eslint는 root: false 설정을 해주자.

Prettier 설정

모든 프로젝트에 공통적으로 실행할 명령어

workspace-tools 플러그인 설치

각 패키지 마다 공통적으로 동일한 네이밍의 스크립트를 일괄적으로 실행 시킬 수 있다.

yarn workspaces foreach 여러 패키지 대해 일괄적인 작업을 수행할 수 있는 명령어

  • -p: 병렬 실행

  • -v: workspace name 출력

typecheck

개별적으로 특정 스크립트 실행하려면

Deploy

Github actions

  • .github/workflows 디렉토리 내에서 워크플로우(.yml)를 생성하여 배포 작업을 정의한다.

  • 모노레포의 경우 각 하위 프로젝트에 대해 배포 작업을 개별적으로 정의해야 한다.

  • 배포하기 전 관련 의존성을 모두 설치하는 작업이 추가 되어야 한다.

  • 관련 의존성을 설치하는 작업은 각 배포 워크플로우에서 공통으로 사용되기 때문에 composite actions를 사용하여 액션을 재사용해보자.

Composite actions

....

배포 하기 전 관련 의존성 설치하는 액션

deploy.yml

workflow dispatch를 사용하여 깃헙 저장소에서 수동으로 workflow를 실행할 수 있다.

여러 워크스페이스를 관리하는 상황에서는 수동으로 배포할 워크스페이스를 선택하는 방식도 꽤 유용해 보인다.

workflow dispatch

Last updated