devtools

Yarn 썸네일

모노레포 도입기


프로젝트를 시작하고 개발환경을 잡을때, 이전까지는 별 고민없이 npm 을 이용하여 프로젝트를 구성하였다. yarn 도구가 더 최근에 나온것이니 더좋은 부분이 있겠지만 생각은 했었다. 하지만 내 회사는 기본적으로 프론트엔드 개발자가 2명밖에 없어서 개발환경에 큰 지장이 없는 이상 쓰던 도구를 쓰고, 개인 프로젝트를 할때도 npm을 쓰는게 크게 불편함이 없었다.

컴포넌트 열심히 만들었는데 ..


지금 회사는 어드민 타입의 프로젝트가 대부분이다. 그래서 React 어드민 프로젝트를 N번째 만들고 있을때 그런 생각이 들었다.

1. 프로젝트 별로 통일감 있는 스타일을 구현하고 싶다.
2. A라는 프로젝트에서 만든 컴포넌트를 B프로젝트에서도 사용하고 싶다.
3. 컴포넌트뿐만 아니라 utils, image lib 등 어드민 사이트에서 자주 쓰이는 자원들을 공유하고 싶다.

위 질문들을 해결하려고 이것저것 찾아본 결과, yarn berry를 이용해 프론트엔드 workspace 환경을 구성할 수 있고, 프로젝트별로 자원이 공유 가능할 것 같다는 자료를 찾아보고 바로 도입해보기로 했다.

Multirepo와 Monorepo의 차이


멀티레포와 모노레포의 차이도 자연스레 찾아보게 됬다. Multirepo 는 프로젝트별 저장소를 따로만들어서 각각 관리하는 방식이다. Monorepo는 여러개의 프로젝트를 하나의 저장소에서 관리할 수 있는 방식을 말한다.

Monorepo

모노레포 구성도

단점
– 코드 재사용성이 용이하고 중복코드를 줄일 수 있다.
– 하나의 레포지토리에서 함께 작업하며, 여러 서비스에 손쉽게 접근 가능하다.
– 레포지토리는 항상 모든 서비스가 연동된 올바른 상태를 유지한다.
단점
– 의존성 연결이 쉽기 때문에 오히려 과도한 의존 관계가 나타날 수 있다.

Multirepo

멀티레포 구성도

장점
– 프로젝트별 독립적인 구성이 가능하다
– 레포지토리 별로 오너를 지정할 수 있다.
– 코드 베이스가 아예 나뉘어 있고, 서로간의 작업 충돌로 마스터 코드가 깨질 가능성이 적다.
단점
– 코드 재사용이 쉽지 않으므로, 중복 코드 가능성이 높아지고 다른 레포지토리의 코드를 사용하기 위해서 해야 할 작업들이 존재한다.

모노레포 구조 생성


yarn을 설치해준다.

npm install -g yarn

workspace로 사용할 디렉토리에서 아래 명령어를 통해 yarn berry를 초기화 해준다.

yarn set version berry

여기서 추가로 workspace 구성을 해줘야 한다.
https://9yujin.tistory.com/100 블로그를 보고 모노레포 개념과 디렉토리를 구성하는데 많이 참조했다.

├── apps
│   └── projectA 
│       └─package.json
└── shared
    ├── ui # 공용 components 모음
    │   └─package.json
    └── utils # 공용 utils
.yarn 
.yarnrc.yaml
package.json  # 어드민 프로젝트에서 자주쓰이는 lib 모음

레포지토리 rootpackage.json안에 공용으로 사용할 dependencies를 명시해주고 workspaces 설정을 해준다.

{
  "name": "monorepo",
  "packageManager": "yarn@4.2.1",
  "private": true,
  "workspaces": {
    "packages": [
      "apps/*",
      "shared/*"
    ]
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    ....
  }
}

다음으로는 yarn set version berry 단계에서 생성됬던 .yarnrc.yml 파일에 속성을 추가해줘야한다. 초기 생성에는 yarnPath 값밖에 없지만 nodeLinker 라는 값을 추가로 넣어야한다. 여기에는 node-modules, pnp 두가지 모드가 있다.

nodeLinker: node-modules # pnp or node-modules
yarnPath: .yarn/releases/yarn-4.2.1.cjs

projectA에 있는 라이브러리를 root로 모두 옮겨줬으므로, 해당 프로젝트의 package.json에 명시된 dependenciesnode_modules폴더를 제거해줬다. 해당 프로젝트를 yarn 명령어로 관리할 수 있도록 속성을 추가해준다.

{
  "name": "project-a",
  "packageManager": "yarn@4.2.1", // 속성 추가
  "version": "0.1.0",
  "private": true,
  "homepage": ".",
  "dependencies": {
    "@shared/ui": "workspace:shared/ui",
    "@shared/utils": "workspace:shared/utils"
  },
}

projectA 프로젝트에 dependenciesshared 디렉토리의 자원을 사용하려고 명시해주었다. 이렇게 하면 프로젝트별로 루트의 shared 디렉토리의 자원을 공통적으로 가져다가 사용할 수 있다.
프로젝트별로 명시된 스크립트가 있다면 root 경로에서 아래와 같은 명령어를 통해 해당 프로젝트의 스크립트를 실행할 수 있다.

yarn workspace project-a start
yarn workspace project-a build

Leave a comment