106 lines
4.5 KiB
Markdown
106 lines
4.5 KiB
Markdown
# [맥락노트] 카테고리 드롭다운 - 3단계 깊이 구분 표시
|
|
|
|
> 관련 문서: [계획서](./CTI[계획]-카테고리-깊이구분.md) | [체크리스트](./CTI[체크]-카테고리-깊이구분.md)
|
|
|
|
---
|
|
|
|
## 왜 이 작업을 하는가
|
|
|
|
- 품목정보 등록 모달의 "재고단위" 등 카테고리 드롭다운에서 3단계 계층이 시각적으로 구분되지 않음
|
|
- 예: "신22"가 "신2"의 하위인데, "신3", "신4"와 같은 레벨로 보임
|
|
- 사용자가 대분류/중분류/소분류 관계를 파악할 수 없어 잘못된 항목을 선택할 위험
|
|
|
|
---
|
|
|
|
## 핵심 결정 사항과 근거
|
|
|
|
### 1. 원인: HTML 공백 축소(collapse)
|
|
|
|
- **현상**: `flattenTree`에서 `" ".repeat(depth)`로 들여쓰기를 만들지만, HTML이 연속 공백을 하나로 합침
|
|
- **결과**: depth 1(`" └ "`)과 depth 2(`" └ "`)가 동일하게 렌더링됨
|
|
- **확인**: `SelectItem`, `CommandItem` 모두 `white-space: pre` 미적용 상태
|
|
|
|
### 2. 해결: Non-Breaking Space(`\u00A0`) 사용
|
|
|
|
- **결정**: 일반 공백 `" "`를 `"\u00A0"`로 교체
|
|
- **근거**: `\u00A0`는 HTML에서 축소되지 않아 depth별 들여쓰기가 정확히 유지됨
|
|
- **대안 검토**:
|
|
- `white-space: pre` CSS 적용 → 기각 (SelectItem, CommandItem 양쪽 모두 수정 필요, shadcn 기본 스타일 오버라이드 부담)
|
|
- CSS `padding-left` 사용 → 기각 (label 문자열 기반 옵션 구조에서 개별 아이템에 스타일 전달 어려움)
|
|
- 트리 문자(`│`, `├`, `└`) 조합 → 기각 (과도한 시각 정보, 단순 들여쓰기면 충분)
|
|
|
|
### 3. depth당 3칸 `\u00A0`
|
|
|
|
- **결정**: `"\u00A0\u00A0\u00A0".repeat(depth)` (depth당 3칸)
|
|
- **근거**: 기존 2칸은 `\u00A0`로 바꿔도 depth간 차이가 작음. 3칸이 시각적 구분에 적절
|
|
|
|
### 4. 두 파일 동시 수정
|
|
|
|
- **결정**: `V2Select.tsx`와 `UnifiedSelect.tsx` 모두 수정
|
|
- **근거**: 동일한 `flattenTree` 패턴이 두 컴포넌트에 존재. 하나만 수정하면 불일치 발생
|
|
|
|
### 5. 기존 prefix strip 정규식 호환
|
|
|
|
- **확인**: V2Select.tsx 979행의 `o.label.replace(/^[\s└]+/, "").trim()`
|
|
- **근거**: JavaScript `\s`는 `\u00A0`를 포함하므로 추가 수정 불필요
|
|
|
|
---
|
|
|
|
## 구현 중 발견한 사항
|
|
|
|
### CAT_ vs CATEGORY_ 접두사 불일치
|
|
|
|
테스트 과정에서 최고 관리자 계정으로 리스트 조회 시 `CAT_MMLL6U02_QH2V` 같은 코드가 그대로 표시되는 현상 발견.
|
|
|
|
- **원인**: 카테고리 값 생성 함수가 두 곳에 존재하며 접두사가 다름
|
|
- `CategoryValueAddDialog.tsx`: `CATEGORY_` 접두사
|
|
- `CategoryValueManagerTree.tsx`: `CAT_` 접두사
|
|
- **영향**: 리스트 해석 로직(`V2Repeater`, `InteractiveDataTable`, `UnifiedRepeater`)이 `CATEGORY_` 접두사만 인식하여 `CAT_` 코드는 라벨 변환 실패
|
|
- **판단**: 일반 회사 계정에서는 정상 동작 확인. 본 작업(들여쓰기 표시) 범위 외로 별도 이슈로 분리
|
|
|
|
---
|
|
|
|
## 관련 파일 위치
|
|
|
|
| 구분 | 파일 경로 | 설명 |
|
|
|------|----------|------|
|
|
| 수정 완료 | `frontend/components/v2/V2Select.tsx` | flattenTree 함수 (904행) |
|
|
| 수정 완료 | `frontend/components/unified/UnifiedSelect.tsx` | flattenTree 함수 (632행) |
|
|
| 백엔드 (변경 없음) | `backend-node/src/services/tableCategoryValueService.ts` | buildHierarchy 메서드 |
|
|
| UI 컴포넌트 (변경 없음) | `frontend/components/ui/select.tsx` | SelectItem 렌더링 |
|
|
| UI 컴포넌트 (변경 없음) | `frontend/components/ui/command.tsx` | CommandItem 렌더링 |
|
|
|
|
---
|
|
|
|
## 기술 참고
|
|
|
|
### flattenTree 동작 흐름
|
|
|
|
```
|
|
백엔드 API 응답 (트리 구조):
|
|
{
|
|
valueCode: "CAT_001", valueLabel: "신예철", children: [
|
|
{ valueCode: "CAT_002", valueLabel: "신2", children: [
|
|
{ valueCode: "CAT_003", valueLabel: "신22", children: [] }
|
|
]},
|
|
{ valueCode: "CAT_004", valueLabel: "신3", children: [] },
|
|
{ valueCode: "CAT_005", valueLabel: "신4", children: [] }
|
|
]
|
|
}
|
|
|
|
→ flattenTree 변환 후 (SelectOption 배열):
|
|
[
|
|
{ value: "CAT_001", label: "신예철" },
|
|
{ value: "CAT_002", label: "\u00A0\u00A0\u00A0└ 신2" },
|
|
{ value: "CAT_003", label: "\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0└ 신22" },
|
|
{ value: "CAT_004", label: "\u00A0\u00A0\u00A0└ 신3" },
|
|
{ value: "CAT_005", label: "\u00A0\u00A0\u00A0└ 신4" }
|
|
]
|
|
```
|
|
|
|
### value vs label 분리
|
|
|
|
- `value` (저장값): `valueCode` — DB에 저장되는 값, 들여쓰기 없음
|
|
- `label` (표시값): prefix + `valueLabel` — 화면에만 보이는 값, 들여쓰기 포함
|
|
- 데이터 무결성에 영향 없음
|