MonoRepo 찍먹하기

MonoRepo 찍먹하기

생성일
2023년 05월 13일
태그
MonoRepo

Background

최근 팀 내에서 MonoRepo를 도입하는 것에 대한 논의가 이루어진적이 있다.
MonoRepoPolyRepo 의 반댓말로, 하나의 레포지토리 안에서 여러 프로젝트들을 관리하는 것을 뜻한다. 팀에서 모노레포에 대한 논의가 나온 이유는 웹과 웹뷰 서비스의 통합을 위해서이다. 현재, 웹 서비스는 Next.js 로, 웹뷰 서비스는 React 로 서비스가 되고 있는데, 웹 서비스도 사실 반응형으로 이루어져 있기 때문에 동일한 서비스를 두 번이나 개발을 해야하는 것에 대해서 피로를 느끼고 있었다.
따라서, 웹뷰 서비스를 Next.js 로 마이그레이션하고 웹과 웹뷰를 모노레포로 통합하여 중첩되는 모듈이나 코드를 공통화시켜 재사용성을 높이자는 의견이다.
정식으로 도입하기로 한 것은 아니기 때문에, 개인적으로 MonoRepo 를 학습하려고 한다. 해당 아티클은 원티드 프리온보딩 5월에서 지식공유자님께서 공유해준 내용을 정리한 것이다.

살펴보기

해당 실습에서는 모노레포를 yarn workspace 로 구축한다. 필요한 스택들의 버전은 다음과 같다.
  • node - v16 이상
  • yarn - v1, 추후에 version berry로 업그레이드함

1. yarn version 변경

yarn 버전을 v1에서 berry로 변경한다.
$ yarn set version berry

2. yarn workspace

이번 실습에서는 yarn workspaceMonoRepo 를 구축한다.
$ yarn init -w

3. package.json 수정

root directory의 package.json 을 수정한다. 실습에서 특정 서비스의 코드들은 /apps 경로에 소스 코드가 담겨있다고 가정한다.
{ "name": "monorepo_excercise", "packageManager": "yarn@3.5.1", "private": true, "workspaces": [ // 서비스되는 소스 코드의 경로 "apps/*", ], "devDependencies": { "typescript": "^5.0.4" } }

4. apps 디렉토리에 create next app

/apps 디렉토리는 Next.js 기반 서비스이다.
$ cd app $ yarn create next-app .

5. apps 디렉토리의 package.json 수정

여기서 핵심은 package.json name에 @을 추가해주는 것이다.
{ // @가 핵심 "name": "@wanted/web", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@types/node": "20.1.1", "@types/react": "18.2.6", "@types/react-dom": "18.2.4", "@wanted/lib": "workspace:^", "eslint": "8.40.0", "eslint-config-next": "13.4.1", "next": "13.4.1", "react": "18.2.0", "react-dom": "18.2.0", "typescript": "5.0.4" } }
각 디렉토리는 root에서 실행시킬 수 있다. /apps 디렉토리에서 서비스되는 프로젝트는 다음과 같이 실행시킬 수 있다.
$ yarn workspace @wanted/web run dev

6. TypeScript 오류 해결

yarn berry 는 기존에 node_modules 로 모듈을 불러오는것에 비해 plug n play 로 불러오기 때문에 TypeScript 오류가 발생한다. 이는 다음과 같이 해결할 수 있다.
$ yarn add -D typescript $ yarn dlx @yarnpkg/sdks vscode

7. 공통 패키지 만들어보기

이제 MonoRepo 의 강력함을 경험하기 위한 작업을 진행할 것이다. 공통 패키지를 만들어 여러 서비스에 사용될 수 있도록 할 것이다.
해당 패키지의 디렉토리는 /packages/lib 이다.
# 해당 디렉토리에 package.json을 설치한다. $ yarn init $ yarn add -D typescript
해당 디렉토리에서 마찬가지로 package.json 을 수정한다.
{ // @가 마찬가지로 핵심이다! "name": "@wanted/lib", "packageManager": "yarn@3.5.1", "main": "./src/index.ts", "dependencies": { "typescript": "^5.0.4" } }
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"] }
 
여러 서비스에서 사용할 수 있는 메서드를 만들어보자.
// packages/lib/src/index.ts export const sayHello = () => { return 'Say Hello From packages lib'; }

8. 의존성 주입

여러 서비스에서 공통 패키지에 만든 sayHello 메서드를 사용하기 위해서는 의존성을 주입해주는 작업이 필요하다. 해당 작업은 root directory에서 진행한다.
# @wanted/web에 @wanted/lib 의존성을 추가한다. $ yarn workspace @wanted/web add @wanted/lib
 
해당 작업이 진행되면, /apps/wanted 디렉토리의 package.json 에서 의존성이 주입된 것을 확인할 수 있다.
"dependencies": { "@types/node": "20.1.1", "@types/react": "18.2.6", "@types/react-dom": "18.2.4", // @wanted/lib 의존성이 잘 주입되었다. "@wanted/lib": "workspace:^", "eslint": "8.40.0", "eslint-config-next": "13.4.1", "next": "13.4.1", "react": "18.2.0", "react-dom": "18.2.0", "typescript": "5.0.4" }

9. apps 서비스에서 공통 패키지의 메서드 사용해보기

이제 @wanted/web 에서 sayHello 메서드를 사용해볼 것이다.
// /apps/wanted/src/pages/index.tsx // 사용하기 import { sayHello } from '@wanted/lib';

References

댓글

guest