- _index.md: 문서 목록 및 버전 관리 - 01~09: 아키텍처, API패턴, 컴포넌트, 폼, 스타일, 인증, 대시보드, 컨벤션 - 10: 문서 API 연동 스펙 (api-specs에서 이관) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.9 KiB
4.9 KiB
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+ 페이지
// 패턴: 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(수정)
<IntegratedDetailTemplate
mode="create"
title="품목 등록"
fields={fieldDefinitions}
onSave={handleSave}
onDelete={handleDelete}
/>
또는 Card 기반 수동 구성 (기존 패턴):
<PageLayout>
<PageHeader title="품목 상세" />
<Card>
<CardContent>
{/* 폼 필드들 */}
</CardContent>
</Card>
</PageLayout>
2.3 대시보드 → 커스텀 섹션 조합
CEO 대시보드처럼 여러 섹션을 조합하는 경우:
<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. 새 페이지 만들기 체크리스트
리스트 페이지
src/app/[locale]/(protected)/{domain}/{page}/page.tsx생성src/components/{domain}/{ComponentName}/index.tsx생성src/components/{domain}/{ComponentName}/actions.ts생성- UniversalListPage config 작성
- types 정의 (API 응답 → 프론트 타입 변환)
상세/폼 페이지
- 기존 유사 페이지 검색 (패턴 참고)
- IntegratedDetailTemplate 사용 가능한지 확인
- 아니면 Card 기반 수동 구성
모달/팝업
SearchableSelectionModal<T>사용 가능한지 먼저 확인- 아니면 Radix Dialog 직접 사용
alert(),confirm()사용 금지 → Dialog 또는 toast
5. 컴포넌트 레지스트리
개발 환경에서 /dev/component-registry 접속하면:
- 전체 컴포넌트 목록 (실시간 스캔)
- 컴포넌트 간 관계도 (imports, usedBy)
- 새 컴포넌트 생성 전 기존 컴포넌트 확인 필수