# React 부서관리 기능 보완 계획

> **작성일**: 2026-03-12
> **목적**: React 부서관리(/hr/department-management)를 MNG 부서관리와 동일 기능 수준으로 보완
> **기준 문서**: `docs/rules/department-tree-api.md`, MNG DepartmentController 분석
> **상태**: 🔄 Phase 1~2 승인 완료 — 작업 대기

---

## 📍 현재 진행 상태

| 항목 | 내용 |
|------|------|
| **마지막 완료 작업** | Phase 1~2 구현 완료 |
| **다음 작업** | 검증 (브라우저 테스트) |
| **진행률** | 7/7 (100%) — Phase 1~2 완료 |
| **마지막 업데이트** | 2026-03-13 |

---

## 1. 개요

### 1.1 배경

MNG(`mng.sam.kr/departments`)와 React(`dev.sam.kr/hr/department-management`)에 동일한 부서관리 기능이 존재하지만, React 쪽이 기능적으로 많이 부족한 상태. 관리 플랫폼이 달라도 같은 수준의 CRUD와 관리 기능을 제공해야 함.

### 1.2 현재 상태 비교

**React에 누락된 기능:**

| # | 누락 기능 | 심각도 | 비고 |
|---|----------|:------:|------|
| 1 | 부서 코드(code) 필드 | 🔴 | 폼에 아예 없음 |
| 2 | 설명(description) 필드 | 🟡 | 폼에 아예 없음 |
| 3 | 정렬순서(sort_order) 필드 | 🟡 | 폼에 아예 없음 |
| 4 | 활성상태(is_active) 관리 | 🔴 | 폼/리스트 모두 없음 |
| 5 | 검색 필터링 | 🔴 | UI만 있고 실제 동작 안함 |
| 6 | 상태 필터 (활성/비활성) | 🟡 | 없음 |
| 7 | Soft Delete 복원 | 🟡 | 없음 |
| 8 | 영구삭제 (슈퍼관리자) | 🟢 | 없음 (admin 전용이라 후순위 가능) |
| 9 | 삭제 상태 필터 | 🟡 | 없음 |
| 10 | 트리 리스트에 상태 뱃지 | 🟡 | 없음 |
| 11 | 트리 리스트에 부서코드 표시 | 🟡 | 없음 |

**React가 이미 잘 된 부분:**
- ✅ 트리 구조 시각화 (펼치기/접기)
- ✅ 통계 카드
- ✅ 행 단위 하위부서 추가 버튼
- ✅ 전체 선택/다중 선택

### 1.3 성공 기준

```
┌─────────────────────────────────────────────────────────────────┐
│  🎯 성공 기준                                                    │
├─────────────────────────────────────────────────────────────────┤
│  1. MNG에서 가능한 모든 CRUD가 React에서도 가능                  │
│  2. 부서 코드/설명/정렬순서/활성상태 필드가 폼에 포함            │
│  3. 검색, 상태 필터가 실제 동작                                  │
│  4. 삭제된 부서 복원 가능                                        │
│  5. 트리 리스트에 코드, 상태 뱃지 표시                           │
└─────────────────────────────────────────────────────────────────┘
```

### 1.4 변경 승인 정책

| 분류 | 예시 | 승인 |
|------|------|------|
| ✅ 즉시 가능 | 타입 확장, 필드 추가, UI 컴포넌트 수정 | 불필요 |
| ⚠️ 컨펌 필요 | API 호출 추가, 새 서버액션 추가 | **필수** |
| 🔴 금지 | DB 스키마 변경, API 컨트롤러 수정 | 별도 협의 |

### 1.5 기준 원칙

```
┌─────────────────────────────────────────────────────────────────┐
│  📌 원칙                                                         │
├─────────────────────────────────────────────────────────────────┤
│  - API 변경 최소화: 기존 /v1/departments API 그대로 활용        │
│  - React 프론트엔드 패턴 준수: Server Action, buildApiUrl 등    │
│  - 트리 구조 유지: 현재 트리 UI 장점 살리면서 필드만 보강       │
│  - MNG와 1:1 기능 매칭이 목표 (UI/UX는 React 스타일 유지)       │
└─────────────────────────────────────────────────────────────────┘
```

