ERP-node/docs/DDD1542/V2_마이그레이션_학습노트_DDD1542.md

14 KiB

V2 마이그레이션 학습노트 (DDD1542 전용)

목적: 마이그레이션 작업 전 완벽한 이해를 위한 개인 학습노트 작성일: 2026-02-03 절대 규칙: 모르면 물어보기, 추측 금지


1. 가장 중요한 핵심 (이전 신하가 실패한 이유)

1.1 "component" vs "v2-input" 차이

[잘못된 상태]              [올바른 상태]
┌──────────────────┐      ┌──────────────────┐
│ component        │      │ v2-input         │
│ 업체코드         │      │ 업체코드         │
│ "자동 생성됩니다" │      │ "자동 생성됩니다" │
└──────────────────┘      └──────────────────┘
    ↑                         ↑
    테이블-컬럼 연결 없음        table_name + column_name 연결됨

핵심: 컬럼을 왼쪽 패널에서 드래그해야 올바른 연결이 생성됨

1.2 올바른 컴포넌트 생성 방법

[왼쪽 패널: 테이블 컬럼 목록]
운송업체 (8개)
├── 업체코드 [numbering]  ─드래그→  화면 캔버스  →  v2-numbering-rule (또는 v2-input)
├── 업체명 [text]         ─드래그→  화면 캔버스  →  v2-input
├── 유형 [category]       ─드래그→  화면 캔버스  →  v2-select
├── 연락처 [text]         ─드래그→  화면 캔버스  →  v2-input
└── ...

1.3 input_type → V2 컴포넌트 매핑

table_type_columns.input_type V2 컴포넌트 연동 테이블
text v2-input -
number v2-input (type=number) -
date v2-date -
category v2-select category_values
numbering v2-numbering-rule 또는 v2-input numbering_rules
entity v2-entity-search 엔티티 조인

2. V1 vs V2 구조 차이

2.1 테이블 구조

V1 (본서버: screen_layouts)          V2 (개발서버: screen_layouts_v2)
──────────────────────────────────────────────────────────────────
- 컴포넌트별 1개 레코드              - 화면당 1개 레코드
- properties JSONB                   - layout_data JSONB
- component_type VARCHAR             - url (컴포넌트 경로)
- menu_objid 기반 채번/카테고리      - table_name + column_name 기반

2.2 V2 layout_data 구조

{
  "version": "2.0",
  "components": [
    {
      "id": "comp_xxx",
      "url": "@/lib/registry/components/v2-table-list",
      "position": { "x": 0, "y": 0 },
      "size": { "width": 100, "height": 50 },
      "displayOrder": 0,
      "overrides": {
        "tableName": "inspection_standard",
        "columns": ["id", "name", "status"]
      }
    }
  ],
  "updatedAt": "2026-02-03T12:00:00Z"
}

2.3 컴포넌트 URL 매핑

const V1_TO_V2_URL_MAPPING = {
  'table-list':          '@/lib/registry/components/v2-table-list',
  'button-primary':      '@/lib/registry/components/v2-button-primary',
  'text-input':          '@/lib/registry/components/v2-input',
  'select-basic':        '@/lib/registry/components/v2-select',
  'date-input':          '@/lib/registry/components/v2-date',
  'entity-search-input': '@/lib/registry/components/v2-entity-search',
  'category-manager':    '@/lib/registry/components/v2-category-manager',
  'numbering-rule':      '@/lib/registry/components/v2-numbering-rule',
  'tabs-widget':         '@/lib/registry/components/v2-tabs-widget',
  'split-panel-layout':  '@/lib/registry/components/v2-split-panel-layout',
};

3. 데이터 타입 관리 (V2)

3.1 핵심 테이블 관계

table_type_columns (컬럼 타입 정의)
├── input_type = 'category'  → category_values (table_name + column_name)
├── input_type = 'numbering' → numbering_rules (detail_settings.numberingRuleId)
├── input_type = 'entity'    → 엔티티 조인
└── input_type = 'text', 'number', 'date', etc.

3.2 category_values 조회 쿼리

