- _index.md: 문서 목록 및 버전 관리 - 01~09: 아키텍처, API패턴, 컴포넌트, 폼, 스타일, 인증, 대시보드, 컨벤션 - 10: 문서 API 연동 스펙 (api-specs에서 이관) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.1 KiB
5.1 KiB
06. 스타일링 가이드
대상: 프론트엔드 개발자, 디자이너 버전: 1.0.0 최종 수정: 2026-03-09
1. 기술 스택
| 도구 | 역할 |
|---|---|
| Tailwind CSS 4 | 유틸리티 클래스 기반 스타일링 |
| shadcn/ui | Radix UI 기반 컴포넌트 라이브러리 |
| CSS Variables | 테마 토큰 (다크모드 대비) |
| lucide-react | 아이콘 |
2. 기본 규칙
사용
// ✅ Tailwind 클래스 사용
<div className="flex items-center gap-2 p-4 bg-muted rounded-lg">
// ✅ shadcn/ui 컴포넌트
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
금지
// ❌ 인라인 스타일
<div style={{ display: 'flex', padding: '16px' }}>
// ❌ CSS 모듈 / styled-components
import styles from './Component.module.css';
// ❌ 전역 CSS (globals.css 외)
3. 레이아웃 패딩 규칙
AuthenticatedLayout (<main>) → 패딩 없음
└── PageLayout → p-0 md:space-y-6 (패딩 담당)
└── 콘텐츠 영역
핵심: page.tsx에서 추가 패딩 래퍼 금지 (이중 패딩 방지)
// ✅ 올바름
<PageLayout>
<PageHeader title="..." />
<Card>...</Card>
</PageLayout>
// ❌ 이중 패딩
<div className="p-6"> {/* ← 금지 */}
<PageLayout>
...
</PageLayout>
</div>
4. 간격 시스템
| 용도 | 클래스 | 값 |
|---|---|---|
| 섹션 간 간격 | space-y-6 |
24px |
| 카드 내부 간격 | space-y-4 |
16px |
| 인라인 요소 간격 | gap-2 |
8px |
| 폼 필드 간격 | space-y-4 |
16px |
| 그리드 갭 | gap-4 또는 gap-6 |
16px / 24px |
5. 반응형 패턴
// 그리드: 모바일 1열 → 데스크톱 2~4열
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
// 숨기기/보이기
<div className="hidden md:block"> {/* 데스크톱만 */}
<div className="block md:hidden"> {/* 모바일만 */}
// 폰트 크기 반응형
<h1 className="text-lg md:text-2xl font-bold">
브레이크포인트
| 접두사 | 최소 너비 | 대상 |
|---|---|---|
| (없음) | 0px | 모바일 |
sm: |
640px | 소형 태블릿 |
md: |
768px | 태블릿 |
lg: |
1024px | 데스크톱 |
xl: |
1280px | 넓은 화면 |
6. 색상 시스템
shadcn/ui CSS 변수 기반 — 다크모드 자동 대응:
| 용도 | 클래스 | 설명 |
|---|---|---|
| 배경 | bg-background |
페이지 배경 |
| 카드 | bg-card |
카드 배경 |
| 강조 | bg-muted |
연한 배경 (테이블 호버 등) |
| 텍스트 | text-foreground |
기본 텍스트 |
| 보조 텍스트 | text-muted-foreground |
설명, 플레이스홀더 |
| 테두리 | border |
기본 테두리 |
| 위험 | text-destructive |
삭제, 에러 |
상태 색상
| 상태 | 텍스트 | 배경 |
|---|---|---|
| 입금/증가 | text-blue-600 |
bg-blue-50 |
| 출금/감소 | text-red-600 |
bg-red-50 |
| 성공/완료 | text-green-600 |
bg-green-50 |
| 경고/대기 | text-orange-500 |
bg-orange-50 |
| 비활성 | text-gray-400 |
bg-gray-50 |
7. 컴포넌트 스타일 규칙
버튼
// 주요 액션
<Button size="sm">등록</Button>
// 보조 액션
<Button variant="outline" size="sm">취소</Button>
// 위험 액션 (삭제)
<Button variant="destructive" size="sm">삭제</Button>
테이블
// 기본 셀 정렬
<TableCell className="text-center"> {/* 날짜, 상태, 번호 */}
<TableCell className="text-right"> {/* 금액 */}
<TableCell className="text-left"> {/* 텍스트 (기본) */}
// 합계 행
<TableRow className="bg-muted/50 font-medium">
Badge
<Badge variant="outline">기본</Badge>
<Badge variant="default">활성</Badge>
<Badge variant="destructive">에러</Badge>
8. 팝업/모달 규칙
| 용도 | 컴포넌트 | 비고 |
|---|---|---|
| 확인/취소 | AlertDialog (Radix) | alert(), confirm() 금지 |
| 데이터 입력 | Dialog (Radix) | prompt() 금지 |
| 알림 | toast (sonner) |
성공/에러 피드백 |
| 검색+선택 | SearchableSelectionModal | 커스텀 Dialog 조합 금지 |
// ✅ 토스트 사용
import { toast } from 'sonner';
toast.success('저장되었습니다.');
toast.error('저장에 실패했습니다.');
// ❌ alert 금지
alert('저장되었습니다.');
9. 아이콘
lucide-react 사용:
import { FileText, Settings, Search, Plus, Trash2 } from 'lucide-react';
// 인라인 아이콘
<FileText className="h-4 w-4" />
// 버튼 내 아이콘
<Button size="sm">
<Plus className="h-4 w-4 mr-1" />
등록
</Button>
10. 금액 표시
import { formatNumber } from '@/lib/utils/amount';
formatNumber(1234567) // "1,234,567"
formatNumber(0) // "0"
formatNumber(undefined) // "0"
테이블에서:
<TableCell className="text-right text-blue-600">
{formatNumber(item.amount)}
</TableCell>