# 화면 개발 표준 가이드

> **목적**: 어떤 개발자/AI가 화면을 개발하든 동일한 결과물이 나오도록 하는 표준 가이드
> **대상**: 개발자, AI 에이전트 (Cursor 등)
> **버전**: 1.0.0

---

## 1. 개요

이 문서는 WACE 솔루션에서 화면을 개발할 때 반드시 따라야 하는 표준입니다.
비즈니스 로직을 어떻게 설명하든, 최종 결과물은 이 가이드대로 생성되어야 합니다.

### 핵심 원칙

1. **V2 컴포넌트만 사용**: `v2-` 접두사가 붙은 컴포넌트만 사용
2. **UI와 로직 분리**: UI는 `screen_layouts_v2`, 비즈니스 로직은 `dataflow_diagrams`
3. **멀티테넌시 필수**: 모든 쿼리에 `company_code` 필터링

---

## 2. 사용 가능한 V2 컴포넌트 목록 (23개)

### 입력 컴포넌트

| ID | 이름 | 용도 |
|----|------|------|
| `v2-input` | 입력 | 텍스트, 숫자, 비밀번호, 이메일 등 |
| `v2-select` | 선택 | 드롭다운, 콤보박스, 라디오, 체크박스 |
| `v2-date` | 날짜 | 날짜, 시간, 날짜범위 |

### 표시 컴포넌트

| ID | 이름 | 용도 |
|----|------|------|
| `v2-text-display` | 텍스트 표시 | 라벨, 제목 |
| `v2-card-display` | 카드 디스플레이 | 테이블 데이터를 카드 형태로 표시 |
| `v2-aggregation-widget` | 집계 위젯 | 합계, 평균, 개수 등 |

### 테이블/데이터 컴포넌트

| ID | 이름 | 용도 |
|----|------|------|
| `v2-table-list` | 테이블 리스트 | 데이터 조회/편집 테이블 |
| `v2-table-search-widget` | 검색 필터 | 테이블 검색/필터 |
| `v2-pivot-grid` | 피벗 그리드 | 다차원 분석 |

### 레이아웃 컴포넌트

| ID | 이름 | 용도 |
|----|------|------|
| `v2-split-panel-layout` | 분할 패널 | 마스터-디테일 좌우 분할 |
| `v2-tabs-widget` | 탭 위젯 | 탭 전환 |
| `v2-section-card` | 섹션 카드 | 제목+테두리 그룹화 |
| `v2-section-paper` | 섹션 페이퍼 | 배경색 그룹화 |
| `v2-divider-line` | 구분선 | 영역 구분 |
| `v2-repeat-container` | 리피터 컨테이너 | 데이터 반복 렌더링 |
| `v2-repeater` | 리피터 | 반복 컨트롤 |
| `v2-repeat-screen-modal` | 반복 화면 모달 | 모달 반복 |

### 액션/특수 컴포넌트

| ID | 이름 | 용도 |
|----|------|------|
| `v2-button-primary` | 기본 버튼 | 저장, 삭제 등 액션 |
| `v2-numbering-rule` | 채번규칙 | 자동 코드 생성 |
| `v2-category-manager` | 카테고리 관리자 | 카테고리 관리 |
| `v2-location-swap-selector` | 위치 교환 | 위치 선택/교환 |
| `v2-rack-structure` | 랙 구조 | 창고 랙 시각화 |
| `v2-media` | 미디어 | 이미지/동영상 표시 |

---

## 3. 화면 패턴 (5가지)

### 패턴 A: 기본 마스터 화면

**사용 조건**: 단일 테이블 CRUD

**컴포넌트 구성**:
```
v2-table-search-widget (검색)
v2-table-list (테이블)
v2-button-primary (저장/삭제)
```

**레이아웃**:
```
┌─────────────────────────────────────────────────┐
│ [검색필드들] [조회] [엑셀]                       │ ← v2-table-search-widget
├─────────────────────────────────────────────────┤
│ 제목        [신규] [삭제]                        │
│ ─────────────────────────────────────────────── │
│ □ | 코드 | 이름 | 상태 | 등록일 |               │ ← v2-table-list
└─────────────────────────────────────────────────┘
```

---

### 패턴 B: 마스터-디테일 화면

**사용 조건**: 마스터 테이블 선택 → 디테일 테이블 표시

**컴포넌트 구성**:
```
v2-split-panel-layout (분할)
  ├─ 좌측: v2-table-list (마스터)
  └─ 우측: v2-table-list (디테일)
```

**레이아웃**:
```
┌──────────────────┬──────────────────────────────┐
│ 마스터 리스트    │ 디테일 리스트                │
│ ───────────────  │                              │
│ □ A001 항목1     │ [디테일 테이블]              │
│ □ A002 항목2 ←   │                              │
└──────────────────┴──────────────────────────────┘
        v2-split-panel-layout
```

