ERP-node/docs/screen-designer-upgrade-pla...

37 KiB
Raw Blame History

화면 디자이너 V2 - 재설계 계획서

작성일: 2026-02-27
방향: 기존 기능 형태는 인정하되, 새로운 방식으로 재설립
핵심 철학: "컴포넌트를 계속 추가하는 시스템"에서 "소수의 강력한 컴포넌트로 유연하게 조합하는 시스템"으로


1. 현재 시스템의 근본적 문제

1.1 "컴포넌트 폭증" 문제

현재 등록된 컴포넌트 수: 70개 이상

기본 입력 13종  +  V2 입력 4종  +  V2 데이터 5종
기존 레이아웃 8종  +  V2 레이아웃 16종  +  특수 10종+
ConfigPanel 26개  +  Renderer 21개  +  위젯 10종+

문제: 새 기능이 필요할 때마다 아래 작업을 반복해야 함

새 기능 요청 → ComponentDefinition 작성
           → Renderer 작성
           → ConfigPanel 작성
           → index.ts에 import 추가
           → 테스트
           → 약 5~8개 파일, 500~1500줄 추가

거래처별 품목정보? → customer-item-mapping 컴포넌트 추가
BOM 트리? → v2-bom-tree + v2-bom-item-editor 추가
세금계산서? → tax-invoice-list 추가
타임라인? → v2-timeline-scheduler 추가

매번 개발자가 코드를 작성해야만 새 기능이 가능하다.

1.2 설정 패널의 사용성 문제

ConfigPanel이 26개이고, 각각 UI 구조/용어/설정 방식이 다름:

패널 설정 항목 사용자 관점
TextConfigPanel inputType, placeholder, maxLength... "이게 뭐지?"
EntityConfigPanel joinTable, joinColumn, displayColumn... "조인? 컬럼?"
SelectConfigPanel optionSource, staticOptions, dynamicApi... "동적 API?"
FlowWidgetConfigPanel flowDefinitionId, stepMapping... "스텝 매핑?"
ButtonConfigPanel actionType, dataFlow, targetScreen... "데이터 플로우?"

사용자(현업 관리자)가 이 설정들을 이해하고 사용하기가 극히 어려움.

1.3 컴포넌트 간 연결의 제한성

현재 컴포넌트들은 대부분 독립적으로 동작:

  • 거래처를 선택하면 → 납품처가 자동으로 바뀌어야 하는데 → 별도 코드 필요
  • 마스터 테이블에서 행을 선택하면 → 디테일 테이블이 자동 필터링 → SplitPanel로 하드코딩
  • 버튼 클릭하면 → 특정 필드 값에 따라 다른 동작 → FlowWidget으로만 가능

컴포넌트 간 동적 상호작용을 사용자가 설정할 방법이 없음.

1.4 V1/V2/기존/신규 혼재

// 같은 테이블 컴포넌트가 3종류
import "./table-list/TableListRenderer";        // 기존
import "./v2-table-list/TableListRenderer";      // V2
import "./v2-table-grouped/TableGroupedRenderer"; // V2 그룹화

동일 기능의 컴포넌트가 "기존 호환"이라는 이유로 중복 존재.
어떤 걸 써야 하는지 사용자도 개발자도 혼란.


2. 새로운 비전

2.1 핵심 원칙

❌ 기존: "기능 = 컴포넌트"     → 기능이 늘어나면 컴포넌트가 늘어남
✅ 새롭게: "기능 = 설정"       → 소수의 메타 컴포넌트 + 풍부한 설정으로 무한 확장
❌ 기존: "개발자가 만들어주는 화면"  → 요청 → 개발 → 배포 → 1~3일
✅ 새롭게: "사용자가 조립하는 화면"  → 드래그 → 설정 → 바로 사용 → 5분

2.2 메타 컴포넌트 체계

70개 이상의 컴포넌트를 7개의 메타 컴포넌트로 통합:

메타 컴포넌트 대체 범위 핵심 능력
Field text, number, date, select, entity, checkbox, radio, file, textarea, code, numbering 테이블 컬럼의 webType에 따라 자동 변환
DataView table-list, repeater, card-display, pivot-grid, bom-tree, aggregation, timeline 같은 데이터를 테이블/카드/트리/피벗/타임라인 등 뷰 모드 전환
Action button-primary, flow-widget, related-data-buttons 클릭 시 저장/삭제/조회/이동/모달/API 호출 등 설정
Layout split-panel, tabs, section-card, section-paper, conditional-container, accordion 영역 분할, 탭, 섹션, 조건부 표시
Display text-display, divider, badge, alert, stats-card, chart, image, progress 읽기 전용 정보 표시
Search table-search, advanced-filters, autocomplete 데이터 필터링/검색
Modal universal-form-modal, repeat-screen-modal 데이터 입력/편집 팝업

