본문 바로가기
FrontEnd/Next.js

모노레포로 공통 된 tailwind config를 생성하기(turborepo, next.js, tailwind) - 2024.12.11 기준

by 위그든씨 2024. 12. 11.

turborepo에서 제공하는 with tailwind 옵션을 통해 초기 셋팅을 한다면 tailwind-config가 자동으로 추가되지만 학습 목적을 가지고 기본 셋팅을 통해 추가해 봄. 

pnpm dlx create-turbo@latest --example with-tailwind

( 옵션을 통해 추가하는 방법은 위 cli를 입력해주면 됨. 링크)

목적 -  공통으로 쓰일 tailwind config 을 만들어서 각 패키지에 적용시키기

turborepo의 공식 문서에서는 패키지 매니저를 pnpm을 추천하여 pnpm으로 진행

1. turbo 전역 설치 

pnpm install turbo --global

2. 초기 셋팅

pnpm dlx create-turbo@latest

위 명령어를 실행하면 

packages 와 apps 폴더가 생성되는데

apps는 프로젝트들이 담겨져 있고, packages에는 typescript-config 와 eslint-config, ui 패키지가 기본적으로 셋팅되어져 있다.

tailwind config는 공통으로 쓰일 설정 파일이 될것이므로 packages에 셋팅할것이다.

3. 폴더 셋팅

cd packages
mkdir tailwind-config
cd tailwind-config

터보레포의 각 패키지들은 고유의 package.json을 가지는 것으로 구분되어진다.

4. package.json 셋팅

pnpm init

위 명령어를 실행하면 package.json이 기본 셋팅되어 있는데 패키지 json의 주요 속성에는 name과 exports가 있다.

  1 )name에는 각 패키지가 구분되어져야 할 고유의 이름값이 들어간다. 따라서 prefix를 넣어주는 것을 turborepo는 추천함.

"

The name field is used to identify the package. It should be unique within your workspace.

 

Modules: Packages | Node.js v23.4.0 Documentation

Modules: Packages# Introduction# A package is a folder tree described by a package.json file. The package consists of the folder containing the package.json file and all subfolders until the next folder containing another package.json file, or a folder nam

nodejs.org

It's best practice to use a namespace prefix for your Internal Packages to avoid conflicts with other packages on the npm registry. For example, if your organization is named acme, you might name your packages @acme/package-name.

We use @repo in our docs and examples because it is an unused, unclaimable namespace on the npm registry. You can choose to keep it or use your own prefix.

"

나는 package.json의 name을 @repo/tailwind-config로 설정함 

2 )exports에는 외부 패키지에서 이 패키지의 모듈을 가져올려고 할 때 경로를 셋팅해주는 것이라고 봐도 될 것 같다.

나는 index.ts에 공통으로 쓰일 tailwind config 내용을 담을 것이므로 

".": ".index.ts" 라고 셋팅해줬다.

만약 빌드 된 경로를 잡아줄 것이라면 아래처럼 잡아줘야 할 것이다.

{
  "exports": {
    ".": "./dist/constants.ts",
    "./add": "./dist/add.ts",
    "./subtract": "./dist/subtract.ts"
  }
}

3) tailwind config 셋팅을 위한 라이브러리 설치

pnpm add -D tailwindcss tailwindcss-animate typscript @types/node

아래는 내가 셋팅해 둔 package.json의 완성본이다.

{
    "name": "@repo/tailwind-config",
    "version": "1.0.0",
    "private": true,
    "exports": {
        ".": "./index.ts"
    },
    "devDependencies": {
        "@types/node": "^22.10.1",
        "tailwindcss": "^3.4.16",
        "tailwindcss-animate": "^1.0.7",
        "typescript": "^5.7.2"
    }
}

5. index.ts 생성 

content 를 생략하는 이유는 패키지별로 tailwind가 적용 될 범위가 다를 수도 있기 때문에 생략해줌.

content가 비워져 있어서 warn - No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration. 이러한 메시지가 뜰 수 있는데 이게 싫으면 content:[]라고 빈 값을 넣어줘도 될듯하다.

