# 조직도 서비스 이관 기획서

> **작성일**: 2026-03-22
> **상태**: API 구현 완료, React 문서 제공
> **대상**: MNG → API + React (서비스 이관)
> **위치**: 서비스 > 인사관리 > 조직도

---

## 1. 개요

### 1.1 목적

MNG 백오피스의 조직도 관리 기능을 서비스(API + React)로 이관한다.
기존 MNG의 Alpine.js + SortableJS 기반 UI를 REST API + React 구조로 재구현하며,
멀티테넌트 격리를 API 레이어에서 강화한다.

### 1.2 배경

- MNG `R&D > 조직도 관리` 메뉴로 v1.0 구현 완료 (2026-03-06)
- 부서 CRUD + 트리 + 사용자 배치 API는 이미 존재 (`DepartmentController`)
- 조직도 전용 기능(직원 일괄 이동, 부서 순서/계층 변경, 숨기기)이 API에 없었음
- MNG는 `session('selected_tenant_id')` 수동 격리 → API는 `BelongsToTenant` 글로벌 스코프

### 1.3 이관 범위

| 구분 | MNG (현재) | API + React (이관 후) |
|------|-----------|---------------------|
| **백엔드** | RdController 직접 로직 | OrgChartService + OrgChartController + FormRequest |
| **프론트** | Alpine.js + SortableJS | React (Next.js) + @dnd-kit |
| **인증** | 세션 기반 | Bearer 토큰 + `BelongsToTenant` |
| **데이터** | `withoutGlobalScopes()` 수동 | 글로벌 스코프 자동 격리 |
| **API 문서** | 없음 | Swagger |

---

## 2. 현재 MNG 기능 분석

### 2.1 MNG 엔드포인트 (RdController)

| Route | Method | 설명 |
|-------|--------|------|
| `/rd/org-chart` | GET | 조직도 페이지 (트리+직원+회사정보) |
| `/rd/org-chart/assign` | POST | 직원 부서 배치 |
| `/rd/org-chart/unassign` | POST | 직원 미배치 처리 |
| `/rd/org-chart/reorder` | POST | 직원 일괄 이동 |
| `/rd/org-chart/reorder-depts` | POST | 부서 트리 순서/계층 변경 |
| `/rd/org-chart/toggle-hide` | POST | 부서 숨기기/표시 토글 |

### 2.2 데이터 모델

- **부서**: `departments` 테이블 (자기참조 `parent_id`, `sort_order`, `options.orgchart_hidden`)
- **직원**: `tenant_user_profiles` 테이블 (`department_id`로 소속 관리)
- **회사**: `tenants` 테이블 (`company_name`, `ceo_name`)

### 2.3 기존 API 구현 (DepartmentController)

| 기능 | 상태 |
|------|:----:|
| 부서 CRUD | ✅ |
| 부서 트리 조회 (`/tree`) | ✅ |
| 사용자 배정 (`attachUser/detachUser`) | ✅ (department_user 피벗) |
| 조직도 전용 기능 | ❌ → **이번 이관 대상** |

---

## 3. API 설계

### 3.1 신규 엔드포인트 (`/v1/org-chart`)

| Method | Path | 설명 |
|--------|------|------|
| GET | `/v1/org-chart` | 조직도 전체 (트리+직원+통계) |
| GET | `/v1/org-chart/stats` | 통계 (전체/배치/미배치) |
| GET | `/v1/org-chart/unassigned?q=` | 미배치 직원 |
| POST | `/v1/org-chart/assign` | 직원 부서 배치 |
| POST | `/v1/org-chart/unassign` | 직원 미배치 처리 |
| PUT | `/v1/org-chart/reorder-employees` | 직원 일괄 이동 |
| PUT | `/v1/org-chart/reorder-departments` | 부서 순서/계층 변경 |
| PATCH | `/v1/org-chart/departments/{id}/toggle-hide` | 부서 숨기기 토글 |

### 3.2 주요 응답 구조