2.3 "테이블 드롭 → 화면 완성" 흐름

현재 (약 15분):

1. 테이블 컬럼을 하나씩 드래그
2. 각 컬럼마다 컴포넌트 타입 확인
3. entity 컬럼이면 → EntityConfigPanel에서 조인 테이블, 조인 컬럼 수동 설정
4. select 컬럼이면 → SelectConfigPanel에서 옵션 소스 수동 설정
5. 버튼 컴포넌트 별도 추가
6. 데이터 테이블 별도 추가
7. 각각 설정...

새로운 방식 (약 2분):

1. 테이블을 통째로 드롭
2. 시스템이 자동으로:
   - 컬럼 타입(webType) 분석 → Field 컴포넌트 자동 생성
   - entity 컬럼 → 조인 정보 자동 감지 (FK 관계)
   - select 컬럼 → 코드 테이블 자동 연결
   - CRUD 버튼 자동 생성 (Action 컴포넌트)
   - DataView(테이블 뷰) 자동 생성
3. 사용자는 세부 설정만 조정

3. 메타 컴포넌트 상세 설계

3.1 Field (통합 입력 컴포넌트)

대체 대상: text-input, number-input, date-input, select-basic, checkbox-basic, radio-basic, entity-search-input, file-upload, textarea, code-input, numbering-rule, v2-input, v2-select, v2-date, v2-file-upload, autocomplete-search-input, toggle-switch, slider

핵심 개념: 하나의 Field 컴포넌트가 webType에 따라 모양과 동작이 바뀜

interface FieldConfig {
  // 자동 결정 (테이블 컬럼 기반)
  webType: "text" | "number" | "date" | "datetime" | "select" | "entity" 
         | "checkbox" | "radio" | "file" | "textarea" | "code" | "numbering"
         | "email" | "tel" | "url" | "password" | "color" | "toggle" | "slider";
  
  // 데이터 바인딩 (자동)
  tableName: string;
  columnName: string;
  
  // 조인 정보 (entity 타입일 때 자동 감지)
  join?: {
    targetTable: string;      // FK가 참조하는 테이블
    targetColumn: string;     // PK 컬럼
    displayColumn: string;    // 표시할 컬럼 (자동: name 또는 첫 번째 text 컬럼)
    additionalColumns?: string[]; // 추가 표시 컬럼
    searchable?: boolean;     // 검색 가능 여부
    filterBy?: Record<string, string>; // 다른 Field 값으로 필터링
  };
  
  // select 옵션 (자동 감지)
  options?: {
    source: "code_table" | "static" | "api";
    codeCategory?: string;    // code_table일 때
    staticList?: { value: string; label: string }[];
    apiEndpoint?: string;
  };
  
  // 공통 설정
  label?: string;
  placeholder?: string;
  required?: boolean;
  readonly?: boolean;
  disabled?: boolean;
  defaultValue?: any;
  
  // 검증
  validation?: {
    min?: number;
    max?: number;
    minLength?: number;
    maxLength?: number;
    pattern?: string;
    customMessage?: string;
  };
  
  // 연동 (다른 Field와의 관계)
  linkedTo?: {
    fieldId: string;          // 연결된 Field의 ID
    relationship: "filter" | "copy" | "calculate" | "show_hide";
    expression?: string;      // 계산식 또는 조건식
  }[];
  
  // 레이아웃
  display?: {
    width?: string;           // "full" | "half" | "third" | "quarter" | 커스텀
    labelPosition?: "top" | "left" | "hidden";
    helpText?: string;
  };
}

사용자 설정 UI (새로운 방식):

┌─────────────────────────────────────┐
│ Field 설정                          │
├─────────────────────────────────────┤
│ 표시 형태: [텍스트 ▼]              │  ← 드롭다운 하나로 webType 전환
│                                     │
│ 라벨: [수주번호         ]          │
│ 필수: [✓]  읽기전용: [ ]           │
│                                     │
│ ─── 데이터 연결 ────               │
│ 테이블: sales_order_mng (자동)      │
│ 컬럼: order_no (자동)               │
│                                     │
│ ─── 연동 설정 ────                 │
│ + 다른 필드와 연결 추가             │
│  [거래처] 변경 시 → [납품처] 필터링 │
│  [수량] × [단가] → [금액] 자동계산  │
│                                     │
│ ─── 표시 ────                      │
│ 너비: [절반 ▼]                     │
│ 도움말: [주문 번호를 입력하세요]    │
└─────────────────────────────────────┘

