ERP-node/test-output/screen-149-field-type-verif...

5.4 KiB

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행)

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가 다를 수 있음
  • wacecompany_code = '*' → division은 category, unit은 text

2. 화면 레이아웃에 저장된 값

  • componentConfig.fieldType이 있으면 DB보다 우선될 수 있음
  • 코드상으로는 dbInputType이 우선이므로, DB가 제대로 로드되면 덮어씀

3. 캐시

  • 백엔드 5분, 프론트 5초
  • 데이터 타입 변경 후 곧바로 화면을 열면 이전 캐시가 사용될 수 있음

4. API 응답 구조

  • columnMetaCache에 넣을 때 col.column_name || col.columnName 사용
  • mergeColumnMetameta.input_type || meta.inputType 사용
  • 백엔드는 inputType(camelCase) 반환 → columnMetaCacheinputType 유지

디버깅용 Console 스크립트

화면 149 로드 후 브라우저 Console에서 실행:

// 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")) 호출 후 재검증