- _index.md: 문서 목록 및 버전 관리 - 01~09: 아키텍처, API패턴, 컴포넌트, 폼, 스타일, 인증, 대시보드, 컨벤션 - 10: 문서 API 연동 스펙 (api-specs에서 이관) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
226 lines
5.1 KiB
Markdown
226 lines
5.1 KiB
Markdown
# 06. 스타일링 가이드
|
|
|
|
> **대상**: 프론트엔드 개발자, 디자이너
|
|
> **버전**: 1.0.0
|
|
> **최종 수정**: 2026-03-09
|
|
|
|
---
|
|
|
|
## 1. 기술 스택
|
|
|
|
| 도구 | 역할 |
|
|
|------|------|
|
|
| **Tailwind CSS 4** | 유틸리티 클래스 기반 스타일링 |
|
|
| **shadcn/ui** | Radix UI 기반 컴포넌트 라이브러리 |
|
|
| **CSS Variables** | 테마 토큰 (다크모드 대비) |
|
|
| **lucide-react** | 아이콘 |
|
|
|
|
---
|
|
|
|
## 2. 기본 규칙
|
|
|
|
### 사용
|
|
```typescript
|
|
// ✅ 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';
|
|
```
|
|
|
|
### 금지
|
|
```typescript
|
|
// ❌ 인라인 스타일
|
|
<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에서 추가 패딩 래퍼 금지 (이중 패딩 방지)
|
|
|
|
```typescript
|
|
// ✅ 올바름
|
|
<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. 반응형 패턴
|
|
|
|
```typescript
|
|
// 그리드: 모바일 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. 컴포넌트 스타일 규칙
|
|
|
|
### 버튼
|
|
```typescript
|
|
// 주요 액션
|
|
<Button size="sm">등록</Button>
|
|
|
|
// 보조 액션
|
|
<Button variant="outline" size="sm">취소</Button>
|
|
|
|
// 위험 액션 (삭제)
|
|
<Button variant="destructive" size="sm">삭제</Button>
|
|
```
|
|
|
|
### 테이블
|
|
```typescript
|
|
// 기본 셀 정렬
|
|
<TableCell className="text-center"> {/* 날짜, 상태, 번호 */}
|
|
<TableCell className="text-right"> {/* 금액 */}
|
|
<TableCell className="text-left"> {/* 텍스트 (기본) */}
|
|
|
|
// 합계 행
|
|
<TableRow className="bg-muted/50 font-medium">
|
|
```
|
|
|
|
### Badge
|
|
```typescript
|
|
<Badge variant="outline">기본</Badge>
|
|
<Badge variant="default">활성</Badge>
|
|
<Badge variant="destructive">에러</Badge>
|
|
```
|
|
|
|
---
|
|
|
|
## 8. 팝업/모달 규칙
|
|
|
|
| 용도 | 컴포넌트 | 비고 |
|
|
|------|---------|------|
|
|
| 확인/취소 | AlertDialog (Radix) | `alert()`, `confirm()` 금지 |
|
|
| 데이터 입력 | Dialog (Radix) | `prompt()` 금지 |
|
|
| 알림 | `toast` (sonner) | 성공/에러 피드백 |
|
|
| 검색+선택 | SearchableSelectionModal | 커스텀 Dialog 조합 금지 |
|
|
|
|
```typescript
|
|
// ✅ 토스트 사용
|
|
import { toast } from 'sonner';
|
|
toast.success('저장되었습니다.');
|
|
toast.error('저장에 실패했습니다.');
|
|
|
|
// ❌ alert 금지
|
|
alert('저장되었습니다.');
|
|
```
|
|
|
|
---
|
|
|
|
## 9. 아이콘
|
|
|
|
**lucide-react** 사용:
|
|
|
|
```typescript
|
|
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. 금액 표시
|
|
|
|
```typescript
|
|
import { formatNumber } from '@/lib/utils/amount';
|
|
|
|
formatNumber(1234567) // "1,234,567"
|
|
formatNumber(0) // "0"
|
|
formatNumber(undefined) // "0"
|
|
```
|
|
|
|
테이블에서:
|
|
```typescript
|
|
<TableCell className="text-right text-blue-600">
|
|
{formatNumber(item.amount)}
|
|
</TableCell>
|
|
```
|