width에 나만의 고유 가로를 줘서 추후에 다른 패키지에서 w-zeroGym이 잘 먹히는지 확인할 것이다.

import type { Config } from 'tailwindcss';
import animate from 'tailwindcss-animate';

const config: Omit<Config, 'content'> = {
    darkMode: ['class'],
    theme: {
        extend: {
            width: {
                zeroGym: '24rem',
            },

            colors: {
                border: 'hsl(var(--border))',
                input: 'hsl(var(--input))',
                ring: 'hsl(var(--ring))',
                background: 'hsl(var(--background))',
                foreground: 'hsl(var(--foreground))',
                primary: {
                    DEFAULT: 'hsl(var(--primary))',
                    foreground: 'hsl(var(--primary-foreground))',
                },
                secondary: {
                    DEFAULT: 'hsl(var(--secondary))',
                    foreground: 'hsl(var(--secondary-foreground))',
                },
                destructive: {
                    DEFAULT: 'hsl(var(--destructive))',
                    foreground: 'hsl(var(--destructive-foreground))',
                },
                muted: {
                    DEFAULT: 'hsl(var(--muted))',
                    foreground: 'hsl(var(--muted-foreground))',
                },
                accent: {
                    DEFAULT: 'hsl(var(--accent))',
                    foreground: 'hsl(var(--accent-foreground))',
                },
                popover: {
                    DEFAULT: 'hsl(var(--popover))',
                    foreground: 'hsl(var(--popover-foreground))',
                },
                card: {
                    DEFAULT: 'hsl(var(--card))',
                    foreground: 'hsl(var(--card-foreground))',
                },
            },
            borderRadius: {
                lg: `var(--radius)`,
                md: `calc(var(--radius) - 2px)`,
                sm: 'calc(var(--radius) - 4px)',
            },
        },
    },
    plugins: [animate],
};

export default config;

6. web 패키지로 이동 

( 루트에서 pnpm install 후 pnpm run dev 또는 pnpm run dev --filter web을 입력하여 실행시킬 수 있는데 turbopack을 읽을 수 없다는 에러가 뜸. web과 docs package.json에 dev 옵션으로 --turbopack을 --turbo로 수정해줬더니 실행 잘 됐음 ) 

기본 셋팅 되어 있는 web 패키지에는 next 15가 설치되어 있을 것이다. 여기에는 tailwind 셋팅도 없을 뿐더러 방금까지 내가 작성한 tailwind-config 가 없기 때문에 이것들을 설치해줘야함.

외부 패키지를 바로 pnpm add 해주면 에러가 떠서 devDependecies에 직접 @repo/tailwind-config:workspace:*를 작성해준뒤 pnpm install 실행함.

7. web에 tailwind 적용해주기 

이건 tailwind 문서에 나온 설치법대로 진행하면 됨

pnpm add -D tailwindcss autoprefixer postcss
pnpm dlx tailwindcss init

init을 통해 tawilwind.config.js 가 생성 될텐데 이제 그 안에 @repo/tailwind-config의 config를 넣어주면 된다.

import config from '@repo/tailwind-config';

/** @type {import('tailwindcss').Config} */
export default {
    ...config,
    content: [
        './components/**/*.{js,ts,jsx,tsx,mdx}',
        './app/**/*.{js,ts,jsx,tsx,mdx}',
    ],
    theme: {
        extend: {
            ...config.theme.extend,
        },
    },
    plugins: [],
};

이때 extend안에 config를 풀어주지 않으면 씹혀져서 적용이 안된다.

따라서 꼭 ...config.theme.extend를 넣어주자..

postcss.config.mjs를 생성도 해주자

const config = {
    plugins: {
        tailwindcss: {},
    },
};

export default config;

이제 global.css 최상단에 아래를 추가

@tailwind base;
@tailwind components;
@tailwind utilities;

8. 최종 

<div className="bg-blue-400 w-zeroGym">sadasd</div>

 

width가 384px ( 24rem ) 인 w-zeroGym이 잘 먹힌 것을 확인할 수 있다.