# Screen 149 필드 타입 검증 가이드 ## 배경 - **화면 149**: 품목정보 (item_info 테이블) 폼 - **division 컬럼**: DB에서 `input_type = 'text'`로 변경했으나 화면에는 여전히 SELECT 드롭다운으로 표시 - **unit 컬럼**: `input_type = 'category'` → SELECT 드롭다운으로 표시되어야 함 ## DB 현황 (vexplor-dev 조회 결과) | column_name | company_code | input_type | |-------------|--------------|------------| | division | * | category | | division | COMPANY_7 | **text** | | division | COMPANY_8, 9, 10, 18, 19, 20, 21 | category | | unit | * | text | | unit | COMPANY_18, 19, 20, 21, 7, 8, 9 | **category** | **주의:** `wace` 사용자는 `company_code = '*'` (최고 관리자)입니다. - division: company * → **category** (text 아님) - unit: company * → **text** (category 아님) **회사별로 다릅니다.** 예: COMPANY_7의 division은 text, unit은 category. --- ## 수동 검증 절차 ### 1. 로그인 - URL: `http://localhost:9771/login` - User ID: `wace` - Password: `wace0909!!` - 회사: "탑씰" (해당 회사 코드 확인 필요) ### 2. 화면 149 접속 - URL: `http://localhost:9771/screens/149` - 페이지 로드 대기 ### 3. 필드 확인 #### 구분 (division) - **예상 (DB 기준):** - company *: SELECT (category) - COMPANY_7: TEXT INPUT (text) - **실제:** TEXT INPUT 또는 SELECT 중 어느 쪽인지 확인 #### 단위 (unit) - **예상 (DB 기준):** - company *: TEXT INPUT (text) - COMPANY_18~21, 7~9: SELECT (category) - **실제:** TEXT INPUT 또는 SELECT 중 어느 쪽인지 확인 ### 4. 스크린샷 - 구분, 단위 필드가 함께 보이도록 캡처 --- ## 코드 흐름 (input_type → 렌더링) ### 1. 컬럼 메타 로드 ``` DynamicComponentRenderer → loadColumnMeta(screenTableName) → GET /api/table-management/tables/item_info/columns?size=1000 → columnMetaCache[tableName][columnName] = { inputType, ... } ``` ### 2. 렌더 타입 결정 (357~369행) ```javascript const dbInputType = columnMetaCache[screenTableName]?.[baseCol]?.inputType; const ft = dbInputType || componentConfig?.fieldType; if (["text", "number", ...].includes(ft)) return "v2-input"; // 텍스트 입력 if (["select", "category", "entity"].includes(ft)) return "v2-select"; // 드롭다운 ``` ### 3. mergeColumnMeta (81~130행) - DB `input_type`이 화면 저장값보다 우선 - `needsSync`이면 DB 값으로 덮어씀 --- ## 캐시 관련 ### 1. 프론트엔드 (DynamicComponentRenderer) - `columnMetaCache`: TTL 5초 - `table-columns-refresh` 이벤트 시 즉시 무효화 및 재로드 ### 2. 백엔드 (tableManagementService) - 컬럼 목록: 5분 TTL - `updateColumnInputType` 호출 시 해당 테이블 캐시 삭제 ### 3. 캐시 무효화가 필요한 경우 - 데이터 타입 관리에서 변경 후 화면이 갱신되지 않을 때 - **대응:** 페이지 새로고침 또는 `?_t=timestamp`로 API 재요청 --- ## 가능한 원인 ### 1. 회사 코드 불일치 - 로그인한 사용자 회사와 DB의 `company_code`가 다를 수 있음 - `wace`는 `company_code = '*'` → division은 category, unit은 text ### 2. 화면 레이아웃에 저장된 값 - `componentConfig.fieldType`이 있으면 DB보다 우선될 수 있음 - 코드상으로는 `dbInputType`이 우선이므로, DB가 제대로 로드되면 덮어씀 ### 3. 캐시 - 백엔드 5분, 프론트 5초 - 데이터 타입 변경 후 곧바로 화면을 열면 이전 캐시가 사용될 수 있음 ### 4. API 응답 구조 - `columnMetaCache`에 넣을 때 `col.column_name || col.columnName` 사용 - `mergeColumnMeta`는 `meta.input_type || meta.inputType` 사용 - 백엔드는 `inputType`(camelCase) 반환 → `columnMetaCache`에 `inputType` 유지 --- ## 디버깅용 Console 스크립트 화면 149 로드 후 브라우저 Console에서 실행: ```javascript // 1. columnMetaCache 조회 (DynamicComponentRenderer 내부) // React DevTools로 DynamicComponentRenderer 선택 후 // 또는 전역에 노출해 둔 경우: const meta = window.__COLUMN_META_CACHE__?.item_info; if (meta) { console.log("division:", meta.division?.inputType || meta.division?.input_type); console.log("unit:", meta.unit?.inputType || meta.unit?.input_type); } // 2. API 직접 호출 fetch("/api/table-management/tables/item_info/columns?size=1000", { credentials: "include" }) .then(r => r.json()) .then(d => { const cols = d.data?.columns || d.columns || []; const div = cols.find(c => (c.columnName || c.column_name) === "division"); const unit = cols.find(c => (c.columnName || c.column_name) === "unit"); console.log("API division:", div?.inputType || div?.input_type); console.log("API unit:", unit?.inputType || unit?.input_type); }); ``` --- ## 권장 사항 1. **회사 코드 확인** - 로그인한 사용자의 `company_code` 확인 - `division`/`unit`을 text/category로 바꾼 회사가 맞는지 확인 2. **캐시 우회** - 데이터 타입 변경 후 페이지 새로고침 - 또는 5초 이상 대기 후 다시 접속 3. **데이터 타입 관리에서 변경 시** - 저장 후 `table-columns-refresh` 이벤트 발생 여부 확인 - 화면 디자이너의 V2FieldConfigPanel에서 변경 시에는 이벤트가 발생함 4. **테이블 관리 UI에서 변경 시** - `table-columns-refresh` 이벤트가 발생하는지 확인 - 없으면 해당 화면에서 수동으로 `window.dispatchEvent(new CustomEvent("table-columns-refresh"))` 호출 후 재검증