Global CSS vs Tailwind.config.ts & Tailwind V4버전

이언덕·2025년 9월 18일
post-thumbnail

🌐 Global CSS vs Tailwind.config.ts, 뭐가 다를까?

Next.js 프로젝트를 세팅하면서 가장 헷갈렸던 부분 중 하나가 globals.csstailwind.config.ts였다. 둘 다 전역에 스타일을 적용할 수 있는데, 무엇을 어디에 두어야 할지 정리가 필요했다.


내가 처음 헷갈렸던 점

나는 이렇게 생각했다.

  • globals.css: 전역으로 CSS를 먹이는 곳
  • tailwind.config.ts: 이것도 전역으로 먹일 수 있는 곳
    둘 다 “전역 적용”이라는 점에서 비슷해 보인다. 하지만 조금 더 깊게 들어가 보니 성격이 달랐다.

globals.css — 실제 CSS

globals.css는 브라우저가 직접 읽는 CSS 파일이다.
여기에 reset, Tailwind 지시어, body 기본값 등을 적으면 모든 페이지에 바로 적용된다.

예를 들어

@import "reset-css/reset.css";
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
  @apply font-sans bg-white text-gray-900;
  line-height: 1.5;
  letter-spacing: -0.01em;
}

👉 즉, 전역으로 바로 먹이는 실제 CSS 코드다.


tailwind.config.ts — 전역 설계도

반대로 tailwind.config.ts는 CSS가 아니라 설정 파일이다.
여기에 색상, 폰트, spacing 단위 등을 정의하면 Tailwind가 빌드 과정에서 새로운 유틸리티 클래스를 만들어준다.

예를 들어:

theme: {
  extend: {
    colors: {
      primary: "#06c",
    },
    fontFamily: {
      sans: ["Pretendard", "ui-sans-serif", "system-ui"],
    },
  },
}

이렇게 정의해두면 어디서든 class="text-primary font-sans"처럼 쓸 수 있다.
👉 즉, 전역 스타일을 “설계”해 두는 곳이다. 실제 적용은 Tailwind가 생성한 클래스가 담당한다.


정리

둘 다 전역에 영향을 주지만, 차이점은 적용 방식이다.

  • globals.css → 브라우저에 직접 적용되는 전역 CSS
  • tailwind.config.ts → Tailwind가 유틸리티 클래스로 변환하는 전역 설계도

결국 나는 이렇게 사용하기로 했다.

  • reset, body 기본값 같은 최소 전역 스타일globals.css
  • 폰트, 컬러 팔레트 같은 디자인 토큰tailwind.config.ts


✨ Tailwind v4, 이제는 한 파일로 전역 스타일 관리한다

프로젝트 세팅을 하면서 전역 스타일 관리 방식을 정리하다가, 추가로 리서치를 해봤다. 리서치 자료
그 과정에서 Tailwind가 최근 v4로 업데이트되었다는 걸 알게 되었다. 이번 버전에서는 전역 스타일을 관리하는 방식이 훨씬 단순해졌다.

이전(v3)까지는 globals.csstailwind.config.ts 두 파일을 나눠서 관리해야 했다. 하지만 v4부터는 하나의 CSS 파일에 모든 걸 몰아넣는 방식이 가능해졌다.


v3 방식의 구조

기존에는 전역 스타일과 디자인 토큰을 이렇게 분리했다.

  • globals.css → reset, Tailwind 지시어, body 전역 스타일
  • tailwind.config.ts → 색상, 폰트, spacing 같은 디자인 토큰

이 구조는 체계적이지만, 파일이 분리되다 보니 초반에는 다소 헷갈리기도 했다.


v4에서 달라진 점

리서치하면서 확인한 가장 큰 변화는 올인원 관리였다.

  • Tailwind 불러오기: 한 줄로 import
  • 디자인 토큰 정의: CSS 안에서 바로 선언 가능
  • 전역 스타일: reset과 함께 base 확장으로 처리

즉, 더 이상 설정 파일을 따로 둘 필요 없이 CSS 한 파일만으로도 프로젝트 전역 스타일을 컨트롤할 수 있게 된 것이다.


reset은 어떻게?

Tailwind에는 기본적으로 Preflight라는 modern reset이 들어 있어, 별도의 reset 패키지를 쓰지 않아도 된다.
필요한 경우에는 전역 스타일 레이어에서 원하는 부분만 덮어쓰면 된다.

정리

  • v3까지: globals.css + tailwind.config.ts로 나눠 관리
  • v4부터: globals.css 하나로 import, 토큰, 전역 스타일까지 관리 가능
  • 장점: 단순함, 진입장벽 낮음, 스타일 관리가 한눈에 보임
  • 단점: 대규모 프로젝트나 모노레포에서는 여전히 분리된 설정 파일이 유리할 수 있음


🎨 :root vs @theme inline — 뭐가 다르고, 언제 써야 할까?

Tailwind v4를 쓰다 보면 globals.css 안에 이런 코드가 생긴다.

:root {
  --background: #ffffff;
  --foreground: #171717;
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
}

처음 보면 “둘 다 색을 정의하는데, 도대체 뭐가 다른 거야?” 싶다.
이 둘은 비슷해 보이지만, 역할이 완전히 다르다.

🧩 1) :root는 ‘일반적인 CSS 변수’

:root는 말 그대로 CSS의 전역 변수다.
사이트 전체에서 var(--background)처럼 직접 불러다 쓸 수 있다.