### 1.6 준수 규칙
- `docs/frontend/v1/02-api-pattern.md` — API 통신 패턴
- `docs/frontend/v1/05-form-pattern.md` — 폼 패턴 (Zod + react-hook-form)
- `docs/frontend/v1/03-component-design.md` — 컴포넌트 설계
- `docs/rules/department-tree-api.md` — 부서 트리 API 규칙
- `docs/dev/standards/quality-checklist.md` — 품질 체크리스트

---

## 2. 대상 범위

### 2.1 Phase 1: 타입 & 폼 필드 보강 (핵심)

| # | 작업 항목 | 상태 | 비고 |
|---|----------|:----:|------|
| 1.1 | types.ts 확장 — code, description, isActive, sortOrder 추가 | ✅ | Department + DepartmentFormData + StatusFilter 추가 |
| 1.2 | actions.ts — 이미 전체 필드 매핑 완료 확인 | ✅ | 변경 불필요 (ApiDepartment→DepartmentRecord 이미 완전) |
| 1.3 | DepartmentDialog 폼 필드 추가 — code, description, sortOrder, isActive | ✅ | Zod v4 + react-hook-form 적용 |
| 1.4 | DepartmentTreeItem에 코드, 상태 뱃지 표시 | ✅ | Badge 컴포넌트 활용 |

### 2.2 Phase 2: 검색 & 필터 (실질 기능)

| # | 작업 항목 | 상태 | 비고 |
|---|----------|:----:|------|
| 2.1 | DepartmentToolbar 검색 실제 동작 구현 | ✅ | 클라이언트사이드 트리 필터링 (filterDepartmentTree) |
| 2.2 | 상태 필터 추가 (전체/활성/비활성) | ✅ | Select 드롭다운 |
| 2.3 | 필터 적용 로직 (index.tsx) | ✅ | filteredDepartments useMemo |

### 2.3 Phase 3: 삭제 & 복원 — ⏭️ 추후 작업 (현재 MNG에서 관리)

> **결정**: 삭제/복원은 현재 MNG에서 관리. 추후 React에서 직접 관리 시 진행.
> **전제조건**: V1 API에 restore 엔드포인트 추가, tree API에 with_trashed 파라미터 추가 필요.

| # | 작업 항목 | 상태 | 비고 |
|---|----------|:----:|------|
| 3.1 | 삭제 상태 필터 추가 (일반/삭제포함/삭제만) | ⏭️ | API 변경 필요: tree에 with_trashed 파라미터 |
| 3.2 | 삭제된 부서 표시 UI (배경색, 뱃지) | ⏭️ | React만 |
| 3.3 | 복원 기능 — actions.ts + 복원 버튼 | ⏭️ | API 추가 필요: POST /v1/departments/{id}/restore |
| 3.4 | 일괄 복원 | ⏭️ | API 추가 필요 |

### 2.4 Phase 4: 편의 기능 — ⏭️ 추후 작업

| # | 작업 항목 | 상태 | 비고 |
|---|----------|:----:|------|
| 4.1 | 통계 카드 확장 (활성/비활성 카운트) | ⏭️ | React만, API 불필요 |
| 4.2 | 영구삭제 (슈퍼관리자 전용) | ⏭️ | API 추가 필요 |
| 4.3 | 부서 이동 (parentId 변경) UI | ⏭️ | API는 이미 지원 (PATCH parent_id) |

---

## 3. 작업 절차

### 3.1 단계별 절차

```
Phase 1: 타입 & 폼 필드 보강 (핵심 — 먼저 완료)
├── 1.1 types.ts 확장
│   └── Department 인터페이스에 code, description, isActive, sortOrder 추가
├── 1.2 actions.ts 수정
│   ├── ApiDepartment → DepartmentRecord 변환에 누락 필드 포함 확인
│   ├── createDepartment, updateDepartment 요청 데이터에 필드 추가
│   └── getDepartmentTree 응답 매핑 확인
├── 1.3 DepartmentDialog 폼 확장
│   ├── Zod 스키마 정의 (code 필수, name 필수, description 선택, sortOrder 선택, isActive 기본 true)
│   ├── 폼 필드 추가 (부서코드, 부서명, 설명, 정렬순서, 활성상태)
│   └── 수정 모드 시 기존 값 로드
└── 1.4 DepartmentTreeItem UI 보강
    ├── 부서코드 표시 (부서명 옆)
    └── 활성/비활성 상태 뱃지

Phase 2: 검색 & 필터
├── 2.1 검색 기능 구현
│   └── 트리 재귀 탐색으로 이름/코드 매칭 필터
├── 2.2 상태 필터 드롭다운 추가
│   └── DepartmentToolbar에 Select 컴포넌트 추가
└── 2.3 필터 적용 로직
    └── index.tsx에 filteredDepartments useMemo

Phase 3~4: ⏭️ 추후 작업 (현재 MNG에서 관리, API 변경 필요)
```