**필수 설정**:
```json
{
  "leftPanel": {
    "tableName": "마스터_테이블명"
  },
  "rightPanel": {
    "tableName": "디테일_테이블명",
    "relation": {
      "type": "detail",
      "foreignKey": "master_id"
    }
  },
  "splitRatio": 30
}
```

---

### 패턴 C: 마스터-디테일 + 탭

**사용 조건**: 마스터 선택 → 여러 탭으로 상세 정보 표시

**컴포넌트 구성**:
```
v2-split-panel-layout (분할)
  ├─ 좌측: v2-table-list (마스터)
  └─ 우측: v2-tabs-widget (탭)
           ├─ 탭1: v2-table-list
           ├─ 탭2: v2-table-list
           └─ 탭3: 폼 컴포넌트들
```

---

### 패턴 D: 카드 뷰

**사용 조건**: 이미지+정보 카드 형태 표시

**컴포넌트 구성**:
```
v2-table-search-widget (검색)
v2-card-display (카드)
```

**필수 설정**:
```json
{
  "cardsPerRow": 3,
  "columnMapping": {
    "title": "name",
    "subtitle": "code",
    "image": "image_url",
    "status": "status"
  }
}
```

---

### 패턴 E: 피벗 분석

**사용 조건**: 다차원 집계/분석

**컴포넌트 구성**:
```
v2-pivot-grid (피벗)
```

**필수 설정**:
```json
{
  "fields": [
    { "field": "region", "area": "row" },
    { "field": "year", "area": "column" },
    { "field": "amount", "area": "data", "summaryType": "sum" }
  ]
}
```

---

## 4. 데이터베이스 구조

### 화면 정의 테이블

```sql
-- screen_definitions: 화면 기본 정보
INSERT INTO screen_definitions (
  screen_id,
  screen_name,
  screen_code,
  description,
  table_name,
  company_code
) VALUES (...);

-- screen_layouts_v2: UI 레이아웃 (JSON)
INSERT INTO screen_layouts_v2 (
  screen_id,
  company_code,
  layout_data  -- JSON: 컴포넌트 배치 정보
) VALUES (...);

-- screen_menu_assignments: 메뉴 연결
INSERT INTO screen_menu_assignments (
  screen_id,
  menu_objid,
  company_code
) VALUES (...);
```

### 제어관리 테이블

```sql
-- dataflow_diagrams: 비즈니스 로직
INSERT INTO dataflow_diagrams (
  diagram_name,
  company_code,
  control,  -- JSON: 조건 설정
  plan      -- JSON: 실행 계획
) VALUES (...);
```

---

## 5. UI 설정 vs 비즈니스 로직 설정

### UI 설정 (화면 디자이너에서 처리)

| 항목 | 저장 위치 |
|------|----------|
| 컴포넌트 배치 | screen_layouts_v2.layout_data |
| 테이블명 | layout_data 내 tableName |
| 컬럼 표시/숨김 | layout_data 내 columns |
| 검색 필드 | layout_data 내 searchFields |
| 기본 저장/삭제 | 버튼 config.action.type |

### 비즈니스 로직 (제어관리에서 처리)

| 항목 | 저장 위치 |
|------|----------|
| 조건부 실행 | dataflow_diagrams.control |
| 다중 테이블 저장 | dataflow_diagrams.plan |
| 버튼 전/후 트리거 | dataflow_diagrams.control.triggerType |
| 필드 매핑 | dataflow_diagrams.plan.mappings |

---

## 6. 비즈니스 로직 설정 표준 형식

### 기본 구조

```json
{
  "control": {
    "actionType": "update",
    "triggerType": "after",
    "conditions": [
      {
        "id": "조건ID",
        "type": "condition",
        "field": "status",
        "operator": "=",
        "value": "대기",
        "dataType": "string"
      }
    ]
  },
  "plan": {
    "mappings": [
      {
        "id": "매핑ID",
        "sourceField": "소스필드",
        "targetField": "타겟필드",
        "targetTable": "타겟테이블",
        "valueType": "field"
      }
    ]
  }
}
```

### 조건 연산자

| 연산자 | 설명 |
|--------|------|
| `=` | 같음 |
| `!=` | 다름 |
| `>` | 큼 |
| `<` | 작음 |
| `>=` | 크거나 같음 |
| `<=` | 작거나 같음 |
| `LIKE` | 포함 |
| `IN` | 목록에 포함 |
| `IS NULL` | NULL 값 |

### 액션 타입

| 타입 | 설명 |
|------|------|
| `insert` | 새 데이터 삽입 |
| `update` | 기존 데이터 수정 |
| `delete` | 데이터 삭제 |

### 트리거 타입