:root {
  --background: #ffffff;
  --foreground: #171717;
}

body {
  background: var(--background);
  color: var(--foreground);
}

이렇게 하면 Tailwind를 몰라도 순수 CSS만으로 색을 적용할 수 있다.
하지만 문제는 — Tailwind가 제공하는 bg-background, text-foreground 같은 유틸리티 클래스는 이 변수를 모르고 있다는 점이다.

즉,
body { background: var(--background) }O
<div class="bg-background">X (유틸 자체가 생성되지 않음)



🧭 2) @theme inline은 Tailwind 전용 “색 이름표”

Tailwind v4에서는 @theme inline을 통해 CSS 변수와 Tailwind 유틸리티를 연결한다.
쉽게 말해,

“이 변수 이름으로 Tailwind 유틸(bg-, text-, border- 등)을 만들어줘”
라고 Tailwind에게 알려주는 구간이다.

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
}

이 코드가 있어야 Tailwind가
👉 bg-background, text-foreground, border-border 같은 클래스를 생성한다.



🪄 3) 어떤 방식을 쓰면 좋을까?

✅ 방법 A — 가장 권장 (원시 변수 + 매핑)

원시 변수(:root)를 두고, @theme inline에서 Tailwind용 이름으로 연결해주는 방식이다.
이 구조가 가장 유연하고, 다크모드 전환에도 강하다.

@import "tailwindcss";

/* 1) 원시 변수 선언 */
:root {
  --background: #ffffff;
  --foreground: #171717;
}
@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}

/* 2) Tailwind 유틸용 의미 토큰 매핑 */
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
}

/* 3) 직접 사용도 가능 */
body {
  background: var(--background);
  color: var(--foreground);
}

📌 이 방식의 장점

  • Tailwind 유틸(bg-background, text-foreground) + 일반 CSS 둘 다 동작
  • 다크모드 전환도 자연스럽게 가능
  • 색 교체가 쉬움 (한 곳만 수정하면 전체 반영)

✅ 방법 B — 가장 간단 (커스텀 토큰을 바로 정의)

Tailwind 유틸만 쓸 예정이거나, 다크모드를 아예 안 쓴다면
@theme inline 안에 색을 바로 정의해도 된다.

@import "tailwindcss";

@theme inline {
  --color-background: #fafafa;
  --color-foreground: #111827;
  --color-primary: #06c;
  --color-primary-foreground: #ffffff;
}

📌 이 방식의 장점

  • 설정이 단순하고 빠름
  • globals.css 하나로 끝
  • 다크모드나 외부 변수 연결이 필요 없는 경우에 적합

⚠️ 방법 C — :root만 쓰는 경우 (비추천)

Tailwind의 bg-*, text-* 유틸은 생성되지 않는다.
직접 CSS에서는 동작하지만, 유틸리티를 전혀 못 쓴다.

:root {
  --background: #fff;
}
body {
  background: var(--background); /* ✅ 가능 */
}
/* <div class="bg-background"> ❌ 동작 안 함 */

🧱 4) 정리 요약

구분역할Tailwind 유틸 가능다크모드 대응사용 난이도
:root일반 CSS 변수⭕ 가능 (CSS 수준)가장 쉬움
@theme inlineTailwind용 토큰 (색 이름표)약간 설정 필요
둘 다 조합 (추천)원시 변수 + 유틸 매핑⭐️ 균형형 (추천)

.



📚 5) 보너스: @layer는 왜 쓰는 걸까?

Tailwind에서는 @layer스타일의 “적용 우선순서”를 관리하는 구조다.
쉽게 말해, “CSS가 겹칠 때 누가 먼저 적용될지”를 Tailwind에게 알려주는 개념이다.

@layer base {
  /* 브라우저 기본 스타일을 덮어쓰는 전역 설정 */
  html, body {
    font-family: Pretendard, system-ui, sans-serif;
    color: var(--color-foreground);
    background: var(--color-background);
  }
}

@layer components {
  /* 프로젝트 내부에서 만든 공통 컴포넌트 스타일 */
  .card {
    @apply bg-card text-card-foreground rounded-lg shadow;
  }
}

@layer utilities {
  /* tailwind 유틸처럼 바로 적용되는 간단한 클래스 */
  .t-14-b { font-size: 1.4rem; font-weight: 700; }
}

Tailwind는 내부적으로 CSS를 세 구역으로 분리해서 처리한다.

Layer용도우선순위
base브라우저 기본값 수정 (reset, 전역 폰트 등)가장 낮음
components재사용 가능한 컴포넌트 스타일중간
utilities.p-4, .text-sm처럼 바로 적용되는 클래스가장 높음

즉,

  • 전역 설정(@layer base)은 항상 먼저 읽히고,
  • 컴포넌트(@layer components)가 그 위에 올라가며,
  • 유틸리티(@layer utilities)가 제일 나중에 덮어쓴다.

    그래서 @layer를 쓰면 CSS가 겹쳐도
    “어떤 스타일이 우선인지” Tailwind가 정확하게 판단할 수 있다.


    💬 한 줄 요약

:rootCSS 전역 변수,
@theme inlineTailwind가 유틸을 만들기 위한 토큰 선언,
@layerCSS가 적용되는 순서를 정리하는 구획이다.

이 세 가지를 함께 쓰면 —
전역 색 체계, 유틸 생성, 그리고 우선순위까지 깔끔하게 통제할 수 있다.

0개의 댓글