Skip to content

Latest commit

 

History

History
291 lines (226 loc) · 9.67 KB

File metadata and controls

291 lines (226 loc) · 9.67 KB
Devup UI logo

CSS-in-JS의 미래 — 제로 런타임, 완전한 문법 지원

Zero Config · Zero FOUC · Zero Runtime · 모든 CSS-in-JS 문법 완벽 지원



English | 한국어

왜 Devup UI인가?

Devup UI는 단순한 CSS-in-JS 라이브러리가 아닙니다 — CSS-in-JS의 미래 그 자체입니다.

기존 CSS-in-JS 솔루션들은 개발자 경험과 성능 사이에서 타협을 강요했습니다. Devup UI는 Rust 기반 전처리기를 통해 모든 스타일을 빌드 타임에 처리함으로써 이 트레이드오프를 완전히 제거합니다.

  • 완전한 문법 지원: 변수, 조건문, 반응형 배열, 가상 선택자 등 모든 CSS-in-JS 패턴을 완벽하게 지원
  • 익숙한 API: styled-components, Emotion과 호환되는 styled() API 제공
  • 진정한 제로 런타임: 런타임에서 스타일링을 위한 JavaScript 실행이 전혀 없습니다
  • 가장 작은 번들 크기: 최적화된 클래스명(a, b, ... aa, ab)으로 CSS 출력 최소화
  • 가장 빠른 빌드 속도: Rust + WebAssembly가 제공하는 압도적인 전처리 성능

설치

npm install @devup-ui/react

# Next.js
npm install @devup-ui/next-plugin

# Vite
npm install @devup-ui/vite-plugin

# Rsbuild
npm install @devup-ui/rsbuild-plugin

# Webpack
npm install @devup-ui/webpack-plugin

기능

  • 전처리기 — 모든 CSS 추출이 빌드 타임에 완료됩니다
  • Zero Config — 별도 설정 없이 바로 사용 가능
  • Zero FOUC — 스타일 깜빡임 없음, Provider 불필요
  • Zero Runtime — 스타일링을 위한 클라이언트 JavaScript 실행 없음
  • RSC 지원 — React Server Components 완벽 호환
  • 라이브러리 모드 — 추출된 스타일과 함께 컴포넌트 라이브러리 빌드 가능
  • 동적 테마 — CSS 변수 기반 제로 코스트 테마 전환
  • 타입 세이프 테마 — 테마 토큰에 대한 완전한 TypeScript 지원
  • 가장 작고 빠름 — 벤치마크로 증명됨

비교 벤치마크

최신 CI 벤치마크ubuntu-latest에서 실행했습니다. 모든 Next.js 빌드는 네이티브 TypeScript 7 CLI로 타입 검사를 수행합니다.

Webpack 값은 cold build 1회 결과입니다.

라이브러리 버전 빌드 시간 빌드 사이즈
tailwindcss 4.3.3 15.55s 66,479,450 bytes
styleX 0.19.0 34.27s 95,417,163 bytes
vanilla-extract 1.21.2 14.91s 67,711,539 bytes
kuma-ui 1.6.4 16.43s 74,774,187 bytes
panda-css 1.12.0 16.82s 70,983,831 bytes
chakra-ui 3.37.0 24.79s 206,598,161 bytes
mui 9.4.0 17.12s 100,621,370 bytes
devup-ui (per-file CSS) 1.0.40 13.43s 66,577,087 bytes
devup-ui (single CSS) 1.0.40 13.37s 66,564,796 bytes

Turbopack 값은 실행 순서를 번갈아 측정한 cold build 6회의 중앙값입니다.

라이브러리 버전 빌드 시간 중앙값 빌드 사이즈
tailwindcss 4.3.3 6.55s 38,386,955 bytes
devup-ui (direct APIs, single CSS) 1.0.40 6.54s 36,519,234 bytes
devup-ui (static .css.ts) 1.0.40 6.47s 36,550,197 bytes

Turbopack 측정 범위는 서로 겹치므로 direct API 결과는 이 fixture에서 Tailwind와 사실상 동률입니다. static .css.ts 행은 lite WASM 빠른 경로를 사용하며, full Boa evaluator가 필요한 dynamic .css.ts는 해당 중앙값에 포함되지 않습니다.

작동 원리

Devup UI는 빌드 타임에 컴포넌트를 변환합니다. 클래스명은 CSS 크기를 최소화하기 위해 압축된 base-37 인코딩을 사용하여 생성됩니다.

기본 변환:

// 개발자가 작성:
const example = <Box _hover={{ bg: 'blue' }} bg="red" p={4} />

