본문 바로가기
Front-End

yarn berry로 workspace(monorepo) 구성하기

by kimik 2021. 9. 20.

Yarn Berry

프로젝트를 진행하다보면 별도의 프로젝트라 생각하고, 서버, 프론트를 나누거나 프론트서버를 데스크탑,

 

모바일로 나눠 각자의 git repository를 만들어 관리하는 경우가 있습니다.

 

백엔드와 프론트는 사용 언어가 다를경우엔 공유할 코드가 없기 때문에 나누는게 

 

여러모로 좋은점이 많지만, 백엔드 언어가 nodeJS라면 프론트도 특별한 경우가 아니면 자바스크립트로

 

이루어져 있기 때문에 프론트와 백엔드가 같은 언어를 사용하게 되고,  같은 언어를사용하면 validation이나 공통적으로

 

사용되는 함수들을 하나만 관리하여 사용할 필요가 있습니다. 이럴때 필요한것이 monorepo로 하나의 repository에서

 

2개이상의 프로젝트를 관리하는것입니다. 

 

그럼 monorepo를 설정하기 위해 monorepo가 될 폴더하나를 만들도록 합니다. (저는 monorepo로 만들었습니다.)

 

*시작전에 monorepo라는 말과 workspace를 혼용해서 사용하는데 둘은 엄연히 다르지만 이 글에서는 그냥 최상단

폴더를 지칭하는것으로 혼재되어 사용하니 참고해주세요.

 

1. yarn 설치 ( 이미 yarn이 있다면 skip)

터미널에서 yarn을 우선 설치하고,

npm install -g yarn

 

2. yarn berry 설치 및 설정

터미널에서 새로만든 폴더로 이동한 후에 

yarn set version berry

를 입력하여 yarn berry로 설정해 주도록 합니다. (yarn 1.0과 2.0이상의 yarn berry는 차이가많아 일반적으로 yarn 1.0을

 

사용하고 원하는 프로젝트에서만 berry를 사용하기 위해 특정 프로젝트 폴더 안에서만 위의 명령어를 사용합니다)

 

3. yarn berry로 프로젝트 시작

yarn -v

위의 명령어로 yarn 2.0이상이 깔렸나 확인하고( 21년 9월 20일 기준으로 3.0.2가 최신) 이상이 없다면 

yarn init

으로 프로젝트를 설정합니다.

 

그럼 package.json과 기타 파일들이생성되고 프로젝트를 시작할 준비가 되었습니다.

 

4. workspace(monorepo) 셋팅 

package.json파일을 열고 name 및에 workspace를 아래와 같이 추가합니다.

{
  "name": "monorepo",
  "private": true,
  "workspaces": {
    "packages": [
      "package/*"
    ]
  },
  "packageManager": "yarn@3.0.2"
}

위와 같이 생성하고 package폴더를 생성합니다. 위와같이 설정하면 package폴더안에 모든 폴더가 workspace에 속하게 됩니다.

 

5. project 생성

package폴더안에 본격적으로 프로젝트를 시작해보도록 하겠습니다. 

 

터미널로 package폴더로 이동 후에 

npx create-react-app front

이렇게 create-react-app으로 프로젝트를 만들어도 상관없지만, 좀더 가볍고 빌드속도가 빠른 

yarn create vite

으로 vite설정을 해보겠습니다. 

위의 명령어를 입력하면 package name입력과 어떤 프레임워크를 쓸지 선택하라고하는데 글쓴이는 

 

front > react > react-ts를 선택하여 진행하였습니다.

 

그리고 나서 package폴더안에 common폴더를 만들어서 아래와 같은 폴더 구조가 되었는지 확인합니다.

 

 

폴더 구조

6. front 서버 확인

vite혹은 cra로 구성한 폴더에 이동하여 front가 정상적으로 동작하는지 확인해봅시다.

cd front로 폴더 이동 후

yarn && yarn dev

yarn은 yarn install명령을 수행하고 yarn dev는 vite의 개발서버를 시작합니다. 

 

7. typescript 에러!!?

package/front/src/App.tsx를 열어서 확인해보면 

가장 꼴보기싫은 에러표시..

위와같이 typescript가 적용이 안될걸 볼 수 있습니다.

 

yarn berry는 npm과 모듈을 불러오는 방식이 다르기 때문에 생기는 문제입니다. 

 

8. typescript, eslint, prettier 설치

터미널에서 root로 이동(monorepo)한 후에

yarn add -D typescript prettier eslint

이 3가지를 설치해주도록 합시다. 그리고 vscode를 사용중이라는 가정하에 

yarn dlx @yarnpkg/sdks vscode

로 sdk를 설치해줍니다.

 

여기서 주의할점은 

 

1. yarn berry로 프로젝트를 실행해야할때 위의 순서를 무시하고 sdk부터 설치하지말고 반드시 typescript처럼 문법에 영향을

 