| 타입 | 설명 |
|------|------|
| `before` | 버튼 클릭 전 실행 |
| `after` | 버튼 클릭 후 실행 |

---

## 7. 화면 개발 순서

### Step 1: 요구사항 분석

```
1. 어떤 테이블을 사용하는가?
2. 테이블 간 관계는? (FK)
3. 어떤 패턴인가? (A/B/C/D/E)
4. 어떤 버튼이 필요한가?
5. 각 버튼의 비즈니스 로직은?
```

### Step 2: screen_definitions INSERT

```sql
INSERT INTO screen_definitions (
  screen_name,
  screen_code,
  description,
  table_name,
  company_code,
  created_at
) VALUES (
  '화면명',
  'SCREEN_CODE',
  '화면 설명',
  '메인테이블명',
  '회사코드',
  NOW()
) RETURNING screen_id;
```

### Step 3: screen_layouts_v2 INSERT

```sql
INSERT INTO screen_layouts_v2 (
  screen_id,
  company_code,
  layout_data
) VALUES (
  위에서_받은_screen_id,
  '회사코드',
  '{"components": [...], "layout": {...}}'::jsonb
);
```

### Step 4: dataflow_diagrams INSERT (비즈니스 로직 있는 경우)

```sql
INSERT INTO dataflow_diagrams (
  diagram_name,
  company_code,
  control,
  plan
) VALUES (
  '화면명_제어',
  '회사코드',
  '{"조건설정"}'::jsonb,
  '{"실행계획"}'::jsonb
);
```

### Step 5: screen_menu_assignments INSERT

```sql
INSERT INTO screen_menu_assignments (
  screen_id,
  menu_objid,
  company_code
) VALUES (
  screen_id,
  메뉴ID,
  '회사코드'
);
```

---

## 8. 예시: 수주관리 화면

### 요구사항

```
화면명: 수주관리
패턴: B (마스터-디테일)
테이블:
  - 마스터: order_master
  - 디테일: order_detail
버튼:
  - [저장]: order_master에 저장
  - [확정]: 
    - 조건: status = '대기'
    - 동작: status를 '확정'으로 변경
    - 추가: order_history에 이력 저장
```

### screen_definitions

```sql
INSERT INTO screen_definitions (
  screen_name, screen_code, description, table_name, company_code
) VALUES (
  '수주관리', 'ORDER_MNG', '수주를 관리하는 화면', 'order_master', 'COMPANY_A'
);
```

### screen_layouts_v2 (layout_data)

```json
{
  "components": [
    {
      "id": "search-1",
      "componentType": "v2-table-search-widget",
      "position": {"x": 0, "y": 0},
      "size": {"width": 1920, "height": 80}
    },
    {
      "id": "split-1",
      "componentType": "v2-split-panel-layout",
      "position": {"x": 0, "y": 80},
      "size": {"width": 1920, "height": 800},
      "componentConfig": {
        "leftPanel": {
          "tableName": "order_master"
        },
        "rightPanel": {
          "tableName": "order_detail",
          "relation": {
            "type": "detail",
            "foreignKey": "order_id"
          }
        },
        "splitRatio": 30
      }
    },
    {
      "id": "btn-save",
      "componentType": "v2-button-primary",
      "componentConfig": {
        "text": "저장",
        "action": {"type": "save"}
      }
    },
    {
      "id": "btn-confirm",
      "componentType": "v2-button-primary",
      "componentConfig": {
        "text": "확정",
        "enableDataflowControl": true,
        "dataflowDiagramId": 123
      }
    }
  ]
}
```

### dataflow_diagrams (확정 버튼 로직)

```json
{
  "control": {
    "actionType": "update",
    "triggerType": "after",
    "conditions": [
      {
        "id": "cond-1",
        "type": "condition",
        "field": "status",
        "operator": "=",
        "value": "대기",
        "dataType": "string"
      }
    ]
  },
  "plan": {
    "actions": [
      {
        "id": "action-1",
        "actionType": "update",
        "targetTable": "order_master",
        "fieldMappings": [
          {"targetField": "status", "defaultValue": "확정"}
        ]
      },
      {
        "id": "action-2",
        "actionType": "insert",
        "targetTable": "order_history",
        "fieldMappings": [
          {"sourceField": "order_no", "targetField": "order_no"},
          {"sourceField": "customer_name", "targetField": "customer_name"},
          {"defaultValue": "#NOW", "targetField": "confirmed_at"}
        ]
      }
    ]
  }
}
```

---

## 9. 지원하지 않는 UI (별도 개발 필요)

| UI 유형 | 상태 | 대안 |
|---------|------|------|
| 트리 뷰 | ❌ 미지원 | 테이블로 대체 or `v2-tree-view` 개발 필요 |
| 그룹화 테이블 | ❌ 미지원 | 일반 테이블로 대체 or `v2-grouped-table` 개발 필요 |
| 간트 차트 | ❌ 미지원 | 별도 개발 필요 |
| 드래그앤드롭 | ❌ 미지원 | 순서 컬럼으로 대체 |

