Tip
모노레포(Monorepo) 소개 (feat. 터보레포(Turborepo))
Kir93
2024. 10. 7. 17:00
728x90
반응형
최근 소프트웨어 개발 환경에서는 모노레포(Monorepo)를 채택하는 팀이 늘어나고 있습니다.
모노레포는 여러 프로젝트나 패키지를 하나의 저장소(repository)에 담는 방식을 의미합니다.
모노레포의 장점
- 코드 재사용성 증가
공통된 코드나 라이브러리를 여러 프로젝트에서 쉽게 공유할 수 있어, 중복 코드를 줄이고 유지보수가 용이합니다. - 일관된 개발 환경
모든 팀원이 동일한 저장소와 설정을 사용하여 의존성 버전이나 코드 스타일의 일관성을 유지할 수 있어 버그 발생을 줄이고 개발 효율성을 높입니다. - 변경 사항 추적 용이
하나의 저장소에서 모든 변경 사항을 관리하므로 전체 시스템에 어떤 영향을 미치는지 쉽게 파악할 수 있으며, 디버깅과 코드 리뷰가 수월해집니다. - 협업 향상
팀원들이 동일한 코드베이스에서 작업하므로 협업이 원활하며, 다른 팀의 코드를 이해하고 수정하기도 쉽습니다.
모노레포의 단점
- 빌드 시간 증가
저장소에 포함된 코드의 양이 많아질수록 빌드 시간이 길어질 수 있습니다. - 복잡한 권한 관리
프로젝트마다 접근 권한을 달리해야 하는 경우 세분화된 권한 관리를 구현하기 어렵습니다. - 의존성 관리 복잡성
다양한 프로젝트의 의존성이 충돌할 수 있어 관리가 복잡해지고, 예상치 못한 버그를 유발할 수 있습니다. - 학습 곡선
모노레포를 처음 도입하는 팀은 새로운 워크플로우와 도구에 익숙해지는 데 시간이 필요합니다.
터보레포(Turborepo)로 문제 해결하기
터보레포는 모노레포 환경에서 발생하는 문제들을 해결하기 위해 개발된 빌드 시스템입니다.
터보레포의 장점
- 지능형 캐싱
이전 빌드 결과를 캐싱하여 변경된 부분만 다시 빌드함으로써 빌드 시간을 크게 단축할 수 있습니다. - 병렬 처리
여러 작업을 동시에 수행하여 효율성을 높입니다. 이는 대규모 프로젝트에서 특히 유용합니다. - 쉬운 설정과 통합
기존 프로젝트에 쉽게 통합할 수 있으며, 설정이 간단해 학습 곡선을 완화해 줍니다. - 원격 캐싱
Vercel과 통합되어 원격 캐싱을 쉽게 구현할 수 있어 CI/CD 파이프라인의 효율성을 높일 수 있습니다. - 유연한 파이프라인
turbo.json
을 통해 복잡한 작업 흐름을 쉽게 정의하고 관리할 수 있습니다. - Vercel 통합
Vercel에서 개발한 도구로, Vercel 플랫폼과의 통합이 원활합니다.
터보레포의 단점
- 상대적으로 적은 기능
Nx와 같은 성숙한 도구들에 비해 제공하는 기능이 적을 수 있습니다. - 생태계 규모
비교적 최근에 출시되어 레퍼런스와 커뮤니티 지원이 다른 도구들에 비해 적을 수 있습니다. - 학습 곡선
기존 모노레포 도구에 익숙한 개발자들에게는 새로운 개념과 설정 방식을 학습해야 할 수 있습니다.
터보레포와 기존 모노레포 도구의 비교
1. Lerna와의 비교
- 빌드 성능: Lerna는 빌드 최적화 기능이 제한적이지만, 터보레포는 캐싱과 병렬 처리를 통해 빌드 성능이 우수합니다.
- 사용성: Lerna는 설정이 다소 복잡한 반면, 터보레포는 간단한 설정으로 쉽게 시작할 수 있습니다.
- 워크플로 통합: Lerna는 패키지 관리에 중점을 두지만, 터보레포는 빌드, 테스트, 배포를 단일 명령어로 통합 관리합니다.
2. Yarn Workspaces와의 비교
- 의존성 관리: Yarn Workspaces는 의존성 관리를 효과적으로 수행하지만, 빌드 효율성에서는 터보레포가 더 우수합니다.
- 사용 편의성: Yarn Workspaces는 빌드 도구를 별도로 설정해야 하지만, 터보레포는 빌드, 테스트, 배포 설정을 간편하게 제공합니다.
3. Nx와의 비교
- 빌드 캐싱 및 병렬 처리: Nx도 터보레포와 유사하게 빌드 캐싱과 병렬 처리를 지원하지만, 초기 설정이 복잡할 수 있습니다.
- 플러그인 생태계: Nx는 다양한 플러그인을 통해 기능을 확장할 수 있지만, 설정과 학습에 시간이 필요합니다.
4. 종합 비교표
기능 | Lerna | Yarn Workspaces | Nx | 터보레포 |
빌드 캐싱 | 없음 | 없음 | 있음 | 있음 |
병렬 처리 | 제한적 | 없음 | 있음 | 있음 |
설정 복잡도 | 중간 | 낮음 | 높음 | 낮음 |
플러그인 생태계 | 풍부함 | 제한적 | 풍부함 | 제한적 |
프레임워크 지원 | Node.js | Node.js | 다양한 언어 | 다양한 언어 |
커뮤니티 지원 | 넓음 | 넓음 | 넓음 | 성장 중 |
Next.js에서 터보레포로 모노레포 구성하기
Next.js 프로젝트를 터보레포로 구성하는 과정은 다음과 같습니다.
1. 터보레포 프로젝트 생성
npx create-turbo@latest
2. 프로젝트 구조
my-turborepo/
├─ apps/
│ ├─ web/
│ └─ docs/
├─ packages/
│ ├─ ui/
│ └─ config/
└─ package.json
3. Next.js 앱 추가
cd apps
npx create-next-app@latest my-app
4. 공유 UI 컴포넌트 사용 예시
4-1. 공유 UI 컴포넌트 생성
// packages/ui/src/Button.tsx
import React from 'react';
export const Button: React.FC<{ text: string }> = ({ text }) => {
return <button className="bg-blue-500 text-white px-4 py-2 rounded">{text}</button>;
};
4-2. Package.json 설정
packages/ui/package.json
{
"name": "@repo/ui",
"version": "0.0.0",
"main": "./src/index.ts",
"types": "./src/index.ts",
"license": "MIT",
"scripts": {
"lint": "eslint ."
},
"devDependencies": {
"@repo/eslint-config": "*",
"@repo/typescript-config": "*",
"@types/react": "^18.2.0",
"react": "^18.2.0"
}
}
4-3. 컴포넌트 내보내기
// packages/ui/src/index.ts
export * from './Button';
4-4. 의존성 설정
// apps/web/package.json
{
"dependencies": {
"@repo/ui": "*",
// 기타 의존성...
}
}
4-5. Apps에서 사용하기
// apps/web/src/pages/index.tsx
import { Button } from "@repo/ui";
export default function Home() {
return (
<div>
<h1>Welcome to my app</h1>
<Button text="Click me!" />
</div>
);
}
4. 터보레포 설정 파일 작성 (turbo.json
)
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"lint": {},
"dev": {
"cache": false,
"persistent": true
}
}
}
5. 루트 package.json
에 스크립트 추가
{
"workspaces": [
"apps/*",
"packages/*"
],
"scripts": {
"dev": "turbo run dev",
"build": "turbo run build",
"start": "turbo run start",
"lint": "turbo run lint"
},
"devDependencies": {
"turbo": "latest"
}
}
모노레포는 코드 재사용성과 협업 측면에서 많은 이점을 제공하지만, 그에 따른 단점도 존재합니다.
터보레포는 빌드 시간 단축과 설정의 편의성을 제공하여 모노레포의 단점을 효과적으로 극복할 수 있습니다.
Next.js를 사용하고 모노레포의 필요성을 느낀다면 터보레포를 사용해 보는 것을 고려해 보시기 바랍니다.
반응형