주는 package들을 먼저 설치하고 sdk를 설치해야합니다!

 

2. 무조건 workspace가 root폴더로 열려있어야합니다 (vscode의 경우) 무슨말이냐면 vscode로 프로젝트 폴더를 오픈해서

 

편집을 시작할때 우리가 만든 workspace폴더 상위 폴더를 열어서 workspace안에 tsx파일을 건드리면 무조건 

 

typescript에러로 위의 스크린샷처럼 에러 범벅이 됩니다! 항상 workspace폴더를 root로!

 

제대로 설치가 되었다면 .yarn/sdks/ 경로에 패키지에 맞는 sdk가 설치된걸 확인할 수 있습니다. 

 

vscode이외에 다른 에디터를 사용한다면 https://yarnpkg.com/getting-started/editor-sdks 를 확인해주세요.

 

9. typescript sdk 설정 방법(vscode 기준)

혹시나 vscode설정이 꼬여서 위의 스크린샷과 같이 tsx에서 typescript에러가 난다면, vscode하단에 

vscode 하단 영역

4.4.3-sdk부분을 클릭하면 typescript버젼을 선택할 수 있는 아래와 같은 창에서 sdk를 선택하면됩니다.

2번째의 sdk선택

 

 

10. project간의 설정 공유

monorepo의 장점 중 하나는 프로젝트간의 코드공유도 있지만, 설정(tsconfig, eslint, prettier)을 모두 공유한다는 점입니다.

 

monorepo바로 아래에 tsconfig.base.json이라는 파일을 만들고,

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": false,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
}

위의 내용을 붙여넣습니다.

 

그리고 package/front폴더 내에 tsconfig.json의 내용을

{
  "extends": "../tsconfig.base.json",
  "include": ["./src"]
}

위와 같이 수정하면 tsconfig.base.json을 설정과 extends하여 사용 할 수 있습니다.

 

만약 프로젝트 별로 별도의 tsconfig설정을 적용하고 싶다면,

{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {
    "baseUrl": ".",
    "types": ["vite/client"],
    "paths": {
      "~/*": ["src/*", "static/*"]
    },
  },
  "include": ["./src"]
}

위와같이 compilerOptions를 기존처럼 사용하면 해당 프로젝트에서만 설정이 적용됩니다. (위의 소스는 예제일 뿐입니다.)

 

그리고 eslint와 prettier는 프로젝트별 설정을 할 일이 적기 때문에 root에 .prettierrc파일과 .eslintrc.js를 만들어 모든

 

프로젝트에서 동일하게 적용되도록 합니다. (eslint와 prettier설정은 사람마다 다르므로 자기 입맛에 맞게!)

 

11. 프로젝트간에 코드 공유

터미널로 package폴더안에 만들었던 common으로 이동한뒤에 

yarn init

으로 package.json파일을 생성합니다. 그리고 

{
  "name": "@monorepo/common",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "author": "",
  "license": "ISC"
}

위와같이 수정해준다음, comon 폴더에 index.ts파일을 생성합니다. 

 

위와같은 구조가 되면 오케이

그리고 index.ts를 열어 

const str: string = "이 변수를 공유해보자!";

export default str;

간단하게 변수를 만들고 export해봅시다.

 

그럼 이걸 가져올 front 프로젝트로 이동하여, package.json을 아래와같이 수정합니다.

...
  "dependencies": {
    "@monorepo/common": "*",
    "react": "^17.0.0",
    "react-dom": "^17.0.0"
  },
 ...

dependencies부분에 common의 package name을 입력하고 버전은 *로 입력합니다.

 

그리고 터미널에서 front혹은 root로 이동하여

yarn

위의 명령어를 입력하여 project끼리 연결을 해줍니다. 

(위와같은 순서로했을때 패키지를 npm서버에서 탐색하는 경우가있는데, 이럴땐 front를 삭제하고 다시 vite나 cra로 설치한다음

package.json을 수정하여 yarn을 실행해줍니다.)

 

에러가 나지않고 완료되면,

 

12. front에서 common의 변수를 import하기

import React, { useState } from 'react'
import logo from './logo.svg'
import './App.css'
import str from '@monorepo/common'

function App() {
  const [count, setCount] = useState(0)
  console.log(str)
...

front에 App.tsx로 이동하여 위와같이 수정하고 서버를 구동시키면 

 

정상적으로 console 노출

 

정상적으로 import되어 console.log에 표시되었습니다! 

 

완성된 레포는 https://github.com/kimik-hyum/yarn-berry-monorepo 여기를 참고해주세요! 

 

* 위의 레포는 eslint, prettier는 설정되어있지않습니다. 그리고 zero install이라 용량이 큽니다! (clone 후 yarn버전을 맞춰주시고, yarn 커맨드 입력한 후에 fornt 폴더로 이동해 yarn dev를 입력해주세요.)

댓글