# 03. 컴포넌트 설계

> **대상**: 프론트엔드 개발자, 기획자
> **버전**: 1.0.0
> **최종 수정**: 2026-03-09

---

## 1. 설계 원칙

- **모든 페이지는 Client Component** (`'use client'` 필수)
- **Config-Driven**: 설정 객체로 페이지 동작 정의 → 일관성 + 빠른 개발
- **기존 패턴 우선**: 새 컴포넌트 만들기 전 반드시 유사 컴포넌트 검색
- **계층 준수**: atoms → molecules → organisms → templates → pages

---

## 2. 페이지 3대 유형

### 2.1 리스트 페이지 → UniversalListPage

**사용 현황**: 59+ 페이지

```typescript
// 패턴: page.tsx는 얇은 껍데기, 비즈니스 로직은 도메인 컴포넌트에
// src/app/[locale]/(protected)/accounting/bills/page.tsx
'use client';
import { BillManagement } from '@/components/accounting/BillManagement';
export default function BillsPage() {
  return <BillManagement />;
}

// src/components/accounting/BillManagement/index.tsx
export function BillManagement() {
  const config: UniversalListConfig<BillRecord> = {
    title: '어음관리',
    icon: FileText,
    columns: [...],
    actions: { getList: getBills },
    // ... 나머지 설정
  };
  return <UniversalListPage config={config} />;
}
```

**config로 제어하는 것들:**
- 컬럼 정의, 정렬, 필터
- 검색/날짜 선택기
- 통계 카드
- 체크박스/선택
- 액션 버튼
- 모바일 카드 렌더링
- Excel 내보내기

### 2.2 상세/폼 페이지 → IntegratedDetailTemplate

**모드**: create(등록), view(조회), edit(수정)

```typescript
<IntegratedDetailTemplate
  mode="create"
  title="품목 등록"
  fields={fieldDefinitions}
  onSave={handleSave}
  onDelete={handleDelete}
/>
```

**또는 Card 기반 수동 구성** (기존 패턴):
```typescript
<PageLayout>
  <PageHeader title="품목 상세" />
  <Card>
    <CardContent>
      {/* 폼 필드들 */}
    </CardContent>
  </Card>
</PageLayout>
```

### 2.3 대시보드 → 커스텀 섹션 조합

CEO 대시보드처럼 여러 섹션을 조합하는 경우:
```typescript
<PageLayout>
  <SummaryNavBar />
  <div className="space-y-6">
    {sectionOrder.map(key => renderSection(key))}
  </div>
</PageLayout>
```

---

## 3. 컴포넌트 계층별 가이드

### atoms (src/components/atoms/)
- 가장 작은 재사용 단위
- HTML 요소 확장 또는 단일 기능
- 예: ScrollableButtonGroup, PhoneInput, BusinessNumberInput

### molecules (src/components/molecules/)
- atom 2개 이상 조합
- **FormField**: Label + Input 통합 (신규 폼 필수)
- 예: FormField, DateRangeFilter

### organisms (src/components/organisms/)
- 독립적 기능 블록, 페이지에 바로 배치 가능
- **내보내기 확인**: `src/components/organisms/index.ts`

| 컴포넌트 | 용도 |
|---------|------|
| PageHeader | 페이지 제목 + 액션 버튼 |
| PageLayout | 페이지 콘텐츠 래퍼 (패딩/max-width) |
| DataTable | 범용 데이터 테이블 |
| StatCards | 통계 카드 모음 |
| SearchFilter | 검색/필터 바 |
| SearchableSelectionModal\<T\> | 검색+선택 모달 (제네릭) |
| MobileCard | 모바일 리스트 카드 |

### templates (src/components/templates/)
- 페이지 전체 구조 정의
- config 객체로 동작 제어

| 템플릿 | 용도 | 사용 수 |
|--------|------|--------|
| UniversalListPage | 리스트/목록 페이지 | 59+ |
| IntegratedDetailTemplate | 상세/등록/수정 페이지 | 10+ |

### 도메인 컴포넌트 (src/components/{domain}/)
- 비즈니스 로직 포함
- 도메인별 폴더 분류

```
components/
├── accounting/     # 회계: 입금, 출금, 전표, 어음, 세금계산서
├── hr/             # 인사: 사원, 급여, 근태
├── production/     # 생산: 공정, 생산일보
├── orders/         # 영업: 주문, 견적, 수주
├── business/       # 경영: CEO 대시보드
└── common/         # 공통: 계정과목 설정 등 여러 도메인에서 사용
```

---

## 4. 새 페이지 만들기 체크리스트

### 리스트 페이지
1. `src/app/[locale]/(protected)/{domain}/{page}/page.tsx` 생성
2. `src/components/{domain}/{ComponentName}/index.tsx` 생성
3. `src/components/{domain}/{ComponentName}/actions.ts` 생성
4. UniversalListPage config 작성
5. types 정의 (API 응답 → 프론트 타입 변환)

### 상세/폼 페이지
1. 기존 유사 페이지 검색 (패턴 참고)
2. IntegratedDetailTemplate 사용 가능한지 확인
3. 아니면 Card 기반 수동 구성

### 모달/팝업
1. `SearchableSelectionModal<T>` 사용 가능한지 먼저 확인
2. 아니면 Radix Dialog 직접 사용
3. `alert()`, `confirm()` 사용 금지 → Dialog 또는 toast

---

## 5. 컴포넌트 레지스트리

개발 환경에서 `/dev/component-registry` 접속하면:
- 전체 컴포넌트 목록 (실시간 스캔)
- 컴포넌트 간 관계도 (imports, usedBy)
- 새 컴포넌트 생성 전 기존 컴포넌트 확인 필수
