fix: 페이지 삭제 시 섹션 동기화 및 코드 정리
- 페이지 삭제 시 독립 섹션 목록 갱신 추가 (독립 엔티티 아키텍처) - ItemForm 컴포넌트 분리 완료 (1607→415줄, 74% 감소) - ItemMasterDataManagement 중복 코드 제거 (getInputTypeLabel 헬퍼) - 문서 업데이트 (realtime-sync-fixes.md) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# claudedocs 문서 맵
|
||||
|
||||
> 프로젝트 기술 문서 인덱스 (Last Updated: 2025-11-27)
|
||||
> 프로젝트 기술 문서 인덱스 (Last Updated: 2025-11-28)
|
||||
|
||||
## 폴더 구조
|
||||
|
||||
@@ -39,7 +39,9 @@ claudedocs/
|
||||
|
||||
| 파일 | 설명 |
|
||||
|------|------|
|
||||
| `[IMPL-2025-11-27] realtime-sync-fixes.md` | ⭐ **최신** - 실시간 동기화 수정 (BOM, 섹션 복제, 항목 수정) |
|
||||
| `[API-REQUEST-2025-11-28] dynamic-page-rendering-api.md` | ⭐ **최신** - 동적 페이지 렌더링 API 요청서 |
|
||||
| `[PLAN-2025-11-27] item-form-component-separation.md` | ✅ **완료** - ItemForm 컴포넌트 분리 (1607→415줄, 74% 감소) |
|
||||
| `[IMPL-2025-11-27] realtime-sync-fixes.md` | 실시간 동기화 수정 (BOM, 섹션 복제, 항목 수정, **페이지 삭제 시 섹션 동기화** 2025-11-28) |
|
||||
| `item-master-api-pending-tasks.md` | 진행중인 API 연동 작업 |
|
||||
| `item-master-pending-integration.md` | 대기중인 통합 작업 |
|
||||
| `item-master-specification.md` | API 명세 |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -171,11 +171,84 @@ console.log('[ItemMasterDataManagement] 📋 sectionsAsTemplates changed:', {...
|
||||
|
||||
---
|
||||
|
||||
### 4. 페이지 삭제 시 섹션 동기화 (`ItemMasterContext.tsx`) - 2025-11-28
|
||||
|
||||
**문제**: 계층구조에서 페이지 삭제 시 연결된 섹션들이 섹션탭에서 사라짐
|
||||
|
||||
**예상 동작**: 페이지 삭제 → 연결된 섹션은 unlink만 되고 독립 섹션으로 복귀 → 섹션탭에서 표시
|
||||
|
||||
**실제 동작**: 페이지 삭제 → 섹션이 UI에서 완전히 사라짐 (삭제된 것처럼 보임)
|
||||
|
||||
**원인 분석**:
|
||||
1. **백엔드는 정상**: `ItemPageService.php`의 `destroy()` 메서드가 독립 엔티티 아키텍처 준수
|
||||
- `entity_relationships`에서 페이지-섹션 관계만 삭제 (섹션 자체는 유지)
|
||||
- 섹션/필드는 독립 엔티티로 계속 존재
|
||||
2. **프론트엔드 상태 동기화 누락**:
|
||||
- `deleteItemPage`가 `setItemPages`만 업데이트
|
||||
- `independentSections` 상태는 갱신 안 됨
|
||||
- `sectionsAsTemplates` useMemo가 `[itemPages, independentSections]` 의존
|
||||
- 결과: 섹션이 `itemPages`에서 제거되었지만 `independentSections`에도 없어서 UI에서 사라짐
|
||||
|
||||
**해결**: 페이지 삭제 후 `refreshIndependentSections()` 호출 추가
|
||||
|
||||
```typescript
|
||||
// deleteItemPage 함수 수정
|
||||
const deleteItemPage = async (id: number) => {
|
||||
try {
|
||||
const response = await itemMasterApi.pages.delete(id);
|
||||
|
||||
if (!response.success) {
|
||||
throw new Error(response.message || '페이지 삭제 실패');
|
||||
}
|
||||
|
||||
// state 업데이트
|
||||
setItemPages(prev => prev.filter(page => page.id !== id));
|
||||
|
||||
// 2025-11-28: 페이지 삭제 후 독립 섹션 목록 갱신
|
||||
// 백엔드에서 섹션은 삭제되지 않고 연결만 해제되므로 (독립 엔티티 아키텍처)
|
||||
// 독립 섹션 목록을 새로고침해야 섹션 탭에서 해당 섹션이 표시됨
|
||||
try {
|
||||
await refreshIndependentSections();
|
||||
console.log('[ItemMasterContext] 페이지 삭제 후 독립 섹션 갱신 완료');
|
||||
} catch (refreshError) {
|
||||
// 갱신 실패해도 페이지 삭제는 성공한 상태이므로 경고만 출력
|
||||
console.warn('[ItemMasterContext] 독립 섹션 갱신 실패:', refreshError);
|
||||
}
|
||||
|
||||
console.log('[ItemMasterContext] 페이지 삭제 성공:', id);
|
||||
} catch (error) {
|
||||
// ...
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**백엔드 코드 참조** (`ItemPageService.php:95-129`):
|
||||
```php
|
||||
/**
|
||||
* 페이지 삭제 (Soft Delete)
|
||||
* 독립 엔티티 아키텍처: 페이지만 삭제하고 연결된 섹션/필드는 unlink만 수행
|
||||
*/
|
||||
public function destroy(int $id): void
|
||||
{
|
||||
// 1. entity_relationships에서 이 페이지의 모든 자식 관계 해제
|
||||
EntityRelationship::where('parent_type', EntityRelationship::TYPE_PAGE)
|
||||
->where('parent_id', $id)
|
||||
->where('is_locked', false)
|
||||
->delete();
|
||||
|
||||
// 2. 페이지만 Soft Delete (섹션/필드는 독립 엔티티로 유지)
|
||||
$page->update(['deleted_by' => $userId]);
|
||||
$page->delete();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 수정된 파일 목록
|
||||
|
||||
| 파일 | 수정 내용 |
|
||||
|---|---|
|
||||
| `src/contexts/ItemMasterContext.tsx` | BOM 동기화, 섹션 복제 수정 |
|
||||
| `src/contexts/ItemMasterContext.tsx` | BOM 동기화, 섹션 복제 수정, **페이지 삭제 시 독립 섹션 갱신 (2025-11-28)** |
|
||||
| `src/components/items/ItemMasterDataManagement/hooks/useTemplateManagement.ts` | 항목 수정 로직 추가 |
|
||||
| `src/components/items/ItemMasterDataManagement/dialogs/TemplateFieldDialog.tsx` | prop 타입 수정 (void → void \| Promise<void>) |
|
||||
|
||||
@@ -185,4 +258,8 @@ console.log('[ItemMasterDataManagement] 📋 sectionsAsTemplates changed:', {...
|
||||
|
||||
1. **양방향 동기화 필수**: 데이터 변경 시 `itemPages`와 `independentSections` 모두 업데이트해야 함
|
||||
2. **null vs undefined**: API 응답의 null 값이 transformer 거치면서 undefined로 바뀔 수 있음 → `== null` 사용 권장
|
||||
3. **useMemo 의존성**: `sectionsAsTemplates`의 의존성 배열 확인 → 두 상태가 모두 업데이트되어야 재계산됨
|
||||
3. **useMemo 의존성**: `sectionsAsTemplates`의 의존성 배열 확인 → 두 상태가 모두 업데이트되어야 재계산됨
|
||||
4. **독립 엔티티 아키텍처 인지**: 페이지/섹션/필드는 각각 독립 엔티티이며 `entity_relationships`로 연결됨
|
||||
- 페이지 삭제 시 → 섹션은 삭제 안 됨 (연결만 해제) → `refreshIndependentSections()` 필요
|
||||
- 섹션 삭제 시 → 필드는 삭제 안 됨 (연결만 해제) → `refreshIndependentFields()` 필요 (해당 시)
|
||||
- 프론트엔드에서 연결 해제된 엔티티들이 적절히 표시되도록 상태 갱신 필수
|
||||
@@ -1,6 +1,14 @@
|
||||
# ItemForm.tsx 컴포넌트 분리 계획
|
||||
|
||||
## 작업 일자: 2025-11-27 (분석)
|
||||
## 작업 일자: 2025-11-27 (분석) → 2025-11-28 (완료)
|
||||
|
||||
## ✅ 최종 결과 요약
|
||||
|
||||
| 항목 | Before | After | 감소율 |
|
||||
|------|--------|-------|--------|
|
||||
| **index.tsx** | 1,607줄 | **415줄** | **74%** |
|
||||
| **useState 수** | 25개+ | **0개** (훅으로 이동) | **100%** |
|
||||
| **파일 수** | 1개 | **21개** | 모듈화 완료 |
|
||||
|
||||
---
|
||||
|
||||
@@ -264,13 +272,55 @@ src/components/items/ItemForm/
|
||||
### Phase 5: 훅 & 컨텍스트 ✅ 완료 (2025-11-27)
|
||||
- [x] context/ItemFormContext.tsx 생성 (~80줄)
|
||||
- [x] context/index.ts export 파일 생성
|
||||
- [x] hooks/useItemFormState.ts 생성 (~280줄) - 25+ useState 통합
|
||||
- [x] hooks/useItemFormState.ts 생성 (~364줄) - 25+ useState 통합
|
||||
- [x] hooks/useBOMManagement.ts 생성 (~180줄) - BOM 라인 관리
|
||||
- [x] hooks/useBendingDetails.ts 생성 (~150줄) - 전개도 계산
|
||||
- [x] hooks/index.ts export 파일 생성
|
||||
|
||||
### Phase 6: 테스트 & 검증
|
||||
### Phase 6: index.tsx에 훅 적용 ✅ 완료 (2025-11-28)
|
||||
- [x] useItemFormState 훅을 index.tsx에 적용
|
||||
- [x] 25+ useState → 훅에서 구조 분해 할당
|
||||
- [x] handleItemTypeChange → resetAllStates 헬퍼 함수 활용
|
||||
- [x] 미사용 import 정리
|
||||
- [x] 빌드 테스트 통과
|
||||
|
||||
### Phase 7: 테스트 & 검증 (추후 진행)
|
||||
- [ ] 모든 품목 유형 등록 테스트
|
||||
- [ ] 수정 모드 테스트
|
||||
- [ ] 폼 검증 테스트
|
||||
- [ ] BOM 추가/삭제 테스트
|
||||
- [ ] BOM 추가/삭제 테스트
|
||||
|
||||
---
|
||||
|
||||
## 9. 최종 파일 구조
|
||||
|
||||
```
|
||||
src/components/items/ItemForm/
|
||||
├── index.tsx (415줄) ← 1,607줄에서 74% 감소
|
||||
├── constants.ts (72줄)
|
||||
├── types.ts (50줄)
|
||||
├── ValidationAlert.tsx (45줄)
|
||||
├── FormHeader.tsx (63줄)
|
||||
├── BendingDiagramSection.tsx (~300줄)
|
||||
├── BOMSection.tsx (~280줄)
|
||||
├── context/
|
||||
│ ├── ItemFormContext.tsx (~80줄)
|
||||
│ └── index.ts
|
||||
├── hooks/
|
||||
│ ├── useItemFormState.ts (364줄) ← 상태 관리 통합
|
||||
│ ├── useBOMManagement.ts (~180줄)
|
||||
│ ├── useBendingDetails.ts (~150줄)
|
||||
│ └── index.ts
|
||||
└── forms/
|
||||
├── index.ts
|
||||
├── ProductForm.tsx (~120줄)
|
||||
├── MaterialForm.tsx (~350줄)
|
||||
├── PartForm.tsx (~273줄)
|
||||
└── parts/
|
||||
├── index.ts
|
||||
├── AssemblyPartForm.tsx (~300줄)
|
||||
├── BendingPartForm.tsx (~280줄)
|
||||
└── PurchasedPartForm.tsx (~270줄)
|
||||
```
|
||||
|
||||
**총 21개 파일로 모듈화 완료**
|
||||
Reference in New Issue
Block a user