---

## 4. 상세 작업 내용

### 4.1 Phase 1 상세

#### 1.1 types.ts 확장

```typescript
// 현재
interface Department {
  id: number;
  name: string;
  parentId: number | null;
  depth: number;
  children?: Department[];
}

// 변경 후
interface Department {
  id: number;
  code: string | null;
  name: string;
  description: string | null;
  parentId: number | null;
  isActive: boolean;
  sortOrder: number;
  depth: number;
  children?: Department[];
  deletedAt?: string | null;  // Phase 3용
}
```

#### 1.3 DepartmentDialog 폼 — Zod 스키마

```typescript
const departmentFormSchema = z.object({
  code: z.string().min(1, '부서 코드를 입력하세요').max(50),
  name: z.string().min(1, '부서명을 입력하세요').max(100),
  description: z.string().max(500).optional().or(z.literal('')),
  sortOrder: z.number().min(0).default(0),
  isActive: z.boolean().default(true),
});
```

#### 1.4 DepartmentTreeItem UI 예시

```
[▼] [☑] DEPT001 경영지원본부  [활성]
      [+] [✎] [🗑]
    [▼] [☑] HR001 인사팀  [활성]
    [▶] [☑] FIN001 재무팀  [비활성]
```

### 4.2 Phase 3 상세 — ⏭️ 추후 작업 시 참고

> 2026-03-13 확인 완료: V1 API에 restore, force-delete, with_trashed 모두 없음.
> Phase 3 진행 시 API 변경 필수 (api/ 저장소).

**필요한 API 변경:**
1. `POST /v1/departments/{id}/restore` — 라우트 + 컨트롤러 + 서비스 추가
2. `GET /v1/departments/tree?with_trashed=1` — tree()에 withTrashed 스코프 추가
3. Department 모델 `$hidden`에서 `deleted_at` 조건부 노출

---

## 5. 컨펌 대기 목록

| # | 항목 | 변경 내용 | 영향 범위 | 상태 |
|---|------|----------|----------|------|
| 1 | Phase 1~2 진행 | React만 수정, API 변경 없음 | react/ | ✅ 승인됨 |
| 2 | Phase 3~4 보류 | 추후 MNG→React 이관 시 진행 (API 변경 필요) | api/ + react/ | ⏭️ 보류 |

---

## 6. 변경 이력

| 날짜 | 항목 | 변경 내용 | 파일 | 승인 |
|------|------|----------|------|------|
| 2026-03-12 | - | 계획 문서 초안 작성 | - | - |

---

## 7. 참고 문서

- **부서 트리 API 규칙**: `docs/rules/department-tree-api.md`
- **프론트엔드 API 패턴**: `docs/frontend/v1/02-api-pattern.md`
- **프론트엔드 폼 패턴**: `docs/frontend/v1/05-form-pattern.md`
- **프론트엔드 컴포넌트 설계**: `docs/frontend/v1/03-component-design.md`
- **품질 체크리스트**: `docs/dev/standards/quality-checklist.md`

### 참고 소스 경로

**React (수정 대상):**
```
react/src/components/hr/DepartmentManagement/
├── index.tsx              — 메인 컴포넌트 (상태 관리)
├── types.ts               — 타입 정의 + 유틸리티
├── actions.ts             — 서버 액션 (API 호출)
├── DepartmentTree.tsx     — 트리 컨테이너
├── DepartmentTreeItem.tsx — 트리 행 (재귀)
├── DepartmentDialog.tsx   — 추가/수정 모달
├── DepartmentToolbar.tsx  — 검색 + 버튼
└── DepartmentStats.tsx    — 통계 카드
```