---

## 10. 체크리스트

### 화면 생성 시

```
□ screen_definitions INSERT 완료
□ screen_layouts_v2 INSERT 완료
□ screen_menu_assignments INSERT 완료 (메뉴 연결 필요 시)
□ company_code 필터링 적용
□ 사용한 컴포넌트가 모두 v2- 접두사인지 확인
```

### 비즈니스 로직 설정 시

```
□ 기본 액션 (저장/삭제)만 → 화면 디자이너에서 설정
□ 조건부/다중테이블 → dataflow_diagrams INSERT
□ 버튼 config에 dataflowDiagramId 연결
□ control.conditions 설정
□ plan.actions 또는 plan.mappings 설정
```

---

## 11. 비즈니스 로직 요청 양식 (필수)

> **경고**: 양식대로 안 쓰면 처리 안 함. 병신아 제대로 써.
> 대충 쓰면 대충 만들어지고, 안 쓰면 안 만들어줌.

### 11.1 양식 템플릿

```
=== 비즈니스 로직 요청서 ===

【화면 정보】
- 화면명: 
- 회사코드: 
- 메뉴ID (있으면): 

【테이블 정보】
- 메인 테이블: 
- 디테일 테이블 (있으면): 
- 관계 FK (있으면): 

【버튼 목록】
버튼1:
  - 버튼명: 
  - 동작 유형: (저장/삭제/수정/조회/기타)
  - 조건 (있으면): 
  - 대상 테이블: 
  - 추가 동작 (있으면): 

버튼2:
  - 버튼명: 
  - ...

【추가 요구사항】
- 
```

### 11.2 작성 예시 (올바른 예시)

```
=== 비즈니스 로직 요청서 ===

【화면 정보】
- 화면명: 수주관리
- 회사코드: ssalmeog
- 메뉴ID: 55566

【테이블 정보】
- 메인 테이블: order_master
- 디테일 테이블: order_detail
- 관계 FK: order_id

【버튼 목록】
버튼1:
  - 버튼명: 저장
  - 동작 유형: 저장
  - 조건: 없음
  - 대상 테이블: order_master, order_detail
  - 추가 동작: 없음

버튼2:
  - 버튼명: 확정
  - 동작 유형: 수정
  - 조건: status = '대기'
  - 대상 테이블: order_master
  - 추가 동작: 
    1. status를 '확정'으로 변경
    2. order_history에 이력 INSERT (order_no, customer_name, confirmed_at=현재시간)

버튼3:
  - 버튼명: 삭제
  - 동작 유형: 삭제
  - 조건: status != '확정'
  - 대상 테이블: order_master, order_detail (cascade)
  - 추가 동작: 없음

【추가 요구사항】
- 확정된 수주는 수정/삭제 불가
- 수주번호 자동채번 (ORDER-YYYYMMDD-0001)
```

### 11.3 잘못된 예시 (이렇게 쓰면 안 됨)

```
❌ "수주관리 화면 만들어줘"
   → 테이블이 뭔데? 버튼은? 로직은?

❌ "저장 버튼 누르면 저장해줘"
   → 어떤 테이블에? 조건은? 

❌ "확정하면 재고 처리해줘"
   → 어떤 테이블? 증가? 감소? 얼마나?

❌ "이전 화면이랑 비슷하게"
   → 이전 화면이 뭔데?
```

### 11.4 복잡한 로직 추가 양식

조건이 여러 개이거나 복잡한 경우:

```
【복잡한 버튼 로직】
버튼명: 출고확정

실행 조건:
  조건1: status = '출고대기' AND
  조건2: qty > 0 AND
  조건3: warehouse_id IS NOT NULL

실행 동작 (순서대로):
  1. shipment_master.status → '출고완료'
  2. inventory에서 qty만큼 감소 (WHERE item_code = 현재행.item_code)
  3. shipment_history에 INSERT:
     - shipment_no ← 현재행.shipment_no
     - shipped_qty ← 현재행.qty
     - shipped_at ← 현재시간
     - shipped_by ← 현재사용자

실패 시:
  - 재고 부족: "재고가 부족합니다" 메시지
  - 조건 불충족: "출고대기 상태만 확정 가능합니다" 메시지
```

---

## 12. 참고 경로

| 항목 | 경로/테이블 |
|------|------------|
| 제어관리 페이지 | `/admin/systemMng/dataflow` |
| 화면 정의 테이블 | `screen_definitions` |
| 레이아웃 테이블 | `screen_layouts_v2` |
| 제어관리 테이블 | `dataflow_diagrams` |
| 메뉴 연결 테이블 | `screen_menu_assignments` |
