# SAM MES 테이블 디자인 시스템

> **작성일**: 2025년 10월 24일  
> **버전**: 1.0.0

---

## 📋 목차

1. [개요](#개요)
2. [테이블 시스템 구조](#테이블-시스템-구조)
3. [셀 타입](#셀-타입)
4. [컴포넌트 가이드](#컴포넌트-가이드)
5. [사용 예시](#사용-예시)
6. [Best Practices](#best-practices)

---

## 개요

SAM MES의 모든 테이블은 통일된 디자인 시스템을 사용합니다. 컬럼과 데이터만 정의하면 자동으로 적절한 형태로 렌더링됩니다.

### 핵심 원칙

1. **일관성**: 모든 테이블이 동일한 디자인 패턴
2. **타입 안정성**: 셀 타입별 자동 렌더링
3. **재사용성**: 컬럼 정의만으로 테이블 완성
4. **반응형**: 데스크톱/모바일 자동 대응

---

## 테이블 시스템 구조

```
DataTable (Organism)
├── Column Definition (셀 타입 정의)
├── Cell Renderer (타입별 자동 렌더링)
│   ├── StatusBadge (Molecule)
│   ├── IconWithBadge (Molecule)
│   ├── TableActions (Molecule)
│   └── Badge (Atom)
└── Pagination (Optional)
```

---

## 셀 타입

### 지원하는 셀 타입

| 타입 | 설명 | 정렬 | 예시 |
|------|------|------|------|
| **text** | 일반 텍스트 | 좌측 | "홍길동" |
| **number** | 숫자 (자동 천 단위 구분) | 우측 | 1,234 |
| **currency** | 통화 (₩ 표시) | 우측 | ₩1,234,567 |
| **date** | 날짜 | 좌측 | 2025-10-24 |
| **datetime** | 날짜 + 시간 | 좌측 | 2025-10-24 14:30 |
| **status** | 상태 배지 | 중앙 | 🟢 활성 |
| **badge** | 일반 배지 | 중앙 | v1.0 |
| **icon** | 아이콘 | 중앙 | 📦 |
| **iconBadge** | 아이콘 + 배지 | 좌측 | 📦 완제품 |
| **actions** | 액션 버튼들 | 우측 | 👁️ ✏️ 🗑️ |
| **custom** | 커스텀 렌더링 | 설정 가능 | (사용자 정의) |

---

## 컴포넌트 가이드

### 1. DataTable (Organism)

통일된 테이블 컴포넌트

**위치**: `/components/organisms/DataTable.tsx`

**Props**:
```typescript
interface DataTableProps<T> {
  columns: Column<T>[];      // 컬럼 정의
  data: T[];                 // 데이터
  keyField: keyof T;         // 고유 키 필드
  onRowClick?: (row: T) => void;  // 행 클릭 핸들러
  loading?: boolean;         // 로딩 상태
  emptyMessage?: string;     // 빈 메시지
  pagination?: {             // 페이지네이션
    currentPage: number;
    totalPages: number;
    onPageChange: (page: number) => void;
  };
  striped?: boolean;         // 줄무늬 (기본: false)
  hoverable?: boolean;       // 호버 효과 (기본: true)
  compact?: boolean;         // 컴팩트 모드 (기본: false)
}
```

**Column 정의**:
```typescript
interface Column<T> {
  key: keyof T | string;     // 데이터 키
  label: string;             // 컬럼 헤더
  type?: CellType;           // 셀 타입
  width?: string;            // 너비
  align?: "left" | "center" | "right";  // 정렬
  
  // 타입별 설정
  statusConfig?: { showDot?: boolean };
  badgeConfig?: { variant?: string; className?: string };
  iconConfig?: { iconColor?: string; iconBgColor?: string; size?: "sm" | "md" | "lg" };
  currencyConfig?: { locale?: string; currency?: string };
  
  // 커스텀
  render?: (value: any, row: T) => ReactNode;
  format?: (value: any) => string | number;
}
```

---

### 2. StatusBadge (Molecule)

상태 표시 배지

**위치**: `/components/molecules/StatusBadge.tsx`

**지원 상태**:
```typescript
// 프로세스 상태
"대기" | "진행중" | "완료" | "취소" | "반려"

// 문서 상태
"작성중" | "검토중" | "승인" | "보류"

// 품질 상태
"합격" | "부적합" | "조건부합격" | "검사중"

// 설비 상태
"정상" | "고장" | "점검중"

// 활성화 상태
"활성" | "비활성" | "사용" | "미사용" | "폐기"

// 생산 상태
"생산중" | "배송중" | "생산대기"

// 재고 상태
"입고" | "출고" | "재고부족"
```

**사용법**:
```typescript
<StatusBadge status="활성" />
<StatusBadge status="진행중" showDot />
```

---

### 3. IconWithBadge (Molecule)

아이콘 + 라벨 + 배지 조합

**위치**: `/components/molecules/IconWithBadge.tsx`

**사용법**:
```typescript
<IconWithBadge
  icon={Package}
  label="완제품"
  iconColor="text-blue-600"
  iconBgColor="bg-blue-100"
  badge={{ label: "신규", variant: "default" }}
  size="md"
/>
```

---

### 4. TableActions (Molecule)

테이블 액션 버튼 그룹

**위치**: `/components/molecules/TableActions.tsx`

**지원 액션 타입**:
- `view` - 상세보기 (👁️)
- `edit` - 수정 (✏️)
- `delete` - 삭제 (🗑️)
- `copy` - 복사 (📋)
- `download` - 다운로드 (⬇️)
- `custom` - 커스텀

**레이아웃**:
- `buttons` - 버튼으로 표시
- `dropdown` - 드롭다운 메뉴
- `auto` - 자동 (3개 이하: 버튼, 4개 이상: 드롭다운)

**사용법**:
```typescript
<TableActions
  actions={[
    { type: "view", onClick: handleView },
    { type: "edit", onClick: handleEdit },
    { type: "delete", onClick: handleDelete, variant: "destructive" }
  ]}
  layout="auto"
/>
```

---

## 사용 예시

### 예시 1: 기본 테이블

```typescript
import { DataTable, Column } from "./organisms/DataTable";

interface Product {
  id: string;
  code: string;
  name: string;
  price: number;
  status: string;
  updatedAt: string;
}

function ProductList() {
  const columns: Column<Product>[] = [
    { key: "code", label: "제품코드", type: "text" },
    { key: "name", label: "제품명", type: "text" },
    { key: "price", label: "가격", type: "currency" },
    { key: "status", label: "상태", type: "status" },
    { key: "updatedAt", label: "수정일", type: "date" }
  ];

  return (
    <DataTable
      columns={columns}
      data={products}
      keyField="id"
    />
  );
}
```

### 예시 2: 액션 버튼이 있는 테이블

```typescript
const columns: Column<Product>[] = [
  { key: "code", label: "제품코드", type: "text" },
  { key: "name", label: "제품명", type: "text" },
  { key: "price", label: "가격", type: "currency" },
  { key: "status", label: "상태", type: "status" },
  {
    key: "id",
    label: "관리",
    type: "actions",
    render: (_, row) => [
      { type: "view", onClick: () => handleView(row) },
      { type: "edit", onClick: () => handleEdit(row) },
      { type: "delete", onClick: () => handleDelete(row), variant: "destructive" }
    ]
  }
];
```

### 예시 3: 아이콘 + 배지

```typescript
const columns: Column<Item>[] = [
  {
    key: "type",
    label: "품목유형",
    type: "iconBadge",
    render: (value) => ({
      icon: getItemIcon(value),
      label: getItemLabel(value),
      badge: { label: "신규", variant: "default" }
    })
  }
];
```

### 예시 4: 커스텀 렌더링

```typescript
const columns: Column<Order>[] = [
  {
    key: "customer",
    label: "고객사",
    type: "custom",
    render: (value, row) => (
      <div>
        <p className="font-medium">{value}</p>
        <p className="text-xs text-muted-foreground">{row.customerCode}</p>
      </div>
    )
  }
];
```

### 예시 5: 페이지네이션

```typescript
const { currentPage, totalPages, paginatedData, goToPage } = usePagination(data, 10);

<DataTable
  columns={columns}
  data={paginatedData}
  keyField="id"
  pagination={{
    currentPage,
    totalPages,
    onPageChange: goToPage
  }}
/>
```

### 예시 6: 다양한 옵션

```typescript
<DataTable
  columns={columns}
  data={data}
  keyField="id"
  striped              // 줄무늬
  compact              // 컴팩트 모드
  hoverable={false}    // 호버 효과 비활성화
  loading={isLoading}  // 로딩 상태
  emptyMessage="검색 결과가 없습니다."
  onRowClick={handleRowClick}  // 행 클릭
/>
```

---

## Best Practices

### 1. 올바른 타입 선택

```typescript
// ✅ 좋은 예
{ key: "price", label: "가격", type: "currency" }
{ key: "quantity", label: "수량", type: "number" }
{ key: "status", label: "상태", type: "status" }
{ key: "createdAt", label: "생성일", type: "date" }

// ❌ 나쁜 예
{ key: "price", label: "가격", type: "text" }  // 통화 형식 미적용
{ key: "status", label: "상태", type: "text" }  // 배지 미적용
```

### 2. 액션 버튼 정리

```typescript
// ✅ 좋은 예 - 타입 시스템 활용
{
  key: "id",
  label: "관리",
  type: "actions",
  render: (_, row) => [
    { type: "view", onClick: () => handleView(row) },
    { type: "edit", onClick: () => handleEdit(row) },
    { type: "delete", onClick: () => handleDelete(row), variant: "destructive" }
  ]
}

// ❌ 나쁜 예 - 직접 구현
{
  key: "id",
  label: "관리",
  render: (_, row) => (
    <div className="flex gap-2">
      <Button onClick={() => handleView(row)}>보기</Button>
      <Button onClick={() => handleEdit(row)}>수정</Button>
      <Button onClick={() => handleDelete(row)}>삭제</Button>
    </div>
  )
}
```

### 3. 상태 통일

```typescript
// ✅ 좋은 예 - StatusBadge 활용
{ key: "status", label: "상태", type: "status" }

// ❌ 나쁜 예 - 직접 구현
{
  key: "status",
  render: (value) => (
    <Badge className={value === "활성" ? "bg-green-100" : "bg-gray-100"}>
      {value}
    </Badge>
  )
}
```

### 4. 정렬 기본값

타입별 자동 정렬을 활용하세요:
- **text**: 좌측 정렬
- **number**, **currency**, **actions**: 우측 정렬
- **status**, **badge**, **icon**: 중앙 정렬

```typescript
// ✅ 자동 정렬 활용
{ key: "price", label: "가격", type: "currency" }  // 자동 우측 정렬

// ⚠️ 필요시에만 명시
{ key: "price", label: "가격", type: "currency", align: "left" }  // 수동 좌측 정렬
```

### 5. 반응형 대응

데스크톱과 모바일을 함께 고려하세요:

```typescript
// 데스크톱: DataTable
<DataTable
  columns={columns}
  data={data}
  keyField="id"
/>

// 모바일: MobileCard
<div className="md:hidden space-y-3">
  {data.map((item) => (
    <MobileCard
      key={item.id}
      title={item.name}
      subtitle={item.code}
      fields={[...]}
    />
  ))}
</div>
```

---

## 마이그레이션 가이드

### 기존 테이블 → 새 테이블 시스템

**Before**:
```typescript
<Table>
  <TableHeader>
    <TableRow>
      <TableHead>제품코드</TableHead>
      <TableHead>제품명</TableHead>
      <TableHead>가격</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    {data.map((row) => (
      <TableRow key={row.id}>
        <TableCell>{row.code}</TableCell>
        <TableCell>{row.name}</TableCell>
        <TableCell>₩{row.price.toLocaleString()}</TableCell>
      </TableRow>
    ))}
  </TableBody>
</Table>
```

**After**:
```typescript
const columns: Column<Product>[] = [
  { key: "code", label: "제품코드", type: "text" },
  { key: "name", label: "제품명", type: "text" },
  { key: "price", label: "가격", type: "currency" }
];

<DataTable columns={columns} data={data} keyField="id" />
```

**효과**:
- 코드 라인 수: 20+ 라인 → 5 라인 (75% 감소)
- 일관성: 자동으로 통일된 디자인 적용
- 유지보수: 컬럼 정의만 수정

---

## 컴포넌트 계층 구조

```
Atoms (UI 기본 컴포넌트)
├── Badge
├── Button
└── Table Components

Molecules (작은 조합)
├── StatusBadge          ⭐ 상태 배지
├── IconWithBadge        ⭐ 아이콘 + 배지
└── TableActions         ⭐ 액션 버튼 그룹

Organisms (복잡한 조합)
└── DataTable            ⭐ 통합 테이블

Templates (페이지 레이아웃)
└── ListPageTemplate     ⭐ 목록 페이지 (DataTable 포함)
```

---

## 적용 대상 페이지

### 즉시 적용 가능 (40개 이상)

**관리 페이지**:
- CustomerManagement
- SupplierManagement
- OrderManagement
- PurchaseOrderManagement
- ItemManagement
- EquipmentManagement
- VehicleManagement
- EmployeeManagement
- DepartmentManagement

**재고 관리**:
- InventoryManagement
- ReceivingManagement
- ShippingManagement
- StockStatus

**생산 관리**:
- ProductionManagement
- WorkOrderManagement
- ProcessManagement

**품질 관리**:
- IncomingInspectionManagement
- ProcessInspectionManagement
- FinalInspectionManagement
- NonconformingManagement

**회계/영업**:
- SalesAccountingManagement
- PurchaseAccountingManagement
- QuoteManagement
- PricingManagement

---

## FAQ

### Q1. 커스텀 렌더링과 타입 시스템 중 어떤 것을 사용해야 하나요?

**A**: 가능하면 타입 시스템을 우선 사용하세요. 커스텀 렌더링은 정말 특수한 경우에만 사용합니다.

```typescript
// ✅ 타입 시스템 활용 (권장)
{ key: "status", label: "상태", type: "status" }

// ⚠️ 커스텀 렌더링 (특수한 경우만)
{
  key: "complex",
  render: (value, row) => (
    <div>
      <p>{value}</p>
      <p className="text-xs">{row.detail}</p>
    </div>
  )
}
```

### Q2. 액션 버튼이 4개 이상일 때 어떻게 표시되나요?

**A**: 자동으로 드롭다운 메뉴로 변환됩니다.

```typescript
// 3개 이하: 버튼으로 표시
// 4개 이상: 자동으로 드롭다운 메뉴로 변환
layout="auto"  // 기본값
```

### Q3. 테이블 행을 클릭 가능하게 만들려면?

**A**: `onRowClick` prop을 사용하세요.

```typescript
<DataTable
  columns={columns}
  data={data}
  keyField="id"
  onRowClick={(row) => navigate(`/detail/${row.id}`)}
/>
```

### Q4. 로딩 상태는 어떻게 표시하나요?

**A**: `loading` prop을 사용하세요.

```typescript
<DataTable
  columns={columns}
  data={data}
  keyField="id"
  loading={isLoading}
/>
```

---

## 변경 이력

| 버전 | 날짜 | 변경 내용 |
|------|------|-----------|
| 1.0.0 | 2025-10-24 | 초기 버전 생성 |

---

**문서 버전**: 1.0.0  
**최종 업데이트**: 2025년 10월 24일  
**작성자**: SAM MES 개발팀
