# [맥락노트] 카테고리 드롭다운 - 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` — 화면에만 보이는 값, 들여쓰기 포함
- 데이터 무결성에 영향 없음
