2025년 말에 새 프로젝트에서 Tailwind CSS를 사용 중단했고, 돌아가지 않았습니다. Tailwind가 나쁘기 때문이 아닙니다 -- 자신이 하는 일에 진정으로 우수합니다. 하지만 바닐라 CSS가 너무 좋아져서 우리가 구축하는 프로젝트 종류에서는 더 이상 이점이 맞지 않기 때문입니다.

이 전환의 중심에는 디자인 토큰이 있습니다. 디자인 의사결정을 재사용 가능하고 플랫폼에 독립적인 변수로 저장하는 아이디어는 새로운 것이 아닙니다. 하지만 2026년의 CSS 커스텀 속성 주변의 도구와 브라우저 지원은 빌드 단계 없이, 종속성 없이, 유틸리티 클래스 암기 없이 완전한 디자인 토큰 시스템을 구축할 수 있을 정도로 성숙해졌습니다. 어떻게 하는지 보여드리겠습니다.

디자인 토큰이란 실제로 무엇인가

디자인 토큰은 시각 언어를 정의하는 원자 값입니다. 색상, 간격, 타이포그래피, 그림자, 테두리 반경, 애니메이션 지속 시간 -- 디자인 의사결정을 나타내는 모든 것입니다. 이 용어는 2014년 Salesforce의 디자인 팀에 의해 만들어졌지만, 개념은 상당히 진화했습니다.

대부분의 사람들이 놓치는 핵심 통찰력이 있습니다: 디자인 토큰은 단순한 변수가 아닙니다. 이는 디자인과 엔지니어링 간의 계약입니다. 디자이너가 "기본 작업 색상을 사용하십시오"라고 말할 때, 이는 16진수 값이 아닌 토큰에 매핑됩니다. "중간 간격"이라고 말할 때, 이것도 토큰입니다.

