ERP-node/popdocs/archive/COMPONENT_ROADMAP.md

390 lines
8.9 KiB
Markdown

# POP 컴포넌트 로드맵
## 큰 그림: 3단계 접근
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 1단계: 기초 블록 2단계: 조합 블록 3단계: 완성 화면 │
│ ─────────────── ─────────────── ─────────────── │
│ │
│ [버튼] [입력창] [폼 그룹] [작업지시 화면] │
│ [아이콘] [라벨] → [카드] → [실적입력 화면] │
│ [뱃지] [로딩] [리스트] [모니터링 대시보드] │
│ [테이블] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 1단계: 기초 블록 (Primitive)
가장 작은 단위. 다른 곳에서 재사용됩니다.
### 필수 기초 블록
| 컴포넌트 | 역할 | 우선순위 |
|---------|------|---------|
| `PopButton` | 모든 버튼 | 1 |
| `PopInput` | 텍스트 입력 | 1 |
| `PopLabel` | 라벨/제목 | 1 |
| `PopIcon` | 아이콘 표시 | 1 |
| `PopBadge` | 상태 뱃지 | 2 |
| `PopLoading` | 로딩 스피너 | 2 |
| `PopDivider` | 구분선 | 3 |
### PopButton 예시
```typescript
interface PopButtonProps {
children: React.ReactNode;
variant: "primary" | "secondary" | "danger" | "success";
size: "sm" | "md" | "lg" | "xl";
disabled?: boolean;
loading?: boolean;
icon?: string;
fullWidth?: boolean;
onClick?: () => void;
}
// 사용
<PopButton variant="primary" size="lg">
작업 완료
</PopButton>
```
### PopInput 예시
```typescript
interface PopInputProps {
type: "text" | "number" | "date" | "time";
value: string | number;
onChange: (value: string | number) => void;
label?: string;
placeholder?: string;
required?: boolean;
error?: string;
size: "md" | "lg"; // POP은 lg 기본
}
// 사용
<PopInput
type="number"
label="수량"
size="lg"
value={qty}
onChange={setQty}
/>
```
---
## 2단계: 조합 블록 (Compound)
기초 블록을 조합한 중간 단위.
### 조합 블록 목록
| 컴포넌트 | 구성 | 용도 |
|---------|------|-----|
| `PopFormField` | Label + Input + Error | 폼 입력 그룹 |
| `PopCard` | Container + Header + Body | 정보 카드 |
| `PopListItem` | Container + Content + Action | 리스트 항목 |
| `PopNumberPad` | Grid + Buttons | 숫자 입력 |
| `PopStatusBox` | Icon + Label + Value | 상태 표시 |
### PopFormField 예시
```typescript
// 기초 블록 조합
function PopFormField({ label, required, error, children }) {
return (
<div className="pop-form-field">
<PopLabel required={required}>{label}</PopLabel>
{children}
{error && <span className="error">{error}</span>}
</div>
);
}
// 사용
<PopFormField label="품번" required error={errors.itemCode}>
<PopInput type="text" value={itemCode} onChange={setItemCode} />
</PopFormField>
```
### PopCard 예시
```typescript
function PopCard({ title, badge, children, onClick }) {
return (
<div className="pop-card" onClick={onClick}>
<div className="pop-card-header">
<PopLabel size="lg">{title}</PopLabel>
{badge && <PopBadge>{badge}</PopBadge>}
</div>
<div className="pop-card-body">
{children}
</div>
</div>
);
}
// 사용
<PopCard title="작업지시 #1234" badge="진행중">
<p>목표 수량: 100개</p>
<p>완료 수량: 45개</p>
</PopCard>
```
---
## 3단계: 복합 컴포넌트 (Complex)
비즈니스 로직이 포함된 완성형.
### 복합 컴포넌트 목록
| 컴포넌트 | 기능 | 데이터 |
|---------|------|-------|
| `PopDataTable` | 대량 데이터 표시/편집 | API 연동 |
| `PopCardList` | 카드 형태 리스트 | API 연동 |
| `PopBarcodeScanner` | 바코드/QR 스캔 | 카메라/외부장치 |
| `PopKpiGauge` | KPI 게이지 | 실시간 데이터 |
| `PopAlarmList` | 알람 목록 | 웹소켓 |
| `PopProcessFlow` | 공정 흐름도 | 공정 데이터 |
### PopDataTable 예시
```typescript
interface PopDataTableProps {
// 데이터
data: any[];
columns: Column[];
// 기능
selectable?: boolean;
editable?: boolean;
sortable?: boolean;
// 반응형 (자동)
responsiveColumns?: {
tablet: string[];
mobile: string[];
};
// 이벤트
onRowClick?: (row: any) => void;
onSelectionChange?: (selected: any[]) => void;
}
// 사용
<PopDataTable
data={workOrders}
columns={[
{ key: "orderNo", label: "지시번호" },
{ key: "itemName", label: "품명" },
{ key: "qty", label: "수량", align: "right" },
{ key: "status", label: "상태" },
]}
responsiveColumns={{
tablet: ["orderNo", "itemName", "qty", "status"],
mobile: ["orderNo", "qty"], // 모바일은 2개만
}}
onRowClick={(row) => openDetail(row.id)}
/>
```
---
## 개발 순서 제안
### Phase 1: 기초 (1-2주)
```
Week 1:
- PopButton (모든 버튼의 기반)
- PopInput (모든 입력의 기반)
- PopLabel
- PopIcon
Week 2:
- PopBadge
- PopLoading
- PopDivider
```
### Phase 2: 조합 (2-3주)
```
Week 3:
- PopFormField (폼의 기본 단위)
- PopCard (카드의 기본 단위)
Week 4:
- PopListItem
- PopStatusBox
- PopNumberPad
Week 5:
- PopModal
- PopToast
```
### Phase 3: 복합 (3-4주)
```
Week 6-7:
- PopDataTable (가장 복잡)
- PopCardList
Week 8-9:
- PopBarcodeScanner
- PopKpiGauge
- PopAlarmList
- PopProcessFlow
```
---
## 컴포넌트 설계 원칙
### 1. 크기는 외부에서 제어
```typescript
// 좋음: 크기를 props로 받음
<PopButton size="lg">확인</PopButton>
// 나쁨: 내부에서 크기 고정
<button style={{ height: "48px" }}>확인</button>
```
### 2. 최소 크기는 내부에서 보장
```typescript
// 컴포넌트 내부
const styles = {
minHeight: 48, // 터치 최소 크기 보장
minWidth: 80,
};
```
### 3. 반응형은 자동
```typescript
// 좋음: 화면 크기에 따라 자동 조절
<PopFormField label="이름">
<PopInput />
</PopFormField>
// 나쁨: 모드별로 다른 컴포넌트
{isMobile ? <MobileInput /> : <TabletInput />}
```
### 4. 데이터와 UI 분리
```typescript
// 좋음: 데이터 로직은 훅으로
const { data, loading, error } = useWorkOrders();
<PopDataTable data={data} loading={loading} />
// 나쁨: 컴포넌트 안에서 fetch
function PopDataTable() {
useEffect(() => {
fetch('/api/work-orders')...
}, []);
}
```
---
## 폴더 구조 제안
```
frontend/components/pop/
├── primitives/ # 1단계: 기초 블록
│ ├── PopButton.tsx
│ ├── PopInput.tsx
│ ├── PopLabel.tsx
│ ├── PopIcon.tsx
│ ├── PopBadge.tsx
│ ├── PopLoading.tsx
│ └── index.ts
├── compounds/ # 2단계: 조합 블록
│ ├── PopFormField.tsx
│ ├── PopCard.tsx
│ ├── PopListItem.tsx
│ ├── PopNumberPad.tsx
│ ├── PopStatusBox.tsx
│ └── index.ts
├── complex/ # 3단계: 복합 컴포넌트
│ ├── PopDataTable/
│ │ ├── PopDataTable.tsx
│ │ ├── PopTableHeader.tsx
│ │ ├── PopTableRow.tsx
│ │ └── index.ts
│ ├── PopCardList/
│ ├── PopBarcodeScanner/
│ └── index.ts
├── hooks/ # 공용 훅
│ ├── usePopTheme.ts
│ ├── useResponsiveSize.ts
│ └── useTouchFeedback.ts
└── styles/ # 공용 스타일
├── pop-variables.css
└── pop-base.css
```
---
## 스타일 변수
```css
/* pop-variables.css */
:root {
/* 터치 크기 */
--pop-touch-min: 48px;
--pop-touch-industrial: 60px;
/* 폰트 크기 */
--pop-font-body: clamp(14px, 1.5vw, 18px);
--pop-font-heading: clamp(18px, 2.5vw, 28px);
--pop-font-caption: clamp(12px, 1vw, 14px);
/* 간격 */
--pop-gap-sm: 8px;
--pop-gap-md: 16px;
--pop-gap-lg: 24px;
/* 색상 */
--pop-primary: #2563eb;
--pop-success: #16a34a;
--pop-warning: #f59e0b;
--pop-danger: #dc2626;
/* 고대비 (야외용) */
--pop-high-contrast-bg: #000000;
--pop-high-contrast-fg: #ffffff;
}
```
---
## 다음 단계
1. **기초 블록부터 시작**: PopButton, PopInput 먼저 만들기
2. **스토리북 설정**: 컴포넌트별 문서화
3. **테스트**: 터치 크기, 반응형 확인
4. **디자이너 연동**: v4 레이아웃 시스템과 통합
---
*최종 업데이트: 2026-02-03*