핵심 차이점:

  • 기존: 컴포넌트 타입 선택 → 타입별 ConfigPanel → 복잡한 설정
  • 새로운: Field 하나 놓으면 → webType 자동 감지 → 간단한 통합 설정

3.2 DataView (통합 데이터 뷰)

대체 대상: table-list, v2-table-list, v2-repeater, card-display, v2-card-display, pivot-grid, v2-pivot-grid, bom-tree, aggregation-widget, v2-aggregation-widget, v2-table-grouped, v2-timeline-scheduler, simple-repeater-table, modal-repeater-table

핵심 개념: 하나의 데이터 소스를 여러 뷰 모드로 전환

interface DataViewConfig {
  // 데이터 소스
  dataSource: {
    tableName: string;
    columns: ColumnConfig[];     // 표시할 컬럼 목록
    defaultSort?: { column: string; direction: "asc" | "desc" };
    defaultFilter?: FilterConfig[];
    pageSize?: number;
    
    // 마스터-디테일 자동 연결
    masterField?: string;        // 상위 DataView의 어떤 컬럼과 연결
    detailForeignKey?: string;   // 하위 테이블의 FK 컬럼
  };
  
  // 뷰 모드 (사용자가 런타임에 전환 가능)
  viewMode: "table" | "card" | "list" | "tree" | "pivot" | "timeline" | "kanban" | "calendar";
  allowedViewModes?: string[];   // 허용된 뷰 모드 목록
  
  // 테이블 뷰 설정
  tableConfig?: {
    showRowNumber?: boolean;
    showCheckbox?: boolean;
    stickyHeader?: boolean;
    groupBy?: string[];          // 그룹화 컬럼
    summaryColumns?: string[];   // 합계 표시 컬럼
    editableColumns?: string[];  // 인라인 편집 가능 컬럼
    frozenColumns?: number;      // 고정 컬럼 수
  };
  
  // 카드 뷰 설정
  cardConfig?: {
    titleColumn: string;
    descriptionColumn?: string;
    imageColumn?: string;
    columnsPerRow?: 2 | 3 | 4;
    cardStyle?: "compact" | "standard" | "detailed";
  };
  
  // 트리 뷰 설정
  treeConfig?: {
    parentColumn: string;
    childColumn: string;
    labelColumn: string;
    expandLevel?: number;
  };
  
  // 피벗 설정
  pivotConfig?: {
    rowFields: string[];
    columnFields: string[];
    valueFields: { column: string; aggregation: "sum" | "count" | "avg" | "min" | "max" }[];
  };
  
  // CRUD 동작 (Action 컴포넌트와 자동 연결)
  actions?: {
    create?: boolean;
    read?: boolean;
    update?: boolean;
    delete?: boolean;
    export?: boolean;
    import?: boolean;
  };
  
  // 검색/필터 (Search 컴포넌트와 자동 연결)
  searchable?: boolean;
  filterColumns?: string[];
}

사용자 설정 UI:

┌─────────────────────────────────────┐
│ DataView 설정                       │
├─────────────────────────────────────┤
│ 테이블: [sales_order_mng ▼]        │
│                                     │
│ 뷰 모드: [테이블] [카드] [트리]     │  ← 클릭 한 번으로 전환
│          ☑테이블 ☑카드 ☐트리       │  ← 허용 모드 체크
│                                     │
│ ─── 컬럼 선택 ────                 │
│  ☑ 수주번호    표시명: 수주번호     │
│  ☑ 거래처      표시명: 거래처       │
│  ☑ 수주수량    표시명: 수량    합계☑│
│  ☐ 생성일      (숨김)              │
│  [↕ 드래그로 순서 변경]            │
│                                     │
│ ─── 기능 ────                      │
│ ☑ 행 번호  ☑ 체크박스  ☑ 검색     │
│ ☑ 등록    ☑ 수정    ☑ 삭제        │
│ ☐ 엑셀 내보내기  ☐ 가져오기        │
│                                     │
│ ─── 연결 ────                      │
│ 마스터: [없음 ▼]                   │  ← 다른 DataView 선택 시
│ 연결 키: [customer_code ▼]         │     자동 마스터-디테일
└─────────────────────────────────────┘