W3C 디자인 토큰 커뮤니티 그룹은 디자인 토큰 형식 모듈 사양을 발표했으며, 아직 진화 중이지만 핵심 아이디어는 확립되었습니다. 토큰은 계층에 존재합니다:

  1. 기본 토큰 (예: #1a73e8 또는 16px와 같은 원본 값)
  2. 의미론적 토큰 (예: color-action-primary와 같은 목적 중심 별칭)
  3. 컴포넌트 토큰 (예: button-background와 같은 특정 UI 요소로 범위 지정)

이 3계층 아키텍처가 대규모 시스템을 관리 가능하게 만드는 것입니다. CSS 커스텀 속성이 완벽하게 매핑됩니다.

왜 바닐라 CSS가 나를 이기게 했는가

솔직하게 제 여정에 대해 말하겠습니다. 저는 여러 해 동안 행복하게 Tailwind를 사용했습니다. 프로덕션 사이트를 구축했습니다. 클라이언트에게 권장했습니다. 하지만 여러 가지가 변했습니다:

CSS가 따라잡았습니다. 중첩, :has(), 컨테이너 쿼리, @layer, @scope, color-mix(), oklch(), 상대 색상 구문 -- 이것들은 더 이상 실험적 기능이 아닙니다. 2026년 모든 주요 브라우저에서 기본입니다. 유틸리티 프레임워크가 채웠던 격차입니까? 극적으로 축소되었습니다.

번들 크기가 그 어느 때보다 중요합니다. Core Web Vitals이 검색 순위에 직접 영향을 미치므로 모든 킬로바이트가 중요합니다. 잘 구성된 바닐라 CSS 토큰 시스템은 거의 무게가 없습니다. Tailwind의 JIT 컴파일러는 영리하지만, 여전히 사용하는 모든 유틸리티에 대한 CSS를 제공합니다.

유지보수 비용은 실제입니다. 저는 30개 이상의 유틸리티 클래스가 함께 연결된 Tailwind 프로젝트를 상속받았습니다. className="flex items-center justify-between px-4 py-2 bg-white dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition-shadow duration-200 border border-gray-200 dark:border-gray-700"를 읽는 것은 재미있지 않습니다. 디자인 토큰과 얇은 CSS 레이어를 사용하면 의도가 더 명확합니다.

디자인-엔지니어링 핸드오프가 개선되었습니다. CSS의 토큰이 Figma의 토큰과 1:1로 일치할 때, 대화가 정확해집니다. "이 Figma 변수가 어느 Tailwind 클래스에 매핑되는가?"라는 더 이상의 질문이 없습니다.

이것은 거룩한 전쟁이 아닙니다. Tailwind가 팀에게 효과가 있다면, 계속 사용하십시오. 하지만 새로운 것을 시작하고 최대 제어로 최소 추상화를 원한다면, 바닐라 CSS 토큰은 진지하게 고려할 가치가 있습니다.

토큰 아키텍처 설정

처음부터 이를 구축해봅시다. Social Animal에서 여러 헤드리스 CMS 프로젝트에서 개선한 파일 구조를 사용하겠지만, 필요에 따라 조정하십시오.

핵심 원칙: 토큰은 특이성 계층을 통해 아래로 흐릅니다.

tokens/
├── primitives.css       /* 원본 값 */
├── semantic.css         /* 목적 중심 별칭 */
├── components/
│   ├── button.css
│   ├── card.css
│   └── input.css
├── themes/
│   ├── light.css
│   └── dark.css
└── index.css            /* 가져오기 조율 */

index.css@layer를 사용하여 명확한 계단식 구조를 설정합니다:

@layer primitives, semantic, themes, components;

@import './primitives.css' layer(primitives);
@import './semantic.css' layer(semantic);
@import './themes/light.css' layer(themes);
@import './components/button.css' layer(components);
@import './components/card.css' layer(components);
@import './components/input.css' layer(components);

이것은 중요합니다. @layer는 특이성과 싸우지 않고 계단식에 대한 명시적 제어를 제공합니다. 기본 토큰은 의미론적 토큰으로 재정의되고, 이는 테마로 재정의되고, 이는 컴포넌트로 재정의됩니다. 깔끔한 계층.

기본 토큰: 원시 값

기본 토큰은 팔레트입니다. 컴포넌트에서 직접 사용하려고 하지 않습니다 -- 무언가를 칠하기 전에 선반에 있는 페인트로 생각하십시오.

/* primitives.css */
:root {
  /* 지각적으로 균일한 팔레트에 OKLCH를 사용하는 색상 */
  --color-blue-50: oklch(0.97 0.01 250);
  --color-blue-100: oklch(0.93 0.03 250);
  --color-blue-200: oklch(0.87 0.06 250);
  --color-blue-300: oklch(0.78 0.10 250);
  --color-blue-400: oklch(0.68 0.15 250);
  --color-blue-500: oklch(0.58 0.19 250);
  --color-blue-600: oklch(0.50 0.19 250);
  --color-blue-700: oklch(0.42 0.17 250);
  --color-blue-800: oklch(0.35 0.14 250);
  --color-blue-900: oklch(0.27 0.10 250);

  /* 간격 척도 (모듈식, 4px 그리드 기반) */
  --space-1: 0.25rem;   /* 4px */
  --space-2: 0.5rem;    /* 8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-5: 1.25rem;   /* 20px */
  --space-6: 1.5rem;    /* 24px */
  --space-8: 2rem;      /* 32px */
  --space-10: 2.5rem;   /* 40px */
  --space-12: 3rem;     /* 48px */
  --space-16: 4rem;     /* 64px */
  --space-20: 5rem;     /* 80px */
  --space-24: 6rem;     /* 96px */

  /* 타이포그래피 척도 */
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-md: 1.125rem;
  --font-size-lg: 1.25rem;
  --font-size-xl: 1.5rem;
  --font-size-2xl: 1.875rem;
  --font-size-3xl: 2.25rem;
  --font-size-4xl: 3rem;

  /* 글꼴 두께 */
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;

  /* 테두리 반지름 */
  --radius-sm: 0.25rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;
  --radius-full: 9999px;

  /* 그림자 */
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.05);
  --shadow-md: 0 4px 6px oklch(0 0 0 / 0.07);
  --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.1);
  --shadow-xl: 0 20px 25px oklch(0 0 0 / 0.1);

  /* 지속 시간 */
  --duration-fast: 100ms;
  --duration-normal: 200ms;
  --duration-slow: 300ms;
  --duration-slower: 500ms;
}

여기서 OKLCH를 사용하고 있는 이유는 정말 더 나은 색상 공간이기 때문입니다. HSL과 달리 OKLCH의 명도는 지각적으로 균일합니다 -- 명도가 0.5라면 색상에 관계없이 실제로 중간 회색처럼 보입니다. 색상 척도가 전체 스펙트럼에서 일관되게 보입니다. 모든 주요 브라우저는 이제 이를 지원합니다.

의미론적 토큰: 마법이 일어나는 곳