// Devup UI가 생성:
const generated = <div className="a b c" />

// CSS:
// .a { background-color: red; }
// .b { padding: 1rem; }
// .c:hover { background-color: blue; }

동적 값은 CSS 변수로 변환:

// 개발자가 작성:
const example = <Box bg={colorVariable} />

// Devup UI가 생성:
const generated = <div className="a" style={{ '--a': colorVariable }} />

// CSS:
// .a { background-color: var(--a); }

복잡한 표현식과 반응형 배열 — 완벽 지원:

// 개발자가 작성:
const example = <Box bg={['red', 'blue', isActive ? 'green' : dynamicColor]} />

// Devup UI가 생성:
const generated = (
  <div
    className={`a b ${isActive ? 'c' : 'd'}`}
    style={{ '--d': dynamicColor }}
  />
)

// 각 브레이크포인트에 대한 반응형 CSS 생성

타입 세이프 테마:

devup.json

{
  "theme": {
    "colors": {
      "default": {
        "primary": "#0070f3",
        "text": "#000"
      },
      "dark": {
        "primary": "#3291ff",
        "text": "#fff"
      }
    },
    "typography": {
      "heading": {
        "fontFamily": "Pretendard",
        "fontSize": "24px",
        "fontWeight": 700,
        "lineHeight": 1.3
      }
    }
  }
}
// 타입 세이프 테마 토큰
const textExample = <Text color="$primary" />
const boxExample = <Box typography="$heading" />

사용자 정의 shorthand:

Shorthand는 디자인 토큰이 아니므로 devup.json이 아니라 빌드 플러그인 옵션에서 정의합니다. 각 shorthand는 하나의 prop 값을 여러 CSS 속성에 동일하게 적용합니다.

// vite.config.ts
export default defineConfig({
  plugins: [
    DevupUI({
      shorthands: {
        insetX: ['left', 'right'],
        scrollMarginX: ['scrollMarginLeft', 'scrollMarginRight'],
      },
    }),
  ],
})

플러그인이 실행되면 기본 경로인 df/theme.d.ts에 선언이 생성되어 일반 prop, 반응형 배열, 가상 선택자, 사용자 정의 selector에서 이름과 값 타입이 자동 완성됩니다. 설정을 바꾼 뒤에는 빌드 도구를 재시작해야 합니다. tsconfig.jsonincludesrc로 제한되어 있다면 df/*.d.ts도 포함하세요. distDir를 바꿨다면 해당 경로를 포함하면 됩니다.

const pinned = <Box insetX={0} />
const responsive = <Box insetX={[0, null, 'auto']} />
const interactive = <Box _hover={{ insetX: 4 }} />

반응형 + 가상 선택자 동시 사용:

// 반응형과 가상 선택자 함께 사용
const example = <Box _hover={{ bg: ['red', 'blue'] }} />

// 동일한 표현
const example2 = <Box _hover={[{ bg: 'red' }, { bg: 'blue' }]} />

styled-components / Emotion 호환 styled() API:

import { styled } from '@devup-ui/react'

// styled-components, Emotion 사용자에게 익숙한 문법
const Card = styled('div', {
  bg: 'white',
  p: 4, // 4 * 4 = 16px
  borderRadius: '8px',
  boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
  _hover: {
    boxShadow: '0 10px 15px rgba(0, 0, 0, 0.1)',
  },
})

// 버튼 예시
const Button = styled('button', {
  px: 4, // 4 * 4 = 16px
  py: 2, // 2 * 4 = 8px
  borderRadius: '4px',
  cursor: 'pointer',
})

// 사용
const cardExample = <Card>Content</Card>
const buttonExample = <Button>Click me</Button>

영감

  • Styled System — 문법적인 부분에서 영감을 받았습니다
  • Chakra UI — 문법적인 부분에서 영감을 받았습니다
  • Theme UI — 전체적인 시스템적인 부분에서 영감을 받았습니다
  • Vanilla Extract — 전처리기 부분에서 영감을 받았습니다
  • Rainbow Sprinkles — 전체적인 시스템적인 부분에서 영감을 받았습니다
  • Kuma UI — 문법적인 부분과 방법론에서 영감을 받았습니다

기여 방법

요구 사항

  • Node.js (LTS 버전 권장)
  • Rust 컴파일러
  • Bun 패키지 매니저

개발 환경 설정

개발 환경을 위해 아래 패키지들을 설치합니다:

bun install
bun run build
cargo install cargo-tarpaulin
cargo install wasm-pack

설치 후 bun run test를 실행하여 문제가 없는지 확인합니다.