3.3 Action (통합 액션 컴포넌트)

대체 대상: button-primary, v2-button-primary, flow-widget, related-data-buttons

핵심 개념: 하나의 Action 컴포넌트에 여러 동작을 설정으로 정의

interface ActionConfig {
  // 표시
  label: string;
  variant: "default" | "outline" | "destructive" | "ghost";
  icon?: string;
  position?: "toolbar" | "inline" | "floating" | "context-menu";
  
  // 동작 정의 (파이프라인 방식 - 순차 실행)
  steps: ActionStep[];
  
  // 실행 조건
  enableCondition?: {
    type: "always" | "selected" | "field_value" | "expression";
    fieldId?: string;
    operator?: "eq" | "ne" | "gt" | "lt" | "empty" | "not_empty";
    value?: any;
    expression?: string;
  };
  
  // 확인 대화상자
  confirmDialog?: {
    title: string;
    message: string;
    confirmText?: string;
    cancelText?: string;
    variant?: "default" | "destructive";
  };
}

type ActionStep =
  | { type: "save"; target: string }           // 데이터 저장
  | { type: "delete"; target: string }         // 데이터 삭제
  | { type: "refresh"; target: string }        // 데이터 새로고침
  | { type: "navigate"; screenId: number }     // 화면 이동
  | { type: "openModal"; modalId: string }     // 모달 열기
  | { type: "setField"; fieldId: string; value: any } // 필드 값 설정
  | { type: "api"; method: string; endpoint: string; body?: any } // API 호출
  | { type: "flowMove"; flowId: number; stepId: number } // 플로우 이동
  | { type: "export"; format: "excel" | "csv" | "pdf" }  // 내보내기
  | { type: "validate"; target: string }       // 유효성 검사
  | { type: "toast"; message: string; variant: "success" | "error" | "warning" }; // 알림

사용자 설정 UI:

┌─────────────────────────────────────┐
│ Action 설정                         │
├─────────────────────────────────────┤
│ 버튼명: [저장                    ]  │
│ 스타일: [기본●] [외곽] [위험] [고스트]│
│ 아이콘: [Save ▼]                   │
│                                     │
│ ─── 동작 순서 ────                 │
│  1. [유효성 검사 ▼] → 주문 폼      │
│  2. [데이터 저장 ▼] → sales_order   │
│  3. [알림 ▼]       → "저장 완료"    │
│  4. [새로고침 ▼]   → 주문 목록      │
│  [+ 동작 추가]                      │
│                                     │
│ ─── 실행 조건 ────                 │
│  [행 선택 시만 ▼]                  │
│                                     │
│ ─── 확인 ────                      │
│  ☑ 실행 전 확인 대화상자            │
│  제목: [저장 확인]                  │
│  메시지: [변경사항을 저장합니다]     │
└─────────────────────────────────────┘

3.4 Layout (통합 레이아웃)

대체 대상: split-panel-layout, v2-split-panel-layout, tabs, v2-tabs, section-card, v2-section-card, section-paper, v2-section-paper, conditional-container, accordion, screen-split-panel, repeat-container

interface LayoutConfig {
  mode: "columns" | "rows" | "tabs" | "accordion" | "card" | "conditional";
  
  // columns/rows 모드
  areas?: {
    id: string;
    label?: string;
    size?: string;        // "1fr", "300px", "auto"
    minSize?: string;
    maxSize?: string;
    collapsible?: boolean;
    resizable?: boolean;  // 드래그로 크기 조절
  }[];
  
  // tabs 모드
  tabs?: {
    id: string;
    label: string;
    icon?: string;
    closable?: boolean;
    lazy?: boolean;       // 탭 전환 시 지연 로드
  }[];
  
  // conditional 모드 (조건에 따라 영역 표시/숨김)
  conditions?: {
    areaId: string;
    showWhen: {
      fieldId: string;
      operator: "eq" | "ne" | "in" | "not_in";
      value: any;
    };
  }[];
  
  // 공통
  gap?: number;
  padding?: number;
  bordered?: boolean;
  title?: string;
}

3.5 Display (통합 표시 컴포넌트)

대체 대상: text-display, v2-text-display, divider-line, v2-divider-line, badge, alert, stats-card, chart, image, progress-bar, v2-media, v2-split-line

interface DisplayConfig {
  displayType: "text" | "heading" | "divider" | "badge" | "alert" | "stat" 
             | "chart" | "image" | "progress" | "spacer" | "html";
  
