ERP-node/docs/ycshin-node/LFC[맥락]-위치포맷-사용자설정.md

7.4 KiB

[맥락노트] 렉 구조 위치코드/위치명 포맷 사용자 설정

관련 문서: 계획서 | 체크리스트


왜 이 작업을 하는가

  • 위치코드(WH001-1층A구역-01-1)와 위치명(A구역-01열-1단)의 포맷이 하드코딩되어 있음
  • 회사마다 구분자("-" vs "/"), 세그먼트 순서, 한글 라벨 유무 등 요구사항이 다름
  • 현재는 코드를 직접 수정하지 않으면 포맷 변경 불가 → 관리자가 화면 디자이너에서 설정할 수 있어야 함

핵심 결정 사항과 근거

1. 엔드유저 모달이 아닌 화면 디자이너 ConfigPanel에 설정 UI 배치

  • 결정: 포맷 편집 UI를 렉 구조 등록 모달이 아닌 화면 디자이너 좌측 속성 패널(ConfigPanel)에 배치
  • 근거: 프로젝트의 설정-사용 분리 패턴 준수. 모든 v2 컴포넌트가 ConfigPanel에서 설정하고 런타임에서 읽기만 하는 구조를 따름
  • 대안 검토: 모달 안에 포맷 편집 UI 배치(방법 B) → 기각 (프로젝트 관행에 맞지 않음, 매번 설정해야 함, 설정이 휘발됨)

2. 패턴 문자열이 아닌 구조화된 세그먼트 배열 사용

  • 결정: "{warehouseCode}-{floor}{zone}-{row:02d}-{level}" 같은 문자열 대신 FormatSegment[] 배열로 포맷 정의
  • 근거: 관리자가 패턴 문법을 알 필요 없이 드래그/토글/Input으로 직관적 편집 가능
  • 대안 검토: 기존 codePattern/namePattern 문자열 활용 → 기각 (관리자가 패턴 문법을 모를 수 있고, 오타 가능성 높음)

2-1. 체크박스는 한글 라벨 표시/숨김 제어 (showLabel)

  • 결정: 세그먼트의 체크박스는 showLabel 속성을 토글하며, 세그먼트 자체를 제거하지 않음
  • 근거: "A구역-01열-1단"에서 "구역", "열" 체크 해제 시 → "A-01-1단"이 되어야 함 (값은 유지, 한글만 제거)
  • 주의: enabled는 세그먼트 자체의 포함 여부, showLabel은 한글 라벨만 표시/숨김. 혼동하지 않도록 분리

2-2. 라벨/구분/자릿수 3개 필드 항상 고정 표시

  • 결정: 라벨 필드를 비워도 입력 필드가 사라지지 않고, 3개 필드(라벨, 구분, 자릿수)가 모든 세그먼트에 항상 표시
  • 근거: 라벨을 지웠을 때 "라벨 없음"이 뜨면서 입력 필드가 사라지면 다시 라벨을 추가할 수 없는 문제 발생
  • UI 개선: 컬럼 헤더를 최상단에 배치하고, 각 행에서는 "구분", "자릿수" 텍스트를 제거하여 공간 확보

2-3. stripKnownSuffix로 원본 값의 한글 접미사를 먼저 벗긴 뒤 라벨 붙임

  • 결정: buildFormattedString에서 값을 처리할 때, 먼저 KNOWN_SUFFIXES(층, 구역)를 벗겨내고 순수 값만 남긴 뒤, showLabel && label일 때만 라벨을 붙이는 구조
  • 근거: context 값이 "1층", "A구역"처럼 한글이 이미 포함된 상태로 들어옴. 이전 방식(if (seg.label))은 라벨 필드가 빈 문자열이면 조건을 건너뛰어서 한글이 제거되지 않는 버그 발생
  • 핵심 흐름: 원본 값 → stripKnownSuffix → 순수 값 → showLabel && label이면 라벨 붙임

2-4. 자릿수 필드는 숫자 타입만 활성화

  • 결정: 자릿수(pad) 필드는 열(row), 단(level)만 편집 가능, 나머지(창고코드, 층, 구역)는 disabled + 회색 배경
  • 근거: 자릿수(zero-padding)는 숫자 값에만 의미가 있음. 비숫자 타입에 자릿수를 설정하면 혼란을 줄 수 있음

