# [맥락노트] 렉 구조 등록 - 층(floor) 필수 입력 해제

> 관련 문서: [계획서](./RFO[계획]-렉구조-층필수해제.md) | [체크리스트](./RFO[체크]-렉구조-층필수해제.md)

---

## 왜 이 작업을 하는가

- 탑씰 회사에서 창고 렉 구조 등록 시 "층"을 선택하지 않아도 되게 해달라는 요청
- 현재 코드에 창고 코드 / 층 / 구역 3개가 필수로 하드코딩되어 있어, 층 미선택 시 미리보기 생성과 저장이 모두 차단됨
- 층 필수 검증이 6곳에 분산되어 있어 한 곳만 고치면 다른 곳에서 오류 발생

---

## 핵심 결정 사항과 근거

### 1. 방법 B(하드코딩 제거) 채택, 방법 A(설정 기능) 미채택

- **결정**: 코드에서 floor 필수 조건을 직접 제거
- **근거**: 이 프로젝트의 다른 모달/컴포넌트들은 모두 코드에서 직접 "필수/선택"을 정해놓는 방식을 사용. 설정으로 필수 여부를 바꿀 수 있게 만든 패턴은 기존에 없음
- **대안 검토**:
  - 방법 A(ConfigPanel에 requiredFields 설정 추가): 유연하지만 4파일 수정 + 프로젝트에 없던 새 패턴 도입 → 기각
  - "상관없음" 값 추가 후 null 변환: 프로젝트 어디에서도 magic value → null 변환 패턴을 쓰지 않음 → 기각
  - "상관없음" 값만 추가 (코드 무변경): DB에 "상관없음" 텍스트가 저장되어 데이터가 지저분함 → 기각
- **향후**: 회사별 독립 제어가 필요해지면 방법 A로 확장 가능 (충돌 없음)

### 2. 전역 적용 (회사별 독립 설정 아님)

- **결정**: 렉 구조 컴포넌트를 사용하는 모든 회사에 동일 적용
- **근거**: 방법 B는 코드 직접 수정이므로 회사별 분기 불가. 단, 기존처럼 층을 선택하면 완전히 동일하게 동작하므로 다른 회사에 실질적 영향 없음 (선택 안 해도 "되는" 것이지, 안 해야 "하는" 것이 아님)

### 3. floor 미선택 시 NULL 저장 (특수값 아님)

- **결정**: floor를 선택하지 않으면 DB에 `NULL` 저장
- **근거**: 프로젝트 표준 패턴. `UserFormModal`의 `email: formData.email || null`, `EnhancedFormService`의 빈 문자열 → null 자동 변환 등과 동일한 방식
- **대안 검토**: "상관없음" 저장 후 null 변환 → 프로젝트에서 미사용 패턴이므로 기각

### 4. 위치 코드에서 층 부분 생략 (폴백값 "1" 사용 안 함)

- **결정**: floor 없을 때 위치 코드에서 층 부분을 아예 빼버림
- **근거**: 기존 코드는 `context?.floor || "1"`로 폴백하여 1층을 선택한 것처럼 위장됨. 이는 잘못된 데이터를 만들 수 있음
- **결과**:
  - 층 있을 때: `WH001-1층A구역-01-1` (기존과 동일)
  - 층 없을 때: `WH001-A구역-01-1` (층 부분 없이 깔끔)

### 5. 중복 체크는 가용 필드 기준으로 수행

- **결정**: floor 없으면 `warehouse_code + zone`으로 중복 체크, floor 있으면 `warehouse_code + floor + zone`으로 중복 체크
- **근거**: 기존 코드는 floor 없으면 중복 체크 전체를 건너뜀 → 중복 데이터 발생 위험. 가용 필드 기준으로 체크하면 floor 유무와 관계없이 안전

### 6. 렉 구조 화면 감지에서 floor 조건 제거

- **결정**: `buttonActions.ts`의 `isRackStructureScreen` 조건에서 `context.formData?.floor` 제거
- **근거**: floor 없으면 렉 구조 화면으로 인식되지 않아 일반 단건 저장으로 빠짐 → 예기치 않은 동작. zone만으로 감지해야 floor 미선택 시에도 렉 구조 일괄 저장이 정상 동작

---

## 관련 파일 위치

| 구분 | 파일 경로 | 설명 |
|------|----------|------|
| 수정 대상 | `frontend/lib/registry/components/v2-rack-structure/RackStructureComponent.tsx` | 필수 검증, 위치 코드 생성, 기존 데이터 조회 |
| 수정 대상 | `frontend/lib/utils/buttonActions.ts` | 화면 감지, 중복 체크 |
| 타입 정의 | `frontend/lib/registry/components/v2-rack-structure/types.ts` | RackStructureContext, FieldMapping 등 |
| 설정 패널 | `frontend/lib/registry/components/v2-rack-structure/RackStructureConfigPanel.tsx` | 필드 매핑 설정 (이번에 수정 안 함) |
| 저장 모달 | `frontend/components/screen/SaveModal.tsx` | 필수 검증 (DB NOT NULL 기반, 별도 확인 필요) |
| 사전 확인 | DB `warehouse_location.floor` 컬럼 | NULL 허용 여부 확인, NOT NULL이면 ALTER TABLE 필요 |

---

## 기술 참고

### 수정 포인트 6곳 요약

| # | 파일 | 행 | 내용 | 수정 방향 |
|---|------|-----|------|----------|
| 1 | RackStructureComponent.tsx | 291~298 | missingFields에서 floor 체크 | floor 체크 제거 |
| 2 | RackStructureComponent.tsx | 517~521 | 미리보기 생성 차단 | 1번 수정으로 자동 해결 |
| 3 | RackStructureComponent.tsx | 497~513 | 위치 코드 생성 `floor \|\| "1"` | 폴백값 제거, 없으면 생략 |
| 4 | RackStructureComponent.tsx | 378~432 | 기존 데이터 조회 조건 | floor 없어도 조회 가능하게 |
| 5 | buttonActions.ts | 692~698 | 렉 구조 화면 감지 | floor 조건 제거 |
| 6 | buttonActions.ts | 2085~2131 | 저장 전 중복 체크 | floor 조건부로 포함 |

### 프로젝트 표준 optional 필드 처리 패턴

```
빈 값 → null 변환:  value || null (UserFormModal)
nullable 자동 변환:  value === "" && isNullable === "Y" → null (EnhancedFormService)
Select placeholder:  "__none__" → "" 또는 undefined (여러 ConfigPanel)
```

이번 변경은 위 패턴들과 일관성을 유지합니다.