**MNG (참고용):**
```
mng/app/Http/Controllers/Api/Admin/DepartmentController.php
mng/app/Services/DepartmentService.php
mng/app/Http/Requests/StoreDepartmentRequest.php
mng/app/Http/Requests/UpdateDepartmentRequest.php
mng/resources/views/departments/
```

**API (확인 대상):**
```
api/app/Http/Controllers/Api/V1/DepartmentController.php
api/app/Services/DepartmentService.php
```

---

## 8. 일정 산정

| Phase | 작업량 | 수정 범위 | 비고 |
|-------|--------|----------|------|
| **Phase 1** | 중간 | React 4개 파일 | API 변경 없음 |
| **Phase 2** | 가벼움 | React 2개 파일 | API 변경 없음 |
| Phase 3 | 무거움 | API 4개 + React 4개 파일 | ⏭️ 추후 |
| Phase 4 | 가벼움 | React 2~3개 파일 | ⏭️ 추후 |

**현재 스코프**: Phase 1 → Phase 2 (순차, React만 수정)
**수정 대상 파일**: types.ts, actions.ts, DepartmentDialog.tsx, DepartmentTreeItem.tsx, DepartmentToolbar.tsx, index.tsx

---

## 9. 검증 결과

> 작업 완료 후 이 섹션에 검증 결과 추가

### 9.1 테스트 체크리스트

| 테스트 항목 | 예상 결과 | 실제 결과 | 상태 |
|------------|----------|----------|------|
| 부서 생성 (전체 필드) | code, name, description, sortOrder, isActive 저장 | | ⏳ |
| 부서 수정 (전체 필드) | 모든 필드 수정 반영 | | ⏳ |
| 부서 코드 중복 검증 | 에러 메시지 표시 | | ⏳ |
| 검색 (이름) | 매칭 부서만 트리에 표시 | | ⏳ |
| 검색 (코드) | 매칭 부서만 트리에 표시 | | ⏳ |
| 상태 필터 (활성만) | 비활성 부서 숨김 | | ⏳ |
| 상태 필터 (비활성만) | 활성 부서 숨김 | | ⏳ |
| 삭제된 부서 표시 | 빨간 배경 + "삭제됨" 뱃지 | | ⏳ |
| 삭제된 부서 복원 | 정상 복원, 트리 갱신 | | ⏳ |
| 트리 펼치기/접기 | 기존 기능 유지 | | ⏳ |
| 전체 선택/해제 | 기존 기능 유지 | | ⏳ |

### 9.2 성공 기준 달성 현황

| 기준 | 달성 | 비고 |
|------|:----:|------|
| MNG CRUD 동일 수준 | ⏳ | |
| 전체 필드 폼 포함 | ⏳ | |
| 검색/필터 동작 | ⏳ | |
| 삭제 부서 복원 가능 | ⏳ | |
| 트리 리스트 정보 표시 | ⏳ | |

---

## 10. 자기완결성 점검 결과

### 10.1 체크리스트 검증

| # | 검증 항목 | 상태 | 비고 |
|---|----------|:----:|------|
| 1 | 작업 목적이 명확한가? | ✅ | 1.1 배경 |
| 2 | 성공 기준이 정의되어 있는가? | ✅ | 1.3 성공 기준 |
| 3 | 작업 범위가 구체적인가? | ✅ | 섹션 2 전체 |
| 4 | 의존성이 명시되어 있는가? | ✅ | 컨펌 대기 목록 |
| 5 | 참고 파일 경로가 정확한가? | ✅ | 섹션 7 |
| 6 | 단계별 절차가 실행 가능한가? | ✅ | 섹션 3 |
| 7 | 검증 방법이 명시되어 있는가? | ✅ | 섹션 9 |
| 8 | 모호한 표현이 없는가? | ✅ | |

### 10.2 새 세션 시뮬레이션 테스트

| 질문 | 답변 가능 | 참조 섹션 |
|------|:--------:|----------|
| Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 |
| Q2. 어디서부터 시작해야 하는가? | ✅ | 3.1 단계별 절차 |
| Q3. 어떤 파일을 수정해야 하는가? | ✅ | 7. 참고 소스 경로 |
| Q4. 작업 완료 확인 방법은? | ✅ | 9. 검증 결과 |
| Q5. 막혔을 때 참고 문서는? | ✅ | 7. 참고 문서 |

---

*이 문서는 /plan 스킬로 생성되었습니다.*