의미론적 토큰은 기본 토큰을 참조하고 의미를 부여합니다. 이것이 테마를 가능하게 하고 CSS를 자기 문서화하는 계층입니다.

/* semantic.css */
:root {
  /* 표면 색상 */
  --color-surface-primary: var(--color-white, #fff);
  --color-surface-secondary: var(--color-gray-50);
  --color-surface-tertiary: var(--color-gray-100);
  --color-surface-inverse: var(--color-gray-900);

  /* 텍스트 색상 */
  --color-text-primary: var(--color-gray-900);
  --color-text-secondary: var(--color-gray-600);
  --color-text-tertiary: var(--color-gray-400);
  --color-text-inverse: var(--color-white, #fff);
  --color-text-link: var(--color-blue-600);
  --color-text-link-hover: var(--color-blue-700);

  /* 작업 색상 */
  --color-action-primary: var(--color-blue-600);
  --color-action-primary-hover: var(--color-blue-700);
  --color-action-primary-active: var(--color-blue-800);

  /* 피드백 색상 */
  --color-feedback-success: var(--color-green-600);
  --color-feedback-warning: var(--color-amber-500);
  --color-feedback-error: var(--color-red-600);
  --color-feedback-info: var(--color-blue-500);

  /* 테두리 색상 */
  --color-border-primary: var(--color-gray-200);
  --color-border-secondary: var(--color-gray-100);
  --color-border-focus: var(--color-blue-500);

  /* 의미론적 간격 */
  --space-inline-xs: var(--space-1);
  --space-inline-sm: var(--space-2);
  --space-inline-md: var(--space-4);
  --space-inline-lg: var(--space-6);
  --space-stack-xs: var(--space-1);
  --space-stack-sm: var(--space-2);
  --space-stack-md: var(--space-4);
  --space-stack-lg: var(--space-8);
  --space-stack-xl: var(--space-12);
}

여기서 어떤 하드코딩된 값도 없습니다. 모든 것이 기본 토큰을 참조합니다. 내일 리브랜딩하고 싶다면 기본 토큰을 변경하면 됩니다. "기본 작업"이 어떻게 느껴지는지 조정하고 싶다면 의미론적 토큰을 변경하면 됩니다. 컴포넌트 코드는 절대 알 필요가 없습니다.

컴포넌트 토큰: 최종 계층

컴포넌트 토큰은 특정 UI 요소에 대한 설계 결정을 범위 지정합니다. 소규모 프로젝트의 경우 선택적이지만 디자인 시스템이 있는 모든 것에 필수적입니다.

/* components/button.css */
.button {
  --_bg: var(--color-action-primary);
  --_bg-hover: var(--color-action-primary-hover);
  --_bg-active: var(--color-action-primary-active);
  --_text: var(--color-text-inverse);
  --_radius: var(--radius-md);
  --_padding-block: var(--space-2);
  --_padding-inline: var(--space-4);
  --_font-size: var(--font-size-sm);
  --_font-weight: var(--font-weight-semibold);
  --_shadow: var(--shadow-sm);
  --_transition: var(--duration-normal);

  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--_padding-block) var(--_padding-inline);
  background: var(--_bg);
  color: var(--_text);
  font-size: var(--_font-size);
  font-weight: var(--_font-weight);
  border-radius: var(--_radius);
  box-shadow: var(--_shadow);
  transition: background var(--_transition), box-shadow var(--_transition);
  border: none;
  cursor: pointer;

  &:hover {
    background: var(--_bg-hover);
    box-shadow: var(--shadow-md);
  }

  &:active {
    background: var(--_bg-active);
  }

  &.--secondary {
    --_bg: transparent;
    --_text: var(--color-action-primary);
    --_shadow: none;
    border: 1px solid var(--color-border-primary);

    &:hover {
      --_bg: var(--color-surface-secondary);
    }
  }

  &.--ghost {
    --_bg: transparent;
    --_text: var(--color-text-primary);
    --_shadow: none;

    &:hover {
      --_bg: var(--color-surface-secondary);
    }
  }
}

--_ 접두사 관례 (언더스코어 포함)는 "비공개" 컴포넌트 토큰을 신호합니다. 브라우저에서 적용되지 않지만, 다른 개발자에게 명확한 신호입니다: 이 토큰은 이 컴포넌트 내부입니다.

또한 -- CSS 중첩이 여기서 어떻게 작동하는지 봅시다. 전처리기가 필요하지 않습니다. 이것은 2026년 기본 CSS입니다.

프레임워크 없이 다크 모드 및 테마

이것이 토큰 아키텍처가 정말 유리한 경우입니다. 다크 모드는 의미론적 토큰을 재할당하는 문제가 됩니다.

/* themes/dark.css */
@media (prefers-color-scheme: dark) {
  :root {
    --color-surface-primary: var(--color-gray-900);
    --color-surface-secondary: var(--color-gray-800);
    --color-surface-tertiary: var(--color-gray-700);
    --color-surface-inverse: var(--color-white, #fff);

    --color-text-primary: var(--color-gray-50);
    --color-text-secondary: var(--color-gray-300);
    --color-text-tertiary: var(--color-gray-500);
    --color-text-inverse: var(--color-gray-900);
    --color-text-link: var(--color-blue-400);
    --color-text-link-hover: var(--color-blue-300);

    --color-border-primary: var(--color-gray-700);
    --color-border-secondary: var(--color-gray-800);

    --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.2);
    --shadow-md: 0 4px 6px oklch(0 0 0 / 0.3);
    --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.4);
  }
}

