Alpha

🏆 AdorableCSS Best Practices

대규모 프로젝트에서의 모범 사례

🎯 핵심 원칙

1. 의미론적 우선 (Semantic First)

<!-- ❌ 유틸리티 나열 -->
<h1 class="font(2xl) bold line-height(1.2) mb(lg) c(gray-900)">

<!-- ✅ 의미론적 클래스 -->
<h1 class="heading(xl)">

2. 컴포넌트 추상화 (Component Abstraction)

<!-- ❌ 반복되는 패턴 -->
<div class="bg(white) p(xl) r(lg) shadow(md)">
<div class="bg(white) p(xl) r(lg) shadow(md)">

<!-- ✅ 재사용 가능한 컴포넌트 -->
<div class="card">

3. 일관성 유지 (Consistency)

<!-- ❌ 혼재된 스타일 -->
<div style="margin: 20px" class="p(md)">
<div class="m(20px) p(md)">

<!-- ✅ 토큰 시스템 준수 -->
<div class="m(lg) p(md)">

📐 아키텍처 패턴

1. 레이어드 구조

🎨 Theme Layer (CSS Variables)
  ↓
📦 Component Layer (재사용 컴포넌트)
  ↓
🔧 Utility Layer (AdorableCSS 유틸리티)
  ↓
💻 Implementation Layer (실제 구현)

2. 컴포넌트 계층

// 1. Base Components (atoms)
export const Button = ({ variant, size, children }) => (
  <button class={cx(
    'btn',
    variants[variant],
    sizes[size]
  )}>
    {children}
  </button>
)

// 2. Composite Components (molecules)
export const Card = ({ title, children }) => (
  <div class="card">
    {title && <h3 class="heading(md)">{title}</h3>}
    <div class="vbox gap(md)">
      {children}
    </div>
  </div>
)

// 3. Layout Components (organisms)
export const PageLayout = ({ sidebar, main }) => (
  <div class="hbox min-h(screen)">
    <aside class="w(260px) hidden lg:block">
      {sidebar}
    </aside>
    <main class="flex(1)">
      {main}
    </main>
  </div>
)

🎨 스타일링 전략

1. 클래스 구성 순서

<div class="
  [1. 컴포넌트] card
  [2. 레이아웃] hbox(middle)
  [3. 크기] w(full) h(200)
  [4. 스타일] bg(white) shadow(md)
  [5. 상태] hover:shadow(lg)
  [6. 반응형] md:h(300)
">

2. 조건부 스타일링 패턴

// 유틸리티 함수
const cls = (...classes) => classes.filter(Boolean).join(' ')

// 사용 예시
function Alert({ type, children }) {
  const styles = {
    info: 'bg(blue-50) bc(blue-200) c(blue-800)',
    warning: 'bg(yellow-50) bc(yellow-200) c(yellow-800)',
    error: 'bg(red-50) bc(red-200) c(red-800)'
  }
  
  return (
    <div class={cls(
      'p(md) r(md) b(1)',
      styles[type]
    )}>
      {children}
    </div>
  )
}

3. 테마 시스템

/* themes/default.css */
:root {
  /* 색상 팔레트 */
  --color-primary: oklch(60% 0.15 250);
  --color-secondary: oklch(70% 0.1 350);
  
  /* 의미론적 색상 */
  --color-success: var(--adorable-green-500);
  --color-danger: var(--adorable-red-500);
  
  /* 컴포넌트 토큰 */
  --card-padding: var(--adorable-space-xl);
  --card-radius: var(--adorable-radius-lg);
}

/* 다크 테마 */
[data-theme="dark"] {
  --color-primary: oklch(70% 0.15 250);
  --card-bg: var(--adorable-gray-800);
}

🔄 상태 관리와 스타일

1. 데이터 속성 활용

<!-- 컴포넌트 상태 -->
<div 
  class="tab-panel"
  data-state="active"
  data-orientation="horizontal"
>
  <!-- CSS에서 선택 -->
  <style>
    .tab-panel[data-state="active"] {
      @apply opacity(100) visible;
    }
  </style>
</div>

2. CSS 변수로 동적 스타일

// 동적 진행률 바
function ProgressBar({ value }) {
  return (
    <div 
      class="h(8) bg(gray-200) r(full) clip"
      style={{ '--progress': `${value}%` }}
    >
      <div class="h(full) bg(blue-500) w(--progress) transition" />
    </div>
  )
}

📱 반응형 디자인

1. 모바일 우선 접근