  // 데이터 바인딩 (선택)
  dataBinding?: {
    tableName?: string;
    columnName?: string;
    expression?: string;      // 계산식: "{total_amount} / {quantity}"
    format?: string;          // 숫자/날짜 포맷
  };
  
  // 텍스트 설정
  text?: {
    content: string;
    size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
    weight?: "normal" | "medium" | "semibold" | "bold";
    color?: string;
    align?: "left" | "center" | "right";
  };
  
  // 차트 설정
  chart?: {
    chartType: "bar" | "line" | "pie" | "donut" | "area";
    dataSource: string;
    xAxis: string;
    yAxis: string[];
    colors?: string[];
  };
  
  // 통계 카드
  stat?: {
    value: string;
    label: string;
    change?: string;
    changeType?: "increase" | "decrease" | "neutral";
    icon?: string;
  };
}

3.6 Search (통합 검색)

대체 대상: table-search-widget, v2-table-search-widget, AdvancedSearchFilters

interface SearchConfig {
  // 연결된 DataView
  targetDataView: string;
  
  // 검색 모드
  mode: "simple" | "advanced" | "combined";
  
  // 검색 필드
  fields?: {
    columnName: string;
    label: string;
    searchType: "text" | "exact" | "range" | "select" | "date_range" | "entity";
    defaultExpanded?: boolean;
  }[];
  
  // 퀵 필터 (버튼 형태)
  quickFilters?: {
    label: string;
    filter: { column: string; operator: string; value: any };
  }[];
}

3.7 Modal (통합 모달)

대체 대상: universal-form-modal, repeat-screen-modal, selected-items-detail-input

interface ModalConfig {
  // 트리거
  trigger: "button" | "row_click" | "row_double_click" | "action";
  
  // 모달 내부
  content: {
    type: "form" | "screen" | "custom";
    
    // form: 필드 자동 구성
    formConfig?: {
      tableName: string;
      mode: "create" | "edit" | "view";
      columns: string[];          // 표시할 컬럼
      layout?: "single" | "two_column";
    };
    
    // screen: 다른 화면 임베딩
    screenId?: number;
    
    // 데이터 전달
    passData?: {
      from: string;               // 현재 화면의 필드/컬럼
      to: string;                 // 모달 내부의 필드/컬럼
    }[];
  };
  
  // 크기
  size?: "sm" | "md" | "lg" | "xl" | "full";
  
  // 닫힐 때 동작
  onClose?: ActionStep[];
}

4. 컴포넌트 간 동적 연동 시스템

4.1 현재의 한계

[거래처 Field]  →  독립 동작  ←  [납품처 Field]
                   연결 없음

4.2 새로운 연동 시스템: Reactive Bindings

interface ReactiveBinding {
  id: string;
  source: {
    componentId: string;
    event: "change" | "select" | "click" | "load";
    field?: string;
  };
  target: {
    componentId: string;
    action: "filter" | "setValue" | "show" | "hide" | "enable" | "disable" | "refresh";
    field?: string;
  };
  transform?: {
    type: "direct" | "lookup" | "calculate" | "condition";
    expression?: string;
  };
}

사용자가 설정하는 방식:

┌─────────────────────────────────────────────┐
│ 연동 설정                                   │
├─────────────────────────────────────────────┤
│                                             │
│ [거래처 ●]─── 변경 시 ───→[납품처 ●]       │
│               └ 필터링: customer_code 일치   │
│                                             │
│ [수량 ●]──┐                                │
│            ├─ 계산 ──→[금액 ●]             │
│ [단가 ●]──┘   수량 × 단가                  │
│                                             │
│ [상태 ●]─── "출고완료" 일 때 ──→[삭제 ●]   │
│               └ 비활성화                     │
│                                             │
│ [+ 새 연동 추가]                            │
└─────────────────────────────────────────────┘

4.3 마스터-디테일 자동 연결

현재는 SplitPanel + 하드코딩된 이벤트 처리가 필요하지만, 새로운 시스템에서는:

DataView(마스터: 수주목록)
  ↕ 자동 연결 (FK: order_id)
DataView(디테일: 수주상세품목)

설정 방법: DataView의 dataSource.masterField 하나만 선택하면 자동 연결


5. 통합 설정 패널 재설계

5.1 현재 → 새로운 방식

현재: 26개의 각기 다른 ConfigPanel

새로운: 1개의 통합 설정 패널 (UnifiedConfigPanel)