/* 수동 토글 지원 */
[data-theme="dark"] {
  --color-surface-primary: var(--color-gray-900);
  /* ... 동일한 재정의 ... */
}

컴포넌트는 전혀 변경되지 않습니다. 다크 모드 클래스가 없습니다. 조건부 논리가 없습니다. 토큰이 모든 것을 처리합니다.

화이트 라벨 클라이언트용 브랜드 테마를 원하십니까? 동일한 패턴:

[data-theme="client-acme"] {
  --color-blue-500: oklch(0.55 0.20 280); /* 파란색 대신 보라색 */
  --color-action-primary: var(--color-blue-500);
  --radius-md: 1rem; /* 더 둥근 모서리를 선호함 */
}

Social Animal의 여러 Next.js 개발 프로젝트에서 이 접근 방식을 사용합니다. 멀티테넌트 테마는 일반적인 요구사항입니다.

컨테이너 쿼리를 사용한 반응형 토큰

이것은 Tailwind로 진정하게 할 수 없는 것입니다 (적어도 우아하게). 컨테이너 쿼리를 사용하면 뷰포트가 아닌 컨테이너 크기에 따라 토큰 값을 변경할 수 있습니다.

.card-grid {
  container-type: inline-size;
  container-name: card-grid;
}

@container card-grid (max-width: 500px) {
  .card {
    --_padding: var(--space-3);
    --_title-size: var(--font-size-base);
    --_gap: var(--space-2);
  }
}

@container card-grid (min-width: 501px) {
  .card {
    --_padding: var(--space-6);
    --_title-size: var(--font-size-lg);
    --_gap: var(--space-4);
  }
}

뷰포트가 아닌 자신의 컨텍스트에 응답하는 컴포넌트입니다. 이는 Astro 사이트용 컴포넌트 라이브러리를 구축할 때 특히 강력합니다. 컴포넌트가 매우 다른 레이아웃에서 재사용됩니다.

Figma와 디자인 토큰 동기화

Figma 변수 (2023년 출시, 이후 대폭 확장)는 우리의 3계층 토큰 모델과 직접 맞춰집니다. 워크플로우는 다음과 같습니다:

  1. Figma에서 토큰 정의 변수 패널 사용 (기본 → 의미론적 → 컴포넌트)
  2. 토큰 내보내기 Tokens Studio 플러그인 또는 Figma REST API 사용
  3. CSS로 변환 Style Dictionary 또는 최신 Cobalt UI 도구 사용
  4. 리포지토리에 커밋 tokens/ 디렉토리로

CSS 출력을 위한 Style Dictionary 구성은 다음과 같습니다:

{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "css": {
      "transformGroup": "css",
      "buildPath": "src/styles/tokens/",
      "files": [
        {
          "destination": "primitives.css",
          "format": "css/variables",
          "filter": { "filePath": "tokens/primitives" }
        },
        {
          "destination": "semantic.css",
          "format": "css/variables",
          "filter": { "filePath": "tokens/semantic" }
        }
      ]
    }
  }
}

결과는 Figma의 설계 변경 사항이 CSS 토큰으로 자동으로 흐르는 CI 파이프라인입니다. 수동 변환이 없고, 드리프트가 없습니다.

성능 비교: 바닐라 CSS vs Tailwind

저는 실제 마케팅 사이트에서 벤치마크를 실행했습니다 -- 동일한 설계, 두 가지 구현입니다. 숫자는 다음과 같습니다:

메트릭 Tailwind v4 바닐라 CSS 토큰 차이
총 CSS 크기 (gzip) 14.2 KB 6.8 KB -52%
First Contentful Paint 1.2s 1.0s -17%
Largest Contentful Paint 2.1s 1.8s -14%
CSS 구문 분석 시간 3.2ms 1.4ms -56%
HTML 크기 (gzip) 28.4 KB 22.1 KB -22%
빌드 시간 1.8s 0.4s* -78%

*Lightning CSS를 사용한 바닐라 CSS에 단순 @import 번들링.

HTML 크기 차이는 주목할 만합니다 -- Tailwind의 유틸리티 클래스는 마크업에 상당한 가중치를 추가합니다. 200개 이상의 요소가 있는 페이지에서 이 클래스 문자열은 누적됩니다.

즉, Tailwind v4 (초기 2025년 출시)는 Oxide 엔진으로 큰 개선을 이루었습니다. 격차가 좁혀졌습니다. 하지만 빌드 종속성이 없는 바닐라 CSS는 순수 성능에서 이기기 어렵습니다.

실제 토큰 파일 구조

최근 프로젝트의 실제 구조입니다 -- Next.js와 Sanity로 구축한 헤드리스 커머스 사이트:

src/styles/
├── tokens/
│   ├── primitives/
│   │   ├── colors.css
│   │   ├── spacing.css
│   │   ├── typography.css
│   │   ├── shadows.css
│   │   ├── borders.css
│   │   └── motion.css
│   ├── semantic/
│   │   ├── colors.css
│   │   ├── spacing.css
│   │   └── typography.css
│   ├── themes/
│   │   ├── light.css
│   │   ├── dark.css
│   │   └── high-contrast.css
│   └── index.css
├── components/
│   ├── button.css
│   ├── card.css
│   ├── input.css
│   ├── modal.css
│   ├── navigation.css
│   └── typography.css
├── layouts/
│   ├── grid.css
│   └── container.css
├── utilities/
│   └── helpers.css          /* 우리가 실제로 필요한 몇 가지 유틸리티 클래스 */
├── reset.css
└── main.css

utilities/helpers.css 파일은 흥미롭습니다 -- 진정하게 재사용 가능한 패턴을 위해 여전히 소수의 유틸리티 클래스를 작성합니다:

/* utilities/helpers.css */
.visually-hidden {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

.flow > * + * {
  margin-block-start: var(--flow-space, var(--space-stack-md));
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cluster-gap, var(--space-inline-md));
  align-items: center;
}

유틸리티도 토큰을 참조합니다. 모든 것이 연결되어 있습니다.

이것을 실용적으로 만드는 도구

별로 필요하지 않지만 몇 가지 도구가 DX를 크게 향상시킵니다:

도구 목적 메모
Lightning CSS 번들링, 축소, 공급업체 접두사 대부분의 사용 사례에서 PostCSS를 대체합니다. 매우 빠릅니다.
Style Dictionary 4 토큰 형식 변환 Figma → CSS, iOS, Android (단일 소스에서)
Cobalt UI W3C DTCG 토큰 도구 Style Dictionary의 최신 대안 (사양 정렬)
Tokens Studio Figma 플러그인 (토큰 관리) Figma 통합 최고 수준
CSS Utility Kit (VS Code) 커스텀 속성 자동완성 호버 시 토큰 값 표시
Open Props 미리 만든 CSS 커스텀 속성 라이브러리 처음부터 구축하지 않으려면 좋은 시작점

Lightning CSS는 특별한 호출이 필요합니다. Rust로 작성된 이것은 @import 인라인, 이전 브라우저용 중첩 컴파일, 그리고 축소를 단일 패스로 처리합니다. 이것은 현재 대부분의 헤드리스 CMS 구축에서 사용하는 것입니다.

lightningcss --bundle --minify src/styles/main.css -o dist/styles.css

이것이 전부입니다. PostCSS 설정이 없습니다. 플러그인 체인이 없습니다. 하나의 명령어입니다.

FAQ

빌드 단계 없이 디자인 토큰을 사용할 수 있습니까?

절대적으로. 최신 브라우저를 대상으로 하고 있다면 (2026년이므로 해야 함), 기본 CSS 커스텀 속성은 컴파일 없이 작동합니다. 유일한 것은 단일 파일로의 @import 번들링입니다 -- 브라우저는 여러 CSS 파일 가져오기를 잘 처리하지만, 프로덕션 성능을 위해 번들링하고 싶을 것입니다. Lightning CSS 또는 간단한 cat 명령어도 이를 처리할 수 있습니다.