**GET `/v1/org-chart`**:
```json
{
  "company": { "name": "...", "ceo_name": "..." },
  "departments": [{ "id": 1, "name": "...", "children": [...], "employees": [...] }],
  "hidden_departments": [{ "id": 5, "name": "..." }],
  "unassigned": [{ "id": 12, "display_name": "...", "position_label": "..." }],
  "stats": { "total": 50, "assigned": 42, "unassigned": 8 }
}
```

---

## 4. API 구현 상세

### 4.1 파일 구조

```
api/
├── app/Http/Controllers/Api/V1/OrgChartController.php  (신규)
├── app/Http/Requests/OrgChart/
│   ├── AssignRequest.php
│   ├── UnassignRequest.php
│   ├── ReorderEmployeesRequest.php
│   ├── ReorderDepartmentsRequest.php
│   └── ToggleHideRequest.php
├── app/Services/OrgChartService.php                     (신규)
├── app/Models/Tenants/Department.php                    (수정: options cast)
├── app/Swagger/v1/OrgChartApi.php                       (신규)
└── routes/api/v1/hr.php                                 (수정: 라우트 추가)
```

### 4.2 설계 결정

- **별도 OrgChartController/Service 분리**: 기존 DepartmentController(13개 메서드)와 관심사 분리
- **TenantUserProfile.department_id 기반**: MNG와 동일하게 직원의 소속 부서 필드 직접 사용
- **순환 참조 방지**: `reorderDepartments`에서 `parent_id` 변경 시 자손→조상 순환 검증

---

## 5. React 구현 (FE 가이드)

> **별도 문서**: `docs/frontend/v1/org-chart-fe-guide.md`

---

## 6. 인증 및 권한

### 6.1 React → API

- `authenticatedFetch` 사용 (HttpOnly 쿠키 기반 Sanctum)
- `auth:sanctum` 미들웨어 자동 적용 (HR 라우트 그룹)

### 6.2 MNG → API (해당 없음)

- MNG는 기존 코드를 유지하고 자체 DB 직접 접근
- 이관 완료 후 MNG 메뉴를 숨기고 React로 안내

---

## 7. 구현 순서

| Phase | 작업 | 상태 |
|-------|------|:----:|
| 1 | Department 모델 `options` cast 추가 | ✅ 완료 |
| 2 | OrgChartService + FormRequest 5개 생성 | ✅ 완료 |
| 3 | OrgChartController + Route 등록 | ✅ 완료 |
| 4 | Swagger 문서 (OrgChartApi.php) | ✅ 완료 |
| 5 | React FE 구현 | 📋 문서 제공 |
| 6 | 통합 테스트 + MNG 메뉴 전환 | ⏳ 대기 |

---

## 8. MNG 기존 코드 처리

- MNG `RdController.orgChart*` 메서드 → **유지** (삭제하지 않음)
- React 구현 완료 후 MNG 메뉴에서 조직도를 비활성화하고 서비스로 안내

---

## 9. 체크리스트

### API
- [x] `OrgChartService` 8개 메서드 구현
- [x] `OrgChartController` FormRequest DI 적용
- [x] 순환 참조 방지 검증 (reorderDepartments)
- [x] `Department` 모델 `options` cast 추가
- [x] Swagger 문서 생성 확인
- [x] Pint 포맷팅 통과

### React
- [ ] `org-chart-fe-guide.md` 기반 구현
- [ ] 드래그 앤 드롭 (부서/직원)
- [ ] 미배치 직원 패널
- [ ] 부서 숨기기/복원

---

## 관련 문서

| 문서 | 경로 |
|------|------|
| 조직도 시스템 (MNG) | `projects/org-chart/README.md` |
| 부서 API 규칙 | `rules/department-tree-api.md` |
| 직원 API 규칙 | `rules/employee-api.md` |
| React FE 가이드 | `frontend/v1/org-chart-fe-guide.md` |
| 이관 현황 | `system/migration-status.md` |

---

**최종 업데이트**: 2026-03-22
