Files
sam-react-prod/claudedocs/item-master/[REF-2025-11-26] item-master-hooks-refactoring.md
byeongcheolryu 65a8510c0b fix: 품목기준관리 실시간 동기화 수정
- BOM 항목 추가/수정/삭제 시 섹션탭 즉시 반영
- 섹션 복제 시 UI 즉시 업데이트 (null vs undefined 이슈 해결)
- 항목 수정 기능 추가 (useTemplateManagement)
- 실시간 동기화 문서 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 22:19:50 +09:00

446 lines
14 KiB
Markdown

# ItemMasterDataManagement 훅 분리 리팩토링
## 개요
- **목표**: 2000줄+ 컴포넌트를 도메인별 커스텀 훅으로 분리
- **예상 결과**: 메인 컴포넌트 ~200줄로 축소 (90% 감소)
- **시작일**: 2025-11-26
## 진행 상태
### Phase 1: 커스텀 훅 생성 ✅ 완료
| # | 훅 이름 | 상태 수 | 핸들러 수 | 상태 | 비고 |
|---|---------|---------|----------|------|------|
| 1 | usePageManagement | ~8 | 3 | [x] 완료 | 가장 단순, 먼저 시작 |
| 2 | useSectionManagement | ~10 | 5 | [x] 완료 | Page에 의존 |
| 3 | useFieldManagement | ~15 | 4 | [x] 완료 | Section에 의존 |
| 4 | useMasterFieldManagement | ~12 | 4 | [x] 완료 | 독립적 |
| 5 | useTemplateManagement | ~18 | 11 | [x] 완료 | 가장 복잡 (BOM 포함) |
| 6 | useAttributeManagement | ~15 | 6 | [x] 완료 | 옵션/칼럼 관리 |
| 7 | useTabManagement | ~12 | 14 | [x] 완료 | 탭 상태 관리 |
### Phase 2: 메인 컴포넌트 정리 ✅ 완료
| # | 작업 | 상태 | 비고 |
|---|------|------|------|
| 2.1 | 훅 import 추가 | [x] 완료 | 7개 훅 import |
| 2.2 | 훅 초기화 코드 추가 | [x] 완료 | 컴포넌트 상단에 훅 호출 |
| 2.3 | useState 제거 - 페이지 관련 | [x] 완료 | usePageManagement로 대체 |
| 2.4 | useState 제거 - 섹션 관련 | [x] 완료 | useSectionManagement로 대체 |
| 2.5 | useState 제거 - 필드 관련 | [x] 완료 | useFieldManagement로 대체 |
| 2.6 | useState 제거 - 마스터필드 관련 | [x] 완료 | useMasterFieldManagement로 대체 |
| 2.7 | useState 제거 - 템플릿 관련 | [x] 완료 | useTemplateManagement로 대체 |
| 2.8 | useState 제거 - 속성 관련 | [x] 완료 | useAttributeManagement로 대체 |
| 2.9 | useState 제거 - 탭 관련 | [x] 완료 | useTabManagement로 대체 |
| 2.10 | 핸들러 함수 제거 | [x] 완료 | 훅에서 가져온 핸들러로 대체 |
| 2.11 | useEffect 제거 | [x] 완료 | 훅 내부로 이동된 것들 |
| 2.12 | 하위 컴포넌트 props 연결 | [x] 완료 | 다이얼로그/탭 컴포넌트에 훅 값 전달 + wrapper 함수 |
| 2.13 | 타입 체크 | [x] 완료 | 기존 타입 에러만 남음 (훅과 무관) |
| 2.14 | 빌드 테스트 | [x] 완료 | npm run build 성공! |
| 2.15 | 기능 테스트 | [ ] 대기 | 브라우저에서 동작 확인 필요 |
---
## Phase 2 상세 가이드
### 2.1 훅 Import 추가
```typescript
// ItemMasterDataManagement.tsx 상단에 추가
import {
usePageManagement,
useSectionManagement,
useFieldManagement,
useMasterFieldManagement,
useTemplateManagement,
useAttributeManagement,
useTabManagement,
} from './ItemMasterDataManagement/hooks';
```
### 2.2 훅 초기화 코드
```typescript
// 컴포넌트 함수 내부 상단에 추가
export function ItemMasterDataManagement() {
const pageManagement = usePageManagement();
const sectionManagement = useSectionManagement();
const fieldManagement = useFieldManagement();
const masterFieldManagement = useMasterFieldManagement();
const templateManagement = useTemplateManagement();
const attributeManagement = useAttributeManagement();
const tabManagement = useTabManagement();
// ... 기존 코드
}
```
### 2.3~2.9 useState 제거 패턴
**변경 전:**
```typescript
const [selectedPageId, setSelectedPageId] = useState<number | null>(null);
```
**변경 후:**
```typescript
const { selectedPageId, setSelectedPageId } = pageManagement;
// 또는 구조분해 없이 pageManagement.selectedPageId 사용
```
### 2.10 핸들러 교체 패턴
**변경 전:**
```typescript
const handleAddPage = async () => {
// 100줄의 핸들러 코드
};
```
**변경 후:**
```typescript
// 삭제하고, pageManagement.handleAddPage 사용
// 또는 상단에서 구조분해
const { handleAddPage } = pageManagement;
```
### 2.12 하위 컴포넌트 Props 연결 예시
```typescript
<PageDialog
isOpen={pageManagement.isPageDialogOpen}
onClose={() => pageManagement.setIsPageDialogOpen(false)}
onSubmit={pageManagement.handleAddPage}
pageName={pageManagement.newPageName}
setPageName={pageManagement.setNewPageName}
// ...
/>
```
### Phase 2 완료 기준 (실제 결과)
- [x] 메인 컴포넌트 줄 수: 2893줄 → 1575줄 (45% 감소) *목표는 90%였으나 렌더링 로직이 많아 45% 달성*
- [x] 모든 useState가 훅으로 이동 (핵심 상태 ~100개)
- [x] 모든 핸들러가 훅에서 제공 (~50개 핸들러)
- [x] 타입 에러: 훅 관련 새 에러 없음 (기존 에러만 존재)
- [x] 빌드 성공
- [ ] 기능 동작 정상 (브라우저 테스트 대기)
---
## 상세 작업 내역
### 1. usePageManagement
**포함될 상태:**
```typescript
- selectedPageId
- editingPageId
- editingPageName
- isPageDialogOpen
- newPageName
- newPageItemType
- editingPathPageId
- editingAbsolutePath
```
**포함될 핸들러:**
```typescript
- handleAddPage
- handleDuplicatePage
- handleDeletePageWithTracking
```
**작업 체크리스트:**
- [ ] hooks/usePageManagement.ts 파일 생성
- [ ] 상태 이동
- [ ] 핸들러 이동
- [ ] 메인 컴포넌트에서 훅 사용으로 변경
- [ ] 기능 테스트
---
### 2. useSectionManagement
**포함될 상태:**
```typescript
- editingSectionId
- editingSectionTitle
- isSectionDialogOpen
- newSectionTitle
- newSectionDescription
- newSectionType
- sectionInputMode
- selectedSectionTemplateId
- expandedSections
```
**포함될 핸들러:**
```typescript
- handleAddSection
- handleLinkTemplate
- handleEditSectionTitle
- handleSaveSectionTitle
- handleDeleteSectionWithTracking
```
**작업 체크리스트:**
- [ ] hooks/useSectionManagement.ts 파일 생성
- [ ] 상태 이동
- [ ] 핸들러 이동
- [ ] 메인 컴포넌트에서 훅 사용으로 변경
- [ ] 기능 테스트
---
### 3. useFieldManagement
**포함될 상태:**
```typescript
- isFieldDialogOpen
- selectedSectionForField
- editingFieldId
- fieldInputMode
- showMasterFieldList
- selectedMasterFieldId
- newFieldName, newFieldKey, newFieldInputType, newFieldRequired
- newFieldOptions, newFieldDescription
- textboxColumns, isColumnDialogOpen, editingColumnId, columnName, columnKey
- newFieldConditionEnabled, newFieldConditionTargetType
- newFieldConditionFields, newFieldConditionSections
- tempConditionFieldKey, tempConditionValue
```
**포함될 핸들러:**
```typescript
- handleAddField
- handleEditField
- handleDeleteFieldWithTracking
- (useEffect for masterField selection)
```
**작업 체크리스트:**
- [ ] hooks/useFieldManagement.ts 파일 생성
- [ ] 상태 이동
- [ ] 핸들러 이동
- [ ] 메인 컴포넌트에서 훅 사용으로 변경
- [ ] 기능 테스트
---
### 4. useMasterFieldManagement
**포함될 상태:**
```typescript
- isMasterFieldDialogOpen
- editingMasterFieldId
- newMasterFieldName, newMasterFieldKey, newMasterFieldInputType
- newMasterFieldRequired, newMasterFieldCategory, newMasterFieldDescription
- newMasterFieldOptions, newMasterFieldAttributeType
- newMasterFieldMultiColumn, newMasterFieldColumnCount, newMasterFieldColumnNames
```
**포함될 핸들러:**
```typescript
- handleAddMasterField
- handleEditMasterField
- handleUpdateMasterField
- handleDeleteMasterField
```
**작업 체크리스트:**
- [ ] hooks/useMasterFieldManagement.ts 파일 생성
- [ ] 상태 이동
- [ ] 핸들러 이동
- [ ] 메인 컴포넌트에서 훅 사용으로 변경
- [ ] 기능 테스트
---
### 5. useTemplateManagement
**포함될 상태:**
```typescript
- isSectionTemplateDialogOpen
- editingSectionTemplateId
- newSectionTemplateTitle, newSectionTemplateDescription
- newSectionTemplateCategory, newSectionTemplateType
- isLoadTemplateDialogOpen, selectedTemplateId
- expandedTemplateId
- isTemplateFieldDialogOpen, currentTemplateId, editingTemplateFieldId
- templateFieldName, templateFieldKey, templateFieldInputType
- templateFieldRequired, templateFieldOptions, templateFieldDescription
- templateFieldMultiColumn, templateFieldColumnCount, templateFieldColumnNames
- templateFieldInputMode, templateFieldShowMasterFieldList, templateFieldSelectedMasterFieldId
```
**포함될 핸들러:**
```typescript
- handleAddSectionTemplate
- handleEditSectionTemplate
- handleUpdateSectionTemplate
- handleDeleteSectionTemplate
- handleLoadTemplate
- handleAddTemplateField
- handleEditTemplateField
- handleDeleteTemplateField
- handleAddBOMItemToTemplate
- handleUpdateBOMItemInTemplate
- handleDeleteBOMItemFromTemplate
```
**작업 체크리스트:**
- [ ] hooks/useTemplateManagement.ts 파일 생성
- [ ] 상태 이동
- [ ] 핸들러 이동
- [ ] 메인 컴포넌트에서 훅 사용으로 변경
- [ ] 기능 테스트
---
### 6. useAttributeManagement
**포함될 상태:**
```typescript
- unitOptions, materialOptions, surfaceTreatmentOptions
- customAttributeOptions
- isOptionDialogOpen, editingOptionType
- newOptionValue, newOptionLabel, newOptionColumnValues
- newOptionInputType, newOptionRequired, newOptionOptions
- newOptionPlaceholder, newOptionDefaultValue
- isColumnManageDialogOpen, managingColumnType
- attributeColumns
- newColumnName, newColumnKey, newColumnType, newColumnRequired
```
**포함될 핸들러:**
```typescript
- handleAddOption
- handleDeleteOption
- (useEffect for attribute sync)
```
**작업 체크리스트:**
- [ ] hooks/useAttributeManagement.ts 파일 생성
- [ ] 상태 이동
- [ ] 핸들러 이동
- [ ] 메인 컴포넌트에서 훅 사용으로 변경
- [ ] 기능 테스트
---
### 7. useTabManagement
**포함될 상태:**
```typescript
- customTabs
- activeTab
- attributeSubTabs, activeAttributeTab
- isAddTabDialogOpen, isManageTabsDialogOpen
- newTabLabel, editingTabId, deletingTabId, isDeleteTabDialogOpen
- isManageAttributeTabsDialogOpen, isAddAttributeTabDialogOpen
- newAttributeTabLabel, editingAttributeTabId
- deletingAttributeTabId, isDeleteAttributeTabDialogOpen
```
**포함될 핸들러:**
```typescript
- handleAddTab
- handleEditTab
- handleDeleteTab
- handleAddAttributeTab
- (useEffect for attributeSubTabs sync)
```
**작업 체크리스트:**
- [ ] hooks/useTabManagement.ts 파일 생성
- [ ] 상태 이동
- [ ] 핸들러 이동
- [ ] 메인 컴포넌트에서 훅 사용으로 변경
- [ ] 기능 테스트
---
## 작업 로그
### 2025-11-26
- 체크리스트 문서 생성
- 분석 완료: 총 7개 훅으로 분리 예정
- ✅ usePageManagement.ts 생성 완료 (타입 에러 없음)
- ✅ useSectionManagement.ts 생성 완료 (타입 에러 없음)
- ✅ useFieldManagement.ts 생성 완료 (타입 에러 수정 완료)
- ✅ useMasterFieldManagement.ts 생성 완료 (타입 에러 수정: 'ㄹ' 오타 제거)
- ✅ useTemplateManagement.ts 생성 완료 (타입 에러 없음, ~350줄)
- ✅ useAttributeManagement.ts 생성 완료 (타입 에러 없음, ~250줄)
- ✅ useTabManagement.ts 생성 완료 (타입 에러 없음, ~330줄)
- 🎉 **Phase 1 완료!** 모든 7개 훅 생성 완료
- 📁 hooks/index.ts에 모든 훅 export 완료
### Phase 2 완료 (2025-11-26 추가)
- ✅ 메인 컴포넌트에서 훅 import 및 연결 완료
- ✅ props drilling 정리 - wrapper 함수 패턴 적용
- ✅ 렌더링 로직만 남기기 - 2893줄 → 1575줄 (45% 감소)
- ✅ 빌드 테스트 성공
- ⏳ 기능 테스트 - 브라우저에서 확인 필요
### 주요 기술 결정 (Phase 2)
1. **Wrapper 함수 패턴**: 훅 함수에 selectedPage 바인딩 필요한 경우 wrapper 사용
- `handleAddSectionWrapper`, `handleLinkTemplateWrapper`
2. **타입 호환성**: setter 함수 타입 불일치는 `as any`로 우회
- `setNewSectionTypeWrapper`, `setNewPageItemTypeWrapper`
3. **기존 타입 에러**: `default_properties` 등 기존 타입 정의 문제는 Phase 2 범위 외
### 다음 단계
- [ ] 기능 테스트 (브라우저)
- [ ] 추가 최적화 (선택)
---
## 참고 사항
### 훅 간 의존성
```
usePageManagement (독립)
useSectionManagement (selectedPageId 필요)
useFieldManagement (selectedSectionId 필요)
useMasterFieldManagement (독립)
useTemplateManagement (독립, but masterFields 참조)
useAttributeManagement (독립, but masterFields와 연동)
useTabManagement (독립)
```
### 파일 구조 (목표)
```
ItemMasterDataManagement/
├── hooks/
│ ├── index.ts
│ ├── usePageManagement.ts
│ ├── useSectionManagement.ts
│ ├── useFieldManagement.ts
│ ├── useMasterFieldManagement.ts
│ ├── useTemplateManagement.ts
│ ├── useAttributeManagement.ts
│ └── useTabManagement.ts
├── tabs/
├── dialogs/
├── components/
├── utils/
├── types.ts
└── index.tsx (메인 컴포넌트, ~200줄 목표)
```
---
## 관련 파일
### 프론트엔드
- `src/components/items/ItemMasterDataManagement.tsx` - 메인 컴포넌트 (리팩토링 대상)
- `src/components/items/ItemMasterDataManagement/hooks/index.ts` - 훅 export
- `src/components/items/ItemMasterDataManagement/hooks/usePageManagement.ts` - 페이지 관리 훅
- `src/components/items/ItemMasterDataManagement/hooks/useSectionManagement.ts` - 섹션 관리 훅
- `src/components/items/ItemMasterDataManagement/hooks/useFieldManagement.ts` - 필드 관리 훅
- `src/components/items/ItemMasterDataManagement/hooks/useMasterFieldManagement.ts` - 마스터 필드 훅
- `src/components/items/ItemMasterDataManagement/hooks/useTemplateManagement.ts` - 템플릿 관리 훅
- `src/components/items/ItemMasterDataManagement/hooks/useAttributeManagement.ts` - 속성 관리 훅
- `src/components/items/ItemMasterDataManagement/hooks/useTabManagement.ts` - 탭 관리 훅
- `src/contexts/ItemMasterContext.tsx` - Context Provider
### 참조 문서
- `claudedocs/item-master/[NEXT-2025-11-26] item-master-api-pending-tasks.md` - API 연동 작업 체크리스트