Next.js + ShadcnUI 프로젝트를 Turborepo로 마이그레이션 하기

LEEJAEJUN·2024년 8월 6일
post-thumbnail

1. 개요

어제 원티드 프리온보딩 강의를 듣던 도중 여러번 언급 된 Monorepo 는 최근 관심 있는 것 중 하나다. 여러 프로젝트를 하나의 규칙에 기반해 공통으로 쓸 수 있다는 점이 굉장히 매력적인데, 초보자인 나로서는 세팅하기가 쉽지 않았다. (처음엔 turborepo 라는 하나의 기술이 있는 줄 알 정도로..)

그러던 와중 지금 개인 프로젝트가 Next.js와 ShadcnUI (tailwindcss)로 되어있다는 점이 떠올랐다. 이걸 미리 Monorepo로 구성해 놓으면 다음에 새로 세팅하지 않고도 하나의 프로젝트를 더 만들 수 있겠다는 생각으로 마이그레이션을 시작했다.

2. 방법

2.1 npm을 pnpm로 마이그레이션

심볼릭 링크와 공유 저장소를 사용하는 pnpm의 효율성을 가져가기 위해 마이그레이션 합니다. 기본적인 순서는 아래와 같습니다.

// 기존 node_modules 삭제
npx npkill
// package-lock.json을 복사하여 pnpm-lock.yaml로 생성
pnpm import
// 새로운 node_modules 생성
pnpm install

2.2 Next.js 프로젝트를 apps/web 폴더로 이동

pnpm-workspace.yaml 에 지정한대로 apps/web 으로 기존 프로젝트를 이동합니다. 이때 주의할 점은, shadcn ui 는 제외하고 옮겨야 한다는 점입니다. 이 부분이 굉장히 까다로웠습니다.

// pnpm-workspace.yaml
packages:
	- apps/*
    - packages/*

2.2.1 apps/web

  1. app 폴더를 apps/web 폴더로 이동
  2. next.config.js, middleware.ts, package.json 등 root에 있던 파일을 apps/web 폴더로 이동시킵니다.

2.3 packages 폴더 생성 및 shadcn ui 이동

  1. shadcn ui 즉, components/ui 폴더, tailwind.config.js, postcss.config.js 등을 packages/ui 폴더로 이동시킵니다.

옮기는 과정에서 import 에러가 무수히 발생하는데 일단 놔둡니다.

2.4 packages/ui 폴더 세팅

  1. packages/ui 폴더에 package.json 파일을 생성합니다.
  2. name을 "@<repo>/ui"로 수정, 추후 web 폴더와 연결하여 사용하기 위함입니다.
  3. 필요한 의존성 모두 설치합니다.
{
  "name": "@gaoridang/ui",
  "version": "0.1.0",
  "main": "index.ts",
  "private": true,
  "scripts": {
    "build": "tsc"
  },
  "dependencies": {
    "@radix-ui/react-alert-dialog": "^1.1.1",
    "@radix-ui/react-checkbox": "^1.1.1",
    "@radix-ui/react-dialog": "^1.1.1",
    "@radix-ui/react-label": "^2.1.0",
    "@radix-ui/react-popover": "^1.1.1",
    "@radix-ui/react-radio-group": "^1.2.0",
    "@radix-ui/react-select": "^2.1.1",
    "@radix-ui/react-slot": "^1.1.0",
    "@radix-ui/react-toast": "^1.2.1",
    "class-variance-authority": "^0.7.0",
    "next-themes": "^0.3.0",
    "clsx": "^2.1.1",
    "lucide-react": "^0.408.0",
    "sonner": "^1.5.0",
    "tailwind-merge": "^2.4.0",
    "tailwindcss-animate": "^1.0.7",
    "react-hook-form": "^7.52.1"
  },
  "devDependencies": {
    "@gaoridang/typescript-config": "workspace:*",
    "@tailwindcss/typography": "^0.5.13",
    "autoprefixer": "^10.4.20",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18"
  },
  "peerDependencies": {
    "react": "^18",
    "react-dom": "^18"
  }
}
  1. packages/ui/components/ui 에 있는 모든 컴포넌트들을 하나의 index.ts 파일에서 export 즉, barrel file로 만들어줍니다.
  2. scripts에 build 커맨드를 추가합니다.
"scripts": {
    "build": "tsc"
},
  1. tailwind.config.js를 수정합니다.
content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
    './app/**/*.{js,ts,jsx,tsx}',
    './src/**/*.{js,ts,jsx,tsx}',
  
    // tailwindcss를 사용할 shadcn ui 컴포넌트 위치를 지정
    '../../packages/ui/**/*.{js,ts,jsx,tsx}',
],

2.5 apps/web과 packages/ui 연결

  1. package.json의 dependencies에 아까 ui/package.json에서 설정한 name을 추가합니다.
"dependencies": {
    "@gaoridang/ui": "workspace:*",
  	// 기존 의존성...
}
  1. postcss.config.js, tailwind.config.js를 ui 패키지에서 extends해서 사용
// postcss.config.js
module.exports = require("@gaoridang/ui/postcss.config");
const sharedConfig = require("@gaoridang/ui/tailwind.config");

/** @type {import('tailwindcss').Config} */
module.exports = {
  ...sharedConfig,
  // 필요한 경우 추가 설정이나 오버라이드를 여기에 작성
};

import 경로 수정

이제 ui를 @gaoridang/ui 패키지에서 가져와야 하므로, 모든 import 경로를 수정해야 한다. VSCode 사용자라면 왼쪽 돋보기 모양 클릭 후, 기존 import 경로를 모두 @gaoridang/ui 로 대체하면 됩니다.

3. 결론 및 보완점

  • 일단 모노레포 구조를 이해하는 데 꽤 많은 시간을 소모했습니다.
  • 의존성이 어디엔 필요하고 어디엔 필요없는지 확인해가며 나누는 과정이 생각보다 어려웠습니다. 아직도 깔끔하게 나눈 것 같진 않습니다.
  • tailwindcss를 packages, app 모두에서 사용하는데 이걸 하나로 두려다 많은 시간을 날렸습니다.
  • 몇몇 config 파일이 확장 없이 중복으로 선언되어 있습니다. 이 부분을 앞으로 보완하고자 합니다.
profile
always be fresh

0개의 댓글