┌─────────────────────────────────────┐
│ 📋 설정                     [×]     │
├─────────────────────────────────────┤
│ [기본] [데이터] [표시] [연동] [조건]│  ← 5개 탭으로 통일
├─────────────────────────────────────┤
│                                     │
│ ◆ 기본 탭                          │
│   컴포넌트 유형: Field              │
│   표시 형태: [텍스트 ▼]            │
│   라벨: [수주번호]                  │
│   필수: ☑   읽기전용: ☐            │
│                                     │
│ ◆ 데이터 탭                        │
│   테이블: sales_order_mng           │
│   컬럼: order_no                    │
│   기본값: [자동생성]                │
│                                     │
│ ◆ 표시 탭                          │
│   너비: [━━━━━━○━━] 50%            │
│   라벨 위치: [좌측 ▼]              │
│   도움말: [...]                     │
│                                     │
│ ◆ 연동 탭                          │
│   거래처 변경 시 → 납품처 필터링    │
│   [+ 연동 추가]                     │
│                                     │
│ ◆ 조건 탭                          │
│   표시 조건: [항상 ▼]              │
│   활성 조건: [항상 ▼]              │
└─────────────────────────────────────┘

5.2 설정 난이도별 UI 분리

[간편 모드]  ← 기본 (현업 관리자용)
  라벨, 필수, 읽기전용, 너비 정도만

[상세 모드]  ← 토글로 전환 (파워유저용)
  검증 규칙, 계산식, 조건부 표시, API 연결 등

[개발자 모드]  ← 숨겨진 모드 (개발자 전용)
  커스텀 렌더러, 이벤트 훅, CSS 오버라이드

6. 캔버스/디자이너 UI 재설계

6.1 새로운 디자이너 레이아웃

┌─────────────────────────────────────────────────────┐
│ [← 목록] │ 수주관리 화면 │ 💾 자동저장 ON │ [미리보기]│
├──────────┼──────────────────────────────┼────────────┤
│          │                              │            │
│ 컴포넌트 │     ┌──────────────────┐     │ 설정       │
│ --------│     │                  │     │ --------  │
│ 📊 Data │     │   [캔버스 영역]   │     │ [기본]    │
│ 📝 Field│     │                  │     │ [데이터]  │
│ ▶ Action│     │   드래그하여      │     │ [표시]    │
│ 📐 Layout     │   컴포넌트 추가   │     │ [연동]    │
│ 📄 Display    │                  │     │ [조건]    │
│ 🔍 Search│    │                  │     │           │
│ 📋 Modal │    └──────────────────┘     │           │
│          │                              │           │
│ 테이블   │  ──────────────────────────  │           │
│ --------│  [줌: 100%] [맞춤] [그리드]  │           │
│ 수주관리 │                              │           │
│  └ 컬럼들│                              │           │
├──────────┼──────────────────────────────┼────────────┤
│ [연동 설정]    컴포넌트 간 연결 시각화                │
│ [거래처] ─── 변경 시 ──→ [납품처] 필터링             │
└─────────────────────────────────────────────────────┘

6.2 핵심 UX 개선 사항

항목 현재 새로운
컴포넌트 패널 70개 위젯 나열 7개 메타 컴포넌트 + 테이블 컬럼
드롭 피드백 없음 스냅 가이드라인 + 드롭 영역 하이라이트
설정 패널 컴포넌트별 26개 통합 5탭 패널 (간편/상세/개발자 모드)
빈 캔버스 빈 화면 "테이블을 드래그하여 시작하세요" 가이드
마우스 휠만 우하단 줌 컨트롤 (+/-/맞춤/100%)
저장 수동만 자동 저장 + 수동 저장
연동 코드 필요 하단 연동 패널에서 시각적 설정
미리보기 새 창 인라인 미리보기 모드 (디자인↔미리보기 전환)

6.3 "테이블 드롭" 자동 화면 생성

테이블을 캔버스에 드롭하면 자동으로 화면 구성:

[sales_order_mng 테이블 드롭]
      ↓