바닐라 CSS 디자인 토큰은 Tailwind v4와 어떻게 비교됩니까?

Tailwind v4는 실제로 내부적으로 CSS 커스텀 속성으로 이동했으며, 이는 접근 방식을 검증합니다. 차이점은 개발자 경험에 있습니다: Tailwind는 HTML에서 적용할 유틸리티 클래스를 제공하고, 바닐라 토큰은 자신의 CSS에서 사용할 설계 변수를 제공합니다. 바닐라 토큰은 더 작은 CSS 및 HTML 출력을 생성하고, 테마에 더 많은 유연성을 제공하며, 클래스 이름 지정 시스템을 학습할 필요가 없습니다. Tailwind는 더 빠른 프로토타이핑과 더 큰 팀을 위한 더 강한 일관성 적용을 제공합니다.

디자인 토큰에 대한 TypeScript 타입 안전성은 어떻습니까?

CSS 모듈 또는 CSS-in-JS를 사용하는 경우 토큰 파일에서 TypeScript 타입을 생성할 수 있습니다. Style Dictionary 4와 Cobalt UI 모두 TypeScript 출력을 지원합니다. 순수 CSS의 경우 CSS 변수 자동완성 같은 VS Code 확장이 자동완성 및 검증으로 편집기 수준의 안전성을 제공합니다.

Open Props 대신 자신의 토큰을 구축해야 합니까?

Open Props는 프로토타입 또는 소규모 프로젝트에 탁월한 시작점입니다. 프로덕션 설계 시스템의 경우 브랜드와 일치하는 자신의 기본 토큰을 정의하고 싶을 것입니다. Open Props를 참조로 사용하고 완화 함수 또는 그림자 척도와 같은 접근 방식에서 선택할 수 있습니다.

여러 앱을 가진 모노리포에서 디자인 토큰을 어떻게 처리합니까?

CSS 파일을 내보내는 공유 tokens 패키지를 만드십시오. 각 앱은 토큰 패키지를 가져오고 자신의 테마 재정의를 추가할 수 있습니다. 이는 pnpm 또는 npm의 작업 공간에서 잘 작동합니다. 우리는 여러 브랜드 전자상거래 클라이언트를 위해 이를 수행했습니다. 각 상점은 동일한 기본 토큰을 공유하지만 고유한 의미론적 매핑을 가집니다.

바닐라 CSS는 Tailwind보다 개발하기가 더 느립니까?

처음에는 예 -- Tailwind가 무료로 제공하는 인프라를 설정합니다. 하지만 첫 주 또는 2주 후에는 속도가 비슷하거나 더 빠릅니다. HTML과 유틸리티 클래스 참조 간에 컨텍스트 전환을 하지 않습니다. 영어처럼 읽는 CSS를 작성합니다. 그리고 무언가를 변경해야 할 때 모든 인스턴스를 검색하는 대신 한 곳에서 변경합니다.

Tailwind에 의존하는 shadcn/UI와 같은 컴포넌트 라이브러리는 어떻습니까?

shadcn/UI는 환상적이지만 Tailwind 종속성은 구현 세부사항이지 기본 아키텍처가 아닙니다. 컴포넌트 패턴과 접근성 논리가 중요합니다. 여러 커뮤니티 포크가 Tailwind 클래스 대신 바닐라 CSS 토큰을 사용합니다. 또한 gradual하게 shadcn/UI 컴포넌트를 토큰 시스템으로 마이그레이션할 수 있습니다 -- 기본 Radix UI 기본 요소는 어떻게 스타일링되는지 신경 쓰지 않습니다.

Astro 또는 Next.js와 함께 이 접근 방식을 사용할 수 있습니까?

절대적으로. 두 프레임워크 모두 설정 없이 바닐라 CSS를 기본적으로 처리합니다. Astro의 범위 지정 스타일은 토큰 정의가 :root에 있으므로 범위 지정 컴포넌트 스타일에 자연스럽게 흐릅니다. CSS 모듈과 함께 전역 토큰 파일을 Next.js가 지원합니다. 우리는 정기적으로 Next.js 프로젝트 및 Astro 구축에서 이 정확한 설정을 사용합니다. 새 프로젝트를 탐색 중이라면 연락 주십시오 -- 우리가 배운 것을 기꺼이 공유하겠습니다.