notes
Architect - 모노레포, 터보 레포
모노레포·Turborepo 구조와 패키지·빌드 파이프라인 구성 메모.
모노레포
모노레포 사용이유.
멀티 레포지토리에서 겪은 문제상황
- 프로젝트마다 서로 다른 컨벤션 (코드, Git/브랜치)
- 프로젝트마다 서로 다른 린트 환경과 코드 패턴들 (eslint, prettier, stylelint, tsconfig)
- 프로젝트마다 서로 다른 라이브러리/프레임워크 사용 (react, vue, next)
- 새로운 서비스(프로젝트)를 구축하기 위한 비용
- 새로운 프로젝트를 생성할 때마다 서비스의 환경과 린트 환경을 반복적으로 세팅
- 공통으로 사용하는 UI 컴포넌트, 패키지들을 새로운 환경에 맞게 반복 구현
- 중복된 코드와, 프로젝트 관리에 대한 비효율
- 각 서비스에서 사용하는 프로젝트의 라이브러리 버전이 통일되지 않음
- 공통 MDS 컴포넌트, 정책에 변경 사항이 생겼을 경우 모든 레포지토리 담당자에게 수정 요청
- 히스토리가 레포지토리 별로 흩어져 있음
- 위와 같은 문제들로 인해서 해당 레포지토리 담당자 외의 다른 팀원이 해당 레포지토리에서 작업을 하려면 코드와 환경을 파악하기 위해 많은 시간이 발생했고, 새로운 사람이 프로젝트를 맡게 되었을 때 초기 온보딩 비용이 많이 들어갔습니다.
모노레포 구성하기.
- pnpm init
- package.json에 "packageManager": "pnpm@[version예)1.0.0]" 추가하기
- pnpm.workspace.yaml 생성
- pnpm.workspace.yaml에 아래 내용 추가하기
packages:
-"packages/*"
- "apps/*";
- git init 후 ignore을 작성해주자. 다음 link를 참조 https://github.com/wixplosives/sample-monorepo/blob/main/.gitignore
폴더 구조
apps - 서비스
- user - passblock 사용자 서비스
- admin - passblock 관리자 서비스 pacakages - 공통으로 사용하는 패키지
- api - api 서버
- shared - 공통으로 사용할 components,hooks,utils (React)
공통 라이브러리
1. ag-grid - 테이블
2. lottiefile - 애니메이션
3. react-hook-form - 폼
4. tailwindcss - css
tailwindcss 를 사용하기 위해선 일단 shared에서 tailwindcss.config.js, postcss.config.js를 추가해준다.
tailwind.config.js는 아래와 같이 설정해주자.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {},
},
plugins: [],
};
아래와 같이 설정이 완료하고 tailwindcss를 이용해 컴포넌트까지 완성했다면 실제 프로젝트 tailwind.config.js 에서도 다음과 같이 추가해줘야한다.
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
"../../packages/shared/src/components/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {},
plugins: [],
};
export default config;
패키지 공유하기
pnpm --filter [패키지명 A] add [패키지명 B] --workspace
// A서비스에서 B패키지를 의존하고싶을 때
루트레벨 라이브러리 프로젝트에서 사용하기
pnpm을 사용하는 모노레포에서 루트 레벨에서 설치한 라이브러리를 하위 프로젝트에서 사용 할 수 있습니다.
그러나 이를 위해선 루트레벨의 pacakage.json 파일에서 해당 라이브러리를 dependencies에 명시적으로 추가 해주고
각 하위 프로젝트 에서도 해당 라이브러리를 dependencies에 명시적으로 추가 해주어야 합니다.
아래와 같이 설정하면 됩니다.
// root 레벨 package.json
"dependencies": {
"ag-grid": "^25.3.0"
}
// 하위 프로젝트 package.json
"dependencies": {
"ag-grid": "^25.3.0"
}
터보레포
모노레포를 효율적으로 생성관리 가능
Turborepo 공식(turbo.build) 기준으로 구조를 맞춘다.
공식문서
project 구조 및 동작원리 (whith. tailwind 연결 )
packages -> 해당 폴더는 공통 요쇼로 사용될 파일들의 집합체
//package.json 연결구문
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
// tsconfig.lint.json
{
"extends": "@repo/typescript-config/react-library.json",
"compilerOptions": {
"outDir": "dist"
},
// 인식 ,"tailwind.config.js","postcss.config.js"
"include": ["src", "turbo","tailwind.config.js","postcss.config.js"],
"exclude": ["node_modules", "dist"]
}
//components.json
// aliases-> 별칭 지정
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "css/styles.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@ui/components/*",
"utils": "@ui/lib/clsx.utils"
}
}
// tsconfig.json
{
"extends": "@repo/typescript-config/react-library.json",
"compilerOptions": {
//"outDir": "dist"
"baseUrl": ".",
// 패스 설정 => 공통 알리아스
"paths": {
"@ui/*": ["./src/*"],
"@ui/components/*": ["./src/components/*"],
}
},
"include": ["."],
"exclude": ["node_modules", "dist"]
}
packages / ui 에 설정한
tailwind.config , postcss.config 를 각각 프로젝트에 연결만 해주면 되며 tsconfig.json 혹은 package.json 의 export 기능을 사용하면 aliases(별칭)를 사용가능
연결구문은
CommonJS , AMD 택 1 로 연결 (파일 스코프로 전역 연결 )
module.exports = require("@repo/ui/tailwind.config");
혹은
import type { Config } from "tailwindcss";
const config: Config = {
theme: {
extend: {
colors: {
}
}
},
plugins: []
};
export default config;
1. 프로젝트 구조
프로젝트 구조는 다음과 같이 구성됩니다.
my-turborepo/
├── apps/
│ └── web/
│ ├── src/
│ │ └── index.jsx
│ ├── package.json
│ └── ...
└── packages/
└── ui/
├── src/
│ └── styles.css
├── package.json
└── ...
├── turbo.json
└── package.json
2. 패키지 설정
각 패키지(apps/web 및 packages/ui)의 package.json 파일에는 서로 의존성을 설정합니다. 예를 들어, web 패키지는 ui 패키지를 의존성으로 가집니다.
apps/web/package.json
{
"name": "web",
"version": "1.0.0",
"main": "src/index.jsx",
"dependencies": {
"ui": "workspace:*"
}
}
packages/ui/package.json
{
"name": "ui",
"version": "1.0.0",
"main": "src/index.js",
"dependencies": {
"@material-design-icons/font": "^0.6.1"
}
}
3. Turborepo 설정
turbo.json 파일은 Turborepo가 작업을 어떻게 수행할지 정의합니다. 이 예제에서는 build, lint, test, dev와 같은 작업을 정의하고 있습니다. 실제로 공통 CSS와 Material Icons 폰트를 사용하는 경우에는 패키지 간 의존성을 설정하는 것이 중요합니다.
turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"lint": {
"outputs": []
},
"test": {
"outputs": []
},
"dev": {
"cache": false
}
}
}
turbo.json 설명
build: 각 패키지의build작업이 다른 패키지의build작업에 의존합니다. 예를 들어,web패키지는ui패키지의build작업에 의존합니다. 따라서web패키지를 빌드하기 전에ui패키지가 먼저 빌드됩니다.outputs:build작업의 출력 디렉토리를 정의합니다. 여기서는dist/**디렉토리가 빌드 출력물입니다.lint,test,dev: 각각의 작업에 대한 설정입니다. 여기서는 출력물이 없거나 캐시를 사용하지 않도록 설정되었습니다.
4. 빌드 및 실행
각 패키지의 의존성을 설치하고 빌드 작업을 실행합니다.
bash코드 복사
# 루트 디렉토리에서 의존성 설치
npm install
# 모든 패키지의 build 작업 실행
npx turbo run build
"build": "tsc --build",
// ui 빌드후 사용