┌─────────────────────────────────────┐
│ 🪄 화면 자동 생성                    │
├─────────────────────────────────────┤
│ 어떤 형태로 만들까요?               │
│                                     │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐   │
│ │목록형│ │폼형 │ │마디 │ │카드 │   │
│ │     │ │     │ │     │ │     │   │
│ │ ≡≡≡ │ │ □□  │ │≡≡│□│ │ ▦▦▦ │   │
│ │ ≡≡≡ │ │ □□  │ │≡≡│□│ │ ▦▦▦ │   │
│ └─────┘ └─────┘ └─────┘ └─────┘   │
│  테이블  입력폼  마스터   카드 그리드│
│  + CRUD  + 저장  디테일   + 필터    │
│                                     │
│ 포함할 컬럼:                        │
│ ☑ order_no (수주번호)               │
│ ☑ customer_code (거래처) → entity   │
│ ☑ order_date (수주일) → date        │
│ ☑ quantity (수량) → number          │
│ ☐ created_by (생성자) [숨김 추천]   │
│ ☐ updated_at (수정일) [숨김 추천]   │
│                                     │
│         [생성하기]                   │
└─────────────────────────────────────┘

생성 결과 (목록형 선택 시):

자동 생성되는 컴포넌트:
1. Search 컴포넌트 (검색바)
2. Action 컴포넌트 그룹 (등록/수정/삭제 버튼)
3. DataView 컴포넌트 (테이블 뷰, 선택한 컬럼 포함)
4. Modal 컴포넌트 (등록/수정용 폼 모달, Field 자동 구성)

7. 마이그레이션 전략

7.1 기존 레이아웃 호환

기존 1,407개 레이아웃(version: "2.0")은 유지하면서 새 시스템 도입:

// 레이아웃 로드 시 자동 변환
function loadLayout(data: LayoutData): LayoutData {
  if (data.version === "2.0") {
    // 기존 컴포넌트 → 메타 컴포넌트 매핑
    return migrateTo3_0(data);
  }
  return data;
}

function migrateTo3_0(data: LayoutData): LayoutData {
  const newComponents = data.components.map(comp => {
    // text-input, number-input, date-input 등 → Field
    if (isInputComponent(comp.componentType)) {
      return convertToField(comp);
    }
    // table-list, v2-table-list 등 → DataView
    if (isDataComponent(comp.componentType)) {
      return convertToDataView(comp);
    }
    // button-primary → Action
    if (isButtonComponent(comp.componentType)) {
      return convertToAction(comp);
    }
    return comp; // 변환 불가 시 기존 유지
  });
  
  return { ...data, version: "3.0", components: newComponents };
}

7.2 단계적 전환 계획

Phase A: 메타 컴포넌트 코어 개발 (3~4주)
  - Field, DataView, Action 핵심 3개 먼저
  - 통합 설정 패널 (UnifiedConfigPanel)
  - Reactive Bindings 엔진

Phase B: 자동 생성 시스템 (2~3주)
  - 테이블 드롭 → 화면 자동 생성
  - 컬럼 webType → Field 자동 변환
  - FK 관계 → 연동 자동 설정

Phase C: 나머지 메타 컴포넌트 (2~3주)
  - Layout, Display, Search, Modal
  - 뷰 모드 전환 (테이블↔카드↔트리)

Phase D: 마이그레이션 & 정리 (2주)
  - 기존 레이아웃 자동 변환
  - 레거시 컴포넌트 정리
  - 사용자 가이드 작성

7.3 공존 기간

[현재]     → [Phase A~C]        → [Phase D]         → [완료]
70개 위젯    70개 위젯            70개 위젯            7개 메타
             + 7개 메타           + 7개 메타 (기본)    (기존 호환 유지)
             (선택적 사용)        (기존은 마이그레이션)

8. 기존 컴포넌트 → 메타 컴포넌트 매핑표

8.1 Field로 통합 (18개 → 1개)

기존 컴포넌트 webType 매핑 비고
text-input text
number-input number
date-input date
select-basic select options 자동 감지
checkbox-basic checkbox
radio-basic radio
textarea-basic textarea
file-upload file
entity-search-input entity join 자동 감지
autocomplete-search-input entity searchable: true
slider-basic slider
toggle-switch toggle
numbering-rule numbering autoGeneration 설정
image-widget file accept: "image/*"
v2-input text/number/email/tel/url inputType에 따라
v2-select select
v2-date date/datetime
v2-file-upload file

8.2 DataView로 통합 (14개 → 1개)

기존 컴포넌트 viewMode 매핑 비고
table-list table
v2-table-list table
v2-table-grouped table groupBy 설정
v2-repeater table editableColumns 설정
simple-repeater-table table inline edit
modal-repeater-table table + modal
card-display card
v2-card-display card
pivot-grid pivot
v2-pivot-grid pivot
v2-bom-tree tree
aggregation-widget table summaryColumns 설정
v2-aggregation-widget table summaryColumns 설정
v2-timeline-scheduler timeline

8.3 Action으로 통합 (4개 → 1개)