-- 특정 테이블.컬럼의 카테고리 값 조회
SELECT value_id, value_code, value_label, parent_value_id, depth
FROM category_values
WHERE table_name = '테이블명'
  AND column_name = '컬럼명'
  AND company_code = 'COMPANY_7'
ORDER BY value_order;

3.3 numbering_rules 연결 방식

// table_type_columns.detail_settings
{
  "numberingRuleId": "rule-xxx"
}

// numbering_rules에서 해당 rule 조회
SELECT * FROM numbering_rules WHERE rule_id = 'rule-xxx';

4. V2 컴포넌트 목록 (23개)

4.1 입력 컴포넌트

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

4.2 표시 컴포넌트

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

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

ID 이름 용도
v2-table-list 테이블 리스트 데이터 그리드
v2-table-search-widget 검색 필터 테이블 검색
v2-pivot-grid 피벗 그리드 다차원 분석
v2-table-grouped 그룹화 테이블 그룹별 접기/펼치기

4.4 레이아웃 컴포넌트

ID 이름 용도
v2-split-panel-layout 분할 패널 마스터-디테일
v2-tabs-widget 탭 위젯 탭 전환
v2-section-card 섹션 카드 제목+테두리 그룹
v2-section-paper 섹션 페이퍼 배경색 그룹
v2-divider-line 구분선 영역 구분
v2-repeat-container 리피터 컨테이너 데이터 반복
v2-unified-repeater 통합 리피터 인라인/모달/버튼

4.5 액션/특수 컴포넌트

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

5. 화면 패턴 (5가지)

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

사용 조건: 단일 테이블 CRUD

┌─────────────────────────────────────────────────┐
│ v2-table-search-widget                          │
├─────────────────────────────────────────────────┤
│ v2-table-list                                   │
│ [신규] [삭제] v2-button-primary                 │
└─────────────────────────────────────────────────┘

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

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

┌──────────────────┬──────────────────────────────┐
│ 마스터 리스트    │ 디테일 리스트                │
│ v2-table-list    │ v2-table-list                │
│                  │ (relation: foreignKey)       │
└──────────────────┴──────────────────────────────┘
          v2-split-panel-layout

필수 설정:

{
  "leftPanel": { "tableName": "master_table" },
  "rightPanel": {
    "tableName": "detail_table",
    "relation": { "type": "detail", "foreignKey": "master_id" }
  },
  "splitRatio": 30
}

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

┌──────────────────┬──────────────────────────────┐
│ 마스터 리스트    │ v2-tabs-widget               │
│ v2-table-list    │ ├─ 탭1: v2-table-list        │
│                  │ ├─ 탭2: v2-table-list        │
│                  │ └─ 탭3: 폼 컴포넌트들        │
└──────────────────┴──────────────────────────────┘
          v2-split-panel-layout

6. 모달 처리 방식 변경

6.1 V1 (본서버)

화면 A (screen_id: 142) - 검사장비관리
    └── 버튼 클릭 → 화면 B (screen_id: 143) - 검사장비 등록모달 (별도 screen_id)

6.2 V2 (개발서버)

화면 A (screen_id: 142) - 검사장비관리
    └── layout_data.components[] 내에 v2-dialog-form 또는 overlay 포함

핵심: V2에서는 모달을 별도 화면이 아닌, 부모 화면의 컴포넌트로 통합


7. 마이그레이션 절차 (Step by Step)

Step 1: 사전 분석

-- 본서버 화면 목록 확인
SELECT sd.screen_id, sd.screen_code, sd.screen_name, sd.table_name,
       COUNT(sl.layout_id) as component_count
FROM screen_definitions sd
LEFT JOIN screen_layouts sl ON sd.screen_id = sl.screen_id
WHERE sd.screen_code LIKE 'COMPANY_7_%'
GROUP BY sd.screen_id, sd.screen_code, sd.screen_name, sd.table_name;

-- 개발서버 V2 현황 확인
SELECT sd.screen_id, sd.screen_code, sd.screen_name,
       sv2.layout_data IS NOT NULL as has_v2_layout
FROM screen_definitions sd
LEFT JOIN screen_layouts_v2 sv2 ON sd.screen_id = sv2.screen_id
WHERE sd.company_code = 'COMPANY_7';