<!-- 기본: 모바일 → 점진적 향상 -->
<div class="
  grid(1)          /* 모바일: 1열 */
  sm:grid(2)       /* 작은 화면: 2열 */
  md:grid(3)       /* 중간 화면: 3열 */
  lg:grid(4)       /* 큰 화면: 4열 */
  gap(md)          /* 기본 간격 */
  lg:gap(xl)       /* 큰 화면: 넓은 간격 */
">

2. 컨테이너 쿼리 준비

/* 미래 대비 */
.card-container {
  container-type: inline-size;
}

.card {
  @apply p(md);
  
  @container (min-width: 400px) {
    @apply p(xl) grid(2);
  }
}

🚀 성능 최적화

1. 클래스 재사용

// ❌ 동적 클래스 생성
items.map(item => `p(${item.padding})`)

// ✅ 정적 클래스 매핑
const paddingMap = {
  small: 'p(sm)',
  medium: 'p(md)',
  large: 'p(lg)'
}
items.map(item => paddingMap[item.size])

2. 컴포넌트 메모이제이션

// React 예시
const ExpensiveCard = memo(({ data }) => (
  <div class="card hover:shadow(xl) transition">
    {/* 복잡한 렌더링 */}
  </div>
))

3. 레이지 로딩

// 대형 컴포넌트 지연 로딩
const HeavyComponent = lazy(() => import('./HeavyComponent'))

// 사용
<Suspense fallback={<div class="animate(pulse)">Loading...</div>}>
  <HeavyComponent />
</Suspense>

🧩 컴포넌트 라이브러리

1. 기본 구조

components/
├── primitives/         # 기본 요소
│   ├── Button/
│   │   ├── Button.tsx
│   │   ├── Button.stories.tsx
│   │   └── Button.test.tsx
│   └── Input/
├── patterns/          # 조합 패턴
│   ├── Card/
│   └── Modal/
└── layouts/          # 레이아웃
    ├── Stack/
    └── Grid/

2. 컴포넌트 문서화

interface ButtonProps {
  /** 버튼 변형 */
  variant?: 'primary' | 'secondary' | 'danger'
  /** 버튼 크기 */
  size?: 'sm' | 'md' | 'lg'
  /** 전체 너비 */
  fullWidth?: boolean
}

/**
 * 기본 버튼 컴포넌트
 * 
 * @example
 * <Button variant="primary" size="md">
 *   클릭하세요
 * </Button>
 */
export const Button: FC<ButtonProps> = ({ ... }) => { ... }

🔍 디버깅 전략

1. 개발 도구 활용

// 개발 환경에서만 디버그 정보
if (process.env.NODE_ENV === 'development') {
  console.log('Applied classes:', element.className)
  console.log('Computed styles:', getComputedStyle(element))
}

2. 클래스 검증

// 클래스 유효성 검사
function validateClasses(classes) {
  const invalid = classes.filter(cls => 
    !isValidAdorableClass(cls)
  )
  
  if (invalid.length > 0) {
    console.warn('Invalid classes:', invalid)
  }
}

📋 체크리스트

코드 리뷰 시

  • [ ] 의미론적 클래스를 우선 사용했는가?
  • [ ] 반복되는 패턴은 컴포넌트화 했는가?
  • [ ] 토큰 시스템을 준수했는가?
  • [ ] 반응형 디자인이 적용되었는가?
  • [ ] 접근성을 고려했는가?

프로덕션 배포 전

  • [ ] 불필요한 클래스는 제거했는가?
  • [ ] 성능 프로파일링을 했는가?
  • [ ] 크로스 브라우저 테스트를 했는가?
  • [ ] 번들 크기를 확인했는가?

🚫 안티패턴

1. 인라인 스타일 남용

<!-- ❌ -->
<div class="p(20px) m(30px) w(250px)">

<!-- ✅ -->
<div class="p(lg) m(xl) w(64)">

2. 과도한 중첩

<!-- ❌ -->
<div class="hbox"><div class="hbox"><div class="hbox">

<!-- ✅ -->
<div class="grid grid-cols-3">

3. 불필요한 !important

<!-- ❌ -->
<div class="bg(red)! c(white)! p(md)!">

<!-- ✅ Layer 시스템 활용 -->
<div class="error-message">

🎯 마무리

AdorableCSS는 도구입니다. 모든 상황에 맞는 만능 해결책은 아닙니다.

핵심은:

  1. 팀과 일관된 규칙 유지
  2. 의미 있는 추상화 만들기
  3. 성능과 가독성의 균형
  4. 지속적인 리팩토링

“Write CSS the way you think” - 생각하는 방식으로 CSS를 작성하되, 유지보수를 고려하세요.


참고 자료