기존 컴포넌트 비고
button-primary steps 설정
v2-button-primary steps 설정
flow-widget flowMove step
related-data-buttons navigate step

8.4 Layout으로 통합 (12개 → 1개)

기존 컴포넌트 mode 매핑
split-panel-layout columns
v2-split-panel-layout columns
screen-split-panel columns (화면 임베딩)
tabs tabs
v2-tabs-widget tabs
section-card card
v2-section-card card
section-paper card (variant)
v2-section-paper card (variant)
conditional-container conditional
accordion-basic accordion
repeat-container rows (반복)
v2-repeat-container rows (반복)

8.5 Display로 통합 (12개 → 1개)

기존 컴포넌트 displayType 매핑
text-display text
v2-text-display text
divider-line divider
v2-divider-line divider
v2-split-line divider
badge badge
alert alert
stats-card stat
chart chart
image-display image
progress-bar progress
v2-media image

8.6 특수 컴포넌트 (별도 유지 또는 DataView 확장)

기존 컴포넌트 처리 방안
v2-bom-item-editor DataView(tree) + inline edit
rack-structure 별도 유지 (특수 시각화)
v2-rack-structure 별도 유지
v2-location-swap-selector 별도 유지 (특수 UI)
location-swap-selector 별도 유지
map 별도 유지 (지도)
category-manager DataView(tree) + Action 조합
v2-category-manager DataView(tree) + Action 조합
customer-item-mapping DataView + Search 조합
tax-invoice-list DataView + Action + Modal 조합
mail-recipient-selector 별도 유지 (특수 UI)
v2-process-work-standard DataView + Modal 조합
v2-item-routing DataView(tree) + Action 조합
repeater-field-group Layout(rows) + Field 조합

9. 기술 스택 결정 사항

영역 선택 이유
상태 관리 Zustand 경량, 보일러플레이트 적음, React에 최적화
DnD @dnd-kit 터치 지원, 커스텀 오버레이, 접근성
연동 엔진 자체 구현 (EventBus 확장) 기존 EventBus 활용, 프로젝트 특화
설정 UI Schema-driven form configSchema 기반 자동 폼 생성
캔버스 CSS Grid + 절대 좌표 하이브리드 기존 호환 + 반응형 전환

10. 성공 지표

지표 현재 목표
새 화면 만드는 시간 (현업) 불가능 (개발자 필요) 5~10분
새 화면 만드는 시간 (개발자) 15~30분 2~5분
새 위젯 타입 추가 시 개발 공수 1~3일 (5~8파일) 대부분 설정으로 해결, 특수한 경우만 개발
컴포넌트 패널 항목 수 70개+ (혼란) 7개 메타 + 테이블 컬럼
ConfigPanel 파일 수 26개 1개 (UnifiedConfigPanel)
컴포넌트 간 연동 설정 코드 필요 UI로 클릭 설정
ScreenDesigner.tsx 줄 수 7,593줄 1,500줄 이하 (훅 분리)

11. 위험 요소

위험 영향 완화 방안
기존 1,407개 레이아웃 마이그레이션 실패 운영 중단 자동 변환 + 수동 검증 + 롤백 가능
메타 컴포넌트가 모든 케이스를 커버 못 함 특수 기능 불가 특수 컴포넌트 별도 유지 (8.6 참고)
통합 설정 패널이 오히려 복잡해질 수 있음 UX 저하 간편/상세/개발자 3단계 모드 분리
Reactive Bindings 디버깅 어려움 유지보수 연동 시각화 패널 + 로그 제공
개발 기간 장기화 일정 지연 Phase별 독립 배포 가능하게 설계

12. 결론

현재 시스템의 본질적 한계: 기능 = 컴포넌트. 기능이 늘면 컴포넌트가 늘고, 코드가 늘고, 복잡도가 늘어남.

새로운 방향: 7개의 메타 컴포넌트(Field, DataView, Action, Layout, Display, Search, Modal)로 통합하고, 컴포넌트 간 Reactive Bindings로 동적 연동을 지원.

사용자가 얻는 것: 테이블 드롭 한 번으로 기본 화면 완성, 설정 몇 번으로 업무에 맞게 커스터마이징, 개발자 없이 화면 변경 가능.

개발팀이 얻는 것: 새 기능 요청 시 코드 작성 대신 설정 가이드 제공, ConfigPanel 26개 → 1개로 유지보수 대폭 감소, 7,593줄 거대 파일 분리.

전체 예상 기간: 9~12주 (Phase A~D)