3. 기존 codePattern/namePattern 필드는 삭제하지 않고 유지

  • 결정: types.tscodePattern, namePattern 필드를 삭제하지 않음
  • 근거: 하위 호환. 기존에 이 필드를 참조하는 코드가 없지만, 향후 다른 용도로 활용될 수 있음

4. formatConfig 미설정 시 기본값으로 현재 동작 유지

  • 결정: config.formatConfig가 없으면 defaultFormatConfig 사용
  • 근거: 기존 화면 설정을 수정하지 않아도 현재와 동일한 위치코드/위치명이 생성됨 (무중단 배포 가능)

5. UI 라벨에서 "패딩" 대신 "자릿수" 사용

  • 결정: ConfigPanel UI에서 숫자 제로패딩 설정을 "자릿수"로 표시
  • 근거: 관리자급 사용자가 "패딩"이라는 개발 용어를 모를 수 있음. "자릿수: 2 → 01, 02, ... 99"가 직관적
  • 코드 내부: 변수명은 pad 유지 (개발자 영역)

6. @dnd-kit으로 드래그 구현

  • 결정: @dnd-kit/core + @dnd-kit/sortable 사용
  • 근거: 프로젝트에 이미 설치되어 있고(package.json), SortableCodeItem.tsx, useDragAndDrop.ts 등 표준 패턴이 확립되어 있음
  • 대안 검토: 위/아래 화살표 버튼으로 순서 변경 → 기각 (프로젝트에 이미 DnD 패턴이 있으므로 일관성 유지)

7. v2-pivot-grid의 format 설정 패턴을 참고

  • 결정: ConfigPanel에서 설정 → componentConfig에 저장 → 런타임에서 읽어 사용하는 흐름
  • 근거: v2-pivot-grid가 필드별 format(type, precision, thousandSeparator 등)을 동일한 패턴으로 구현하고 있음. 가장 유사한 선례

관련 파일 위치

구분 파일 경로 설명
타입 정의 frontend/lib/registry/components/v2-rack-structure/types.ts FormatSegment, LocationFormatConfig 타입
기본 설정 frontend/lib/registry/components/v2-rack-structure/config.ts 기본 세그먼트 상수, buildFormattedString 함수
신규 컴포넌트 frontend/lib/registry/components/v2-rack-structure/FormatSegmentEditor.tsx 포맷 편집 UI 서브컴포넌트
설정 패널 frontend/lib/registry/components/v2-rack-structure/RackStructureConfigPanel.tsx FormatSegmentEditor 배치
런타임 컴포넌트 frontend/lib/registry/components/v2-rack-structure/RackStructureComponent.tsx generateLocationCode 세그먼트 기반 교체
DnD 참고 frontend/hooks/useDragAndDrop.ts 프로젝트 표준 DnD 패턴
DnD 참고 frontend/components/admin/SortableCodeItem.tsx useSortable 사용 예시
선례 참고 frontend/lib/registry/components/v2-pivot-grid/ ConfigPanel에서 format 설정하는 패턴

기술 참고

세그먼트 기반 문자열 생성 흐름

FormatSegment[] → filter(enabled && 값 있음) → map(stripKnownSuffix → showLabel && label이면 라벨 붙임 → 자릿수 → 구분자) → join("") → 최종 문자열

componentConfig 저장/로드 흐름

ConfigPanel onChange
  → V2PropertiesPanel.onUpdateProperty("componentConfig", mergedConfig)
  → layout.components[i].componentConfig.formatConfig
  → convertLegacyToV2 → screen_layouts_v2.layout_data.overrides.formatConfig (DB)
  → convertV2ToLegacy → componentConfig.formatConfig (런타임)
  → RackStructureComponent config.formatConfig (prop)

context 값 참고

context.warehouseCode = "WH001"        (창고 코드)
context.floor = "1층"                   (층 라벨 - 값 자체에 "층" 포함)
context.zone = "A구역" 또는 "A"         (구역 라벨 - "구역" 포함 여부 불확실)
row = 1, 2, 3, ...                     (열 번호 - 숫자)
level = 1, 2, 3, ...                   (단 번호 - 숫자)