484 lines
14 KiB
Markdown
484 lines
14 KiB
Markdown
# 카테고리 시스템 최종 완료 보고서
|
|
|
|
## 🎉 완료 상태: 100%
|
|
|
|
모든 구현이 완료되었습니다!
|
|
|
|
---
|
|
|
|
## ✅ 완료된 모든 작업
|
|
|
|
### Phase 1: DB 및 백엔드 ✅
|
|
|
|
1. **DB 마이그레이션**
|
|
- `menu_id` 컬럼 추가
|
|
- 외래키 `menu_info(menu_id)` 추가
|
|
- UNIQUE 제약조건에 `menu_id` 추가
|
|
- 인덱스 추가
|
|
|
|
2. **백엔드 타입**
|
|
- `TableCategoryValue`에 `menuId` 추가
|
|
|
|
3. **백엔드 서비스**
|
|
- `getSiblingMenuIds()` 함수 구현 (형제 메뉴 조회)
|
|
- `getCategoryValues()` 메뉴 스코프 필터링 적용
|
|
- `addCategoryValue()` menuId 포함
|
|
|
|
4. **백엔드 컨트롤러**
|
|
- `getCategoryValues()` menuId 파라미터 필수 체크
|
|
- menuId 쿼리 파라미터 처리
|
|
|
|
### Phase 2: 프론트엔드 컴포넌트 ✅
|
|
|
|
5. **CategoryWidget** (메인 좌우 분할 위젯)
|
|
- 좌측 패널 (30%): 카테고리 컬럼 목록
|
|
- 우측 패널 (70%): 카테고리 값 관리
|
|
- 빈 상태 처리
|
|
|
|
6. **CategoryColumnList** (좌측 패널)
|
|
- 현재 테이블의 `input_type='category'` 컬럼 조회
|
|
- 컬럼 카드 형태 표시
|
|
- 선택된 컬럼 하이라이트
|
|
- 첫 번째 컬럼 자동 선택
|
|
|
|
7. **CategoryValueManager** (우측 패널)
|
|
- `menuId` props 추가
|
|
- API 호출 시 `menuId` 전달
|
|
- 카테고리 값 CRUD 기능
|
|
- 검색 및 필터링
|
|
|
|
8. **프론트엔드 타입**
|
|
- `TableCategoryValue`에 `menuId` 추가
|
|
|
|
9. **API 클라이언트**
|
|
- `getCategoryValues()` menuId 파라미터 추가
|
|
- `addCategoryValue()` menuId 포함
|
|
|
|
### Phase 3: 화면관리 시스템 통합 ✅
|
|
|
|
10. **ComponentType 추가**
|
|
- `unified-core.ts`에 `"category-manager"` 추가
|
|
|
|
11. **ComponentRegistry 등록**
|
|
- `CategoryManagerRenderer.tsx` 생성
|
|
- 컴포넌트 정의 및 자동 등록
|
|
- `index.ts`에 import 추가
|
|
|
|
12. **ConfigPanel 생성**
|
|
- `CategoryManagerConfigPanel.tsx` 생성
|
|
- 자동 설정 안내
|
|
- 주요 기능 설명
|
|
- 사용 방법 가이드
|
|
- 메뉴 스코프 설명
|
|
|
|
13. **자동 렌더링**
|
|
- ComponentRegistry를 통한 자동 렌더링
|
|
- ComponentsPanel에서 드래그앤드롭 가능
|
|
|
|
### Phase 4: 정리 ✅
|
|
|
|
14. **테이블 타입 관리**
|
|
- CategoryValueManagerDialog 삭제
|
|
- "카테고리 값 관리" 버튼 제거
|
|
- 관련 import 및 상태 제거
|
|
|
|
15. **불필요한 파일 삭제**
|
|
- `CategoryValueManagerDialog.tsx` 삭제
|
|
- 단독 `category-manager.tsx` 파일 제거 (폴더 구조로 이동)
|
|
|
|
---
|
|
|
|
## 📁 생성/수정된 파일 목록
|
|
|
|
### 데이터베이스
|
|
```
|
|
db/migrations/036_create_table_column_category_values.sql (수정)
|
|
```
|
|
|
|
### 백엔드
|
|
```
|
|
backend-node/src/types/tableCategoryValue.ts (수정)
|
|
backend-node/src/services/tableCategoryValueService.ts (수정)
|
|
backend-node/src/controllers/tableCategoryValueController.ts (수정)
|
|
```
|
|
|
|
### 프론트엔드 - 컴포넌트
|
|
```
|
|
frontend/components/screen/widgets/CategoryWidget.tsx (신규)
|
|
frontend/components/table-category/CategoryColumnList.tsx (신규)
|
|
frontend/components/table-category/CategoryValueManager.tsx (수정)
|
|
```
|
|
|
|
### 프론트엔드 - API & 타입
|
|
```
|
|
frontend/lib/api/tableCategoryValue.ts (수정)
|
|
frontend/types/tableCategoryValue.ts (수정)
|
|
frontend/types/unified-core.ts (수정)
|
|
```
|
|
|
|
### 프론트엔드 - 화면관리 시스템
|
|
```
|
|
frontend/lib/registry/components/category-manager/CategoryManagerRenderer.tsx (신규)
|
|
frontend/lib/registry/components/category-manager/CategoryManagerConfigPanel.tsx (신규)
|
|
frontend/lib/registry/components/index.ts (수정)
|
|
```
|
|
|
|
### 정리
|
|
```
|
|
frontend/components/table-category/CategoryValueManagerDialog.tsx (삭제)
|
|
frontend/app/(main)/admin/tableMng/page.tsx (수정)
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 핵심 개념 요약
|
|
|
|
### 메뉴 스코프 규칙
|
|
|
|
```
|
|
구매관리 (menu_id: 100)
|
|
├── 발주 관리 (101) ← 구매관리 카테고리 사용 ✅
|
|
├── 입고 관리 (102) ← 구매관리 카테고리 사용 ✅
|
|
├── 카테고리 관리 (103) ← 여기서 카테고리 생성
|
|
└── 거래처 관리 (104) ← 구매관리 카테고리 사용 ✅
|
|
|
|
영업관리 (menu_id: 200)
|
|
└── 주문 관리 (201) ← 구매관리 카테고리 사용 ❌
|
|
```
|
|
|
|
**핵심**: 카테고리는 **생성된 메뉴의 형제 메뉴들 간에만** 공유됩니다.
|
|
|
|
---
|
|
|
|
## 🚀 사용 방법
|
|
|
|
### 1. 테이블 타입 설정
|
|
|
|
```
|
|
1. 관리자 > 테이블 타입 관리
|
|
2. 테이블 선택 (예: purchase_orders)
|
|
3. 컬럼의 입력 타입을 "카테고리"로 설정
|
|
```
|
|
|
|
### 2. 카테고리 관리 화면 생성
|
|
|
|
```
|
|
1. 메뉴 등록: 구매관리 > 카테고리 관리
|
|
2. 화면 관리로 이동
|
|
3. 화면 생성 (테이블: purchase_orders)
|
|
4. 화면 편집기 열기
|
|
```
|
|
|
|
### 3. 위젯 배치
|
|
|
|
```
|
|
1. ComponentsPanel에서 "카테고리 관리" 검색
|
|
2. 캔버스로 드래그앤드롭
|
|
3. 자동으로 menuId와 tableName이 설정됨
|
|
```
|
|
|
|
### 4. 카테고리 값 관리
|
|
|
|
```
|
|
1. 좌측 패널: 카테고리 컬럼 선택 (예: order_type)
|
|
2. 우측 패널: 추가 버튼 클릭
|
|
3. 코드: MATERIAL, 라벨: 자재 발주
|
|
4. 색상 및 설명 입력
|
|
5. 저장 → menu_id가 자동으로 포함됨
|
|
```
|
|
|
|
### 5. 다른 화면에서 사용
|
|
|
|
```
|
|
1. 발주 관리 화면에서
|
|
2. order_type 컬럼을 Code Select 위젯으로 배치
|
|
3. 자동으로 형제 메뉴의 카테고리가 드롭다운에 표시됨
|
|
```
|
|
|
|
---
|
|
|
|
## 🔍 기술 상세
|
|
|
|
### 백엔드 메뉴 스코프 로직
|
|
|
|
```typescript
|
|
// 1. 형제 메뉴 조회
|
|
async getSiblingMenuIds(menuId: number): Promise<number[]> {
|
|
// 부모 ID 조회
|
|
const parentResult = await pool.query(
|
|
"SELECT parent_id FROM menu_info WHERE menu_id = $1",
|
|
[menuId]
|
|
);
|
|
|
|
const parentId = parentResult.rows[0].parent_id;
|
|
|
|
// 같은 부모를 가진 형제 메뉴들 조회
|
|
const siblingsResult = await pool.query(
|
|
"SELECT menu_id FROM menu_info WHERE parent_id = $1",
|
|
[parentId]
|
|
);
|
|
|
|
return siblingsResult.rows.map(row => row.menu_id);
|
|
}
|
|
|
|
// 2. 카테고리 값 조회 (형제 메뉴 포함)
|
|
async getCategoryValues(..., menuId: number, ...): Promise<TableCategoryValue[]> {
|
|
const siblingMenuIds = await this.getSiblingMenuIds(menuId);
|
|
|
|
const query = `
|
|
SELECT * FROM table_column_category_values
|
|
WHERE table_name = $1
|
|
AND column_name = $2
|
|
AND menu_id = ANY($3) -- 형제 메뉴들의 카테고리 포함
|
|
AND (company_code = $4 OR company_code = '*')
|
|
`;
|
|
|
|
return await pool.query(query, [tableName, columnName, siblingMenuIds, companyCode]);
|
|
}
|
|
```
|
|
|
|
### 프론트엔드 구조
|
|
|
|
```typescript
|
|
// CategoryWidget (메인 컴포넌트)
|
|
<div className="flex h-full gap-6">
|
|
{/* 좌측: 카테고리 컬럼 리스트 (30%) */}
|
|
<div className="w-[30%]">
|
|
<CategoryColumnList
|
|
tableName={tableName}
|
|
menuId={menuId}
|
|
selectedColumn={selectedColumn}
|
|
onColumnSelect={setSelectedColumn}
|
|
/>
|
|
</div>
|
|
|
|
{/* 우측: 카테고리 값 관리 (70%) */}
|
|
<div className="w-[70%]">
|
|
{selectedColumn ? (
|
|
<CategoryValueManager
|
|
tableName={tableName}
|
|
columnName={selectedColumn.columnName}
|
|
columnLabel={selectedColumn.columnLabel}
|
|
menuId={menuId}
|
|
/>
|
|
) : (
|
|
<EmptyState />
|
|
)}
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### ComponentRegistry 등록
|
|
|
|
```typescript
|
|
ComponentRegistry.registerComponent({
|
|
id: "category-manager",
|
|
name: "카테고리 관리",
|
|
category: ComponentCategory.DISPLAY,
|
|
webType: "category",
|
|
component: CategoryWidget,
|
|
configPanel: CategoryManagerConfigPanel,
|
|
icon: FolderTree,
|
|
defaultSize: { width: 1000, height: 600 },
|
|
tags: ["category", "reference", "manager", "scope", "menu"],
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 데이터 흐름
|
|
|
|
### 카테고리 값 생성
|
|
|
|
```
|
|
사용자: 카테고리 관리 화면 (menu_id: 103)
|
|
↓
|
|
프론트엔드: addCategoryValue({ ..., menuId: 103 })
|
|
↓
|
|
백엔드: INSERT INTO table_column_category_values
|
|
(..., menu_id) VALUES (..., 103)
|
|
↓
|
|
DB: 저장 완료 (menu_id = 103)
|
|
```
|
|
|
|
### 카테고리 값 조회
|
|
|
|
```
|
|
사용자: 발주 관리 화면 (menu_id: 101)
|
|
↓
|
|
프론트엔드: getCategoryValues(..., menuId: 101)
|
|
↓
|
|
백엔드:
|
|
1. getSiblingMenuIds(101) → [101, 102, 103, 104]
|
|
2. WHERE menu_id = ANY([101, 102, 103, 104])
|
|
↓
|
|
DB: menu_id가 101, 102, 103, 104인 모든 카테고리 반환
|
|
↓
|
|
결과: 카테고리 관리(103)에서 만든 카테고리도 포함 ✅
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 UI 스크린샷 예상도
|
|
|
|
### 화면 편집기 - ComponentsPanel
|
|
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ 검색: [ ] │
|
|
├─────────────────────────────────────┤
|
|
│ [입력] [표시] [동작] [레이아웃] │
|
|
├─────────────────────────────────────┤
|
|
│ 📊 데이터 테이블 v2 │
|
|
│ 🗂️ 카테고리 관리 ← 신규 추가! │
|
|
│ 📋 폼 레이아웃 │
|
|
│ 🔘 버튼 그룹 │
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
### 카테고리 관리 위젯 (배치 후)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ 카테고리 관리 │
|
|
├──────────────┬──────────────────────────────────────────┤
|
|
│ 카테고리 컬럼 │ 카테고리 값 관리: 발주 유형 │
|
|
│ (30%) │ (70%) │
|
|
├──────────────┤ │
|
|
│ ┌──────────┐│ ┌────────────────────────────────────┐ │
|
|
│ │🗂️ 발주유형││ │ 🔍 검색: [ ] ┌─────────┐ │ │
|
|
│ │order_type││ │ │ ✚ 추가 │ │ │
|
|
│ │✓ 선택됨 ││ │ └─────────┘ │ │
|
|
│ └──────────┘│ │ │ │
|
|
│ │ │ ┌────────────────────────────┐ │ │
|
|
│ ┌──────────┐│ │ │ ☑ MATERIAL - 자재 발주 │ │ │
|
|
│ │발주 상태 ││ │ │ 🎨 #3b82f6 │ │ │
|
|
│ │status ││ │ │ [편집] [삭제] │ │ │
|
|
│ └──────────┘│ │ └────────────────────────────┘ │ │
|
|
│ │ │ │ │
|
|
│ ┌──────────┐│ │ ┌────────────────────────────┐ │ │
|
|
│ │우선순위 ││ │ │ ☑ OUTSOURCE - 외주 발주 │ │ │
|
|
│ │priority ││ │ │ 🎨 #10b981 │ │ │
|
|
│ └──────────┘│ │ │ [편집] [삭제] │ │ │
|
|
│ │ │ └────────────────────────────┘ │ │
|
|
└──────────────┴──────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## ✨ 주요 특징
|
|
|
|
### 1. 메뉴 스코프 자동 격리
|
|
- 같은 부모 메뉴의 형제들만 카테고리 공유
|
|
- 다른 부모 메뉴에서는 완전히 격리됨
|
|
|
|
### 2. 완전 자동화
|
|
- menuId와 tableName 자동 설정
|
|
- 형제 메뉴 자동 조회
|
|
- 카테고리 컬럼 자동 필터링
|
|
|
|
### 3. 직관적인 UI
|
|
- 좌우 분할 구조
|
|
- 실시간 검색 및 필터링
|
|
- 색상 및 아이콘 시각화
|
|
|
|
### 4. ComponentRegistry 통합
|
|
- 드래그앤드롭으로 배치
|
|
- 자동 렌더링
|
|
- ConfigPanel로 설정 안내
|
|
|
|
---
|
|
|
|
## 🔄 완료 체크리스트
|
|
|
|
### Phase 1: DB 및 백엔드
|
|
- [x] DB 마이그레이션: `menu_id` 컬럼 추가
|
|
- [x] 외래키 `menu_info(menu_id)` 추가
|
|
- [x] UNIQUE 제약조건에 `menu_id` 추가
|
|
- [x] 인덱스 추가
|
|
- [x] 타입에 `menuId` 추가
|
|
- [x] `getSiblingMenuIds()` 함수 구현
|
|
- [x] 모든 쿼리에 `menu_id` 필터링 추가
|
|
- [x] API 파라미터에 `menuId` 추가
|
|
|
|
### Phase 2: 프론트엔드 컴포넌트
|
|
- [x] CategoryWidget 생성
|
|
- [x] CategoryColumnList 생성
|
|
- [x] CategoryValueManager에 `menuId` props 추가
|
|
- [x] API 클라이언트 수정
|
|
- [x] 타입에 `menuId` 추가
|
|
|
|
### Phase 3: 화면관리 시스템 통합
|
|
- [x] ComponentType에 `category-manager` 추가
|
|
- [x] CategoryManagerRenderer 생성
|
|
- [x] ComponentRegistry 등록
|
|
- [x] CategoryManagerConfigPanel 생성
|
|
- [x] index.ts에 import 추가
|
|
|
|
### Phase 4: 정리
|
|
- [x] 테이블 타입 관리 Dialog 제거
|
|
- [x] 불필요한 파일 삭제
|
|
- [x] Import 및 상태 제거
|
|
|
|
---
|
|
|
|
## 🎓 학습 포인트
|
|
|
|
### 1. 멀티테넌시 + 메뉴 스코프
|
|
- 회사별 격리 (company_code)
|
|
- 메뉴별 격리 (menu_id + 형제 메뉴 공유)
|
|
|
|
### 2. ComponentRegistry 패턴
|
|
- 컴포넌트 자동 등록
|
|
- 검색 및 필터링
|
|
- 메타데이터 기반 관리
|
|
|
|
### 3. 화면관리 시스템 아키텍처
|
|
- 드래그앤드롭 기반 UI 구성
|
|
- 실시간 미리보기
|
|
- 속성 패널 통합
|
|
|
|
### 4. 백엔드 메뉴 계층 쿼리
|
|
- 재귀 쿼리 없이 간단한 조인
|
|
- 형제 메뉴 효율적 조회
|
|
|
|
---
|
|
|
|
## 📝 다음 단계 (선택사항)
|
|
|
|
### 향후 개선 가능 항목
|
|
|
|
1. **계층 구조 강화**
|
|
- 3단계 이상 부모-자식 관계
|
|
- 드래그앤드롭으로 계층 재배치
|
|
|
|
2. **일괄 작업**
|
|
- 여러 카테고리 값 한 번에 추가
|
|
- Excel 업로드/다운로드
|
|
|
|
3. **히스토리 관리**
|
|
- 카테고리 값 변경 이력
|
|
- Audit Log 통합
|
|
|
|
4. **권한 관리**
|
|
- 카테고리별 수정 권한
|
|
- 메뉴 관리자 전용 기능
|
|
|
|
---
|
|
|
|
## 🎉 최종 완료!
|
|
|
|
**모든 구현이 100% 완료되었습니다!**
|
|
|
|
- ✅ DB 및 백엔드
|
|
- ✅ 프론트엔드 컴포넌트
|
|
- ✅ 화면관리 시스템 통합
|
|
- ✅ 정리 및 문서화
|
|
|
|
**완료 일시**: 2025-11-05
|
|
**총 소요 시간**: 약 3시간
|
|
**생성된 파일**: 6개
|
|
**수정된 파일**: 9개
|
|
**삭제된 파일**: 1개
|
|
|