Step 2: table_type_columns 확인

-- 해당 테이블의 컬럼 타입 확인
SELECT column_name, column_label, input_type, detail_settings
FROM table_type_columns
WHERE table_name = '대상테이블명'
  AND company_code = 'COMPANY_7';

Step 3: V2 layout_data 생성

{
  "version": "2.0",
  "components": [
    {
      "id": "생성된ID",
      "url": "@/lib/registry/components/v2-컴포넌트타입",
      "position": { "x": 0, "y": 0 },
      "size": { "width": 100, "height": 50 },
      "displayOrder": 0,
      "overrides": {
        "tableName": "테이블명",
        "fieldName": "컬럼명"
      }
    }
  ],
  "migratedFrom": "V1",
  "migratedAt": "2026-02-03T00:00:00Z"
}

Step 4: screen_layouts_v2 INSERT

INSERT INTO screen_layouts_v2 (screen_id, company_code, layout_data)
VALUES ($1, $2, $3::jsonb)
ON CONFLICT (screen_id, company_code) 
DO UPDATE SET layout_data = $3::jsonb, updated_at = NOW();

Step 5: 검증

  • 화면 렌더링 확인 (component가 아닌 v2-xxx로 표시되는지)
  • 컴포넌트별 테이블-컬럼 연결 확인
  • 카테고리 드롭다운 동작 확인
  • 채번 규칙 동작 확인
  • 저장/수정/삭제 테스트

8. 품질관리 메뉴 마이그레이션 현황

본서버 코드 화면명 테이블 상태 비고
COMPANY_7_126 검사정보 관리 inspection_standard V2 존재 컴포넌트 검증 필요
COMPANY_7_127 품목옵션 설정 - V2 존재 v2-category-manager
COMPANY_7_138 카테고리 설정 inspection_standard 누락 table_name 기반
COMPANY_7_139 코드 설정 inspection_standard 누락 table_name 기반
COMPANY_7_142 검사장비 관리 inspection_equipment_mng 누락 모달 통합
COMPANY_7_143 검사장비 등록모달 inspection_equipment_mng 누락 → 142 통합
COMPANY_7_144 불량기준 정보 defect_standard_mng 누락 모달 통합
COMPANY_7_145 불량기준 등록모달 defect_standard_mng 누락 → 144 통합

9. 관련 코드 파일 경로

항목 경로
V2 컴포넌트 폴더 frontend/lib/registry/components/v2-xxx/
컴포넌트 등록 frontend/lib/registry/components/index.ts
카테고리 서비스 backend-node/src/services/categoryTreeService.ts
채번 서비스 backend-node/src/services/numberingRuleService.ts
엔티티 조인 API frontend/lib/api/entityJoin.ts
폼 호환성 훅 frontend/hooks/useFormCompatibility.ts

10. 절대 하지 말 것

  1. 테이블-컬럼 연결 없이 컴포넌트 배치 → "component"로 표시됨
  2. menu_objid 기반 카테고리/채번 사용 → V2는 table_name + column_name 기반
  3. 모달을 별도 screen_id로 생성 → V2는 부모 화면에 통합
  4. V1 컴포넌트 타입 사용 → 반드시 v2- 접두사 컴포넌트 사용
  5. company_code 필터링 누락 → 멀티테넌시 필수

11. 모르면 확인할 곳

  1. 컴포넌트 구조: docs/V2_컴포넌트_분석_가이드.md
  2. 화면 개발 표준: docs/screen-implementation-guide/화면개발_표준_가이드.md
  3. 마이그레이션 절차: docs/DDD1542/본서버_개발서버_마이그레이션_상세가이드.md
  4. 탑실 디자인 명세: /Users/gbpark/Downloads/화면개발 8/
  5. 실제 코드: 위 경로의 소스 파일들

12. 왕의 훈계

"항상 애매한 거는 md파일 보거나 물어볼 것. 코드에는 전부 정답이 있음. 만약 모른다면 너 잘못. 실수해도 너 잘못."


변경 이력

날짜 작성자 내용
2026-02-03 DDD1542 초안 작성 (문서 4개 정독 후)