232 lines
8.5 KiB
Markdown
232 lines
8.5 KiB
Markdown
|
|
# 조직도 React 프론트엔드 구현 가이드
|
||
|
|
|
||
|
|
> **작성일**: 2026-03-22
|
||
|
|
> **상태**: API 완료, FE 구현 대기
|
||
|
|
> **대상**: React (Next.js) 프론트엔드 개발자
|
||
|
|
> **페이지 URL**: `/hr/org-chart`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. 개요
|
||
|
|
|
||
|
|
MNG의 조직도 관리 기능을 React로 재구현한다. API는 이미 구현 완료(`/v1/org-chart`).
|
||
|
|
드래그 앤 드롭으로 직원 배치, 부서 순서/계층 변경, 부서 숨기기 기능을 제공한다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. API 엔드포인트
|
||
|
|
|
||
|
|
| 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` | 부서 숨기기 토글 |
|
||
|
|
|
||
|
|
> Swagger UI: `/api-docs` → "OrgChart" 태그 참조
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. 응답 구조
|
||
|
|
|
||
|
|
### 3.1 GET `/v1/org-chart`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"data": {
|
||
|
|
"company": {
|
||
|
|
"name": "주일산업",
|
||
|
|
"ceo_name": "홍길동"
|
||
|
|
},
|
||
|
|
"departments": [
|
||
|
|
{
|
||
|
|
"id": 1,
|
||
|
|
"name": "경영지원팀",
|
||
|
|
"code": "MGT",
|
||
|
|
"parent_id": null,
|
||
|
|
"sort_order": 1,
|
||
|
|
"is_active": true,
|
||
|
|
"orgchart_hidden": false,
|
||
|
|
"children": [],
|
||
|
|
"employees": [
|
||
|
|
{
|
||
|
|
"id": 5,
|
||
|
|
"user_id": 3,
|
||
|
|
"department_id": 1,
|
||
|
|
"display_name": "김과장",
|
||
|
|
"position_label": "과장"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"hidden_departments": [
|
||
|
|
{ "id": 5, "name": "해외사업팀", "code": "OVS" }
|
||
|
|
],
|
||
|
|
"unassigned": [
|
||
|
|
{ "id": 12, "user_id": 8, "display_name": "이사원", "position_label": "사원" }
|
||
|
|
],
|
||
|
|
"stats": {
|
||
|
|
"total": 50,
|
||
|
|
"assigned": 42,
|
||
|
|
"unassigned": 8
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3.2 요청 바디 예시
|
||
|
|
|
||
|
|
**POST `/v1/org-chart/assign`**:
|
||
|
|
```json
|
||
|
|
{ "employee_id": 5, "department_id": 3 }
|
||
|
|
```
|
||
|
|
|
||
|
|
**PUT `/v1/org-chart/reorder-employees`**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"moves": [
|
||
|
|
{ "employee_id": 5, "department_id": 3 },
|
||
|
|
{ "employee_id": 6, "department_id": null }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**PUT `/v1/org-chart/reorder-departments`**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"orders": [
|
||
|
|
{ "id": 1, "parent_id": null, "sort_order": 0 },
|
||
|
|
{ "id": 2, "parent_id": 1, "sort_order": 1 }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**PATCH `/v1/org-chart/departments/{id}/toggle-hide`**:
|
||
|
|
```json
|
||
|
|
{ "hidden": true }
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. 컴포넌트 구조 (제안)
|
||
|
|
|
||
|
|
```
|
||
|
|
src/
|
||
|
|
├── app/[locale]/(protected)/hr/
|
||
|
|
│ └── org-chart/
|
||
|
|
│ └── page.tsx ← 페이지 진입점
|
||
|
|
├── components/hr/org-chart/
|
||
|
|
│ ├── index.tsx ← 메인 컨테이너
|
||
|
|
│ ├── OrgChartTree.tsx ← 부서 트리 렌더링
|
||
|
|
│ ├── DepartmentNode.tsx ← 부서 카드 (접기/펼치기, 숨기기)
|
||
|
|
│ ├── EmployeeCard.tsx ← 직원 카드 (드래그 가능)
|
||
|
|
│ ├── UnassignedPanel.tsx ← 미배치 직원 패널 (검색 포함)
|
||
|
|
│ ├── HiddenDepartmentsPanel.tsx ← 숨겨진 부서 복원 패널
|
||
|
|
│ ├── OrgChartStats.tsx ← 상단 통계 표시
|
||
|
|
│ ├── CompanyHeader.tsx ← 회사명 + CEO 표시
|
||
|
|
│ ├── actions.ts ← Server Actions
|
||
|
|
│ └── types.ts ← TypeScript 타입 정의
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. UI 구성 (MNG 참조)
|
||
|
|
|
||
|
|
MNG 조직도 UI: `mng/resources/views/rd/org-chart.blade.php`
|
||
|
|
|
||
|
|
### 5.1 화면 레이아웃
|
||
|
|
|
||
|
|
```
|
||
|
|
┌───────────────────────────────────────────────────────┐
|
||
|
|
│ 조직도 관리 전체 50명 | 배치 42명 | 미배치 8명 │ ← 헤더 + 통계
|
||
|
|
├───────────────────────────────────────────────────────┤
|
||
|
|
│ ┌─미배치 직원──────┐ ┌─조직도 트리───────────────────┐ │
|
||
|
|
│ │ 🔍 검색 │ │ ┌──────────────────────────┐ │ │
|
||
|
|
│ │ │ │ │ 회사명 │ │ │
|
||
|
|
│ │ ▪ 이사원 (사원) │ │ │ CEO: 홍길동 │ │ │
|
||
|
|
│ │ ▪ 박대리 (대리) │ │ └──────────────────────────┘ │ │
|
||
|
|
│ │ │ │ │ │
|
||
|
|
│ │ (드래그 가능) │ │ ┌─경영지원팀 (MGT)──────────┐ │ │
|
||
|
|
│ │ │ │ │ 김과장 (과장) [미배치 ✕] │ │ │
|
||
|
|
│ │ │ │ │ 최대리 (대리) [미배치 ✕] │ │ │
|
||
|
|
│ │ │ │ └──────────────────────────┘ │ │
|
||
|
|
│ │ │ │ ┌─생산팀 (PRD)───────────────┐ │ │
|
||
|
|
│ │ │ │ │ ... │ │ │
|
||
|
|
│ │ │ │ └────────────────────────────┘ │ │
|
||
|
|
│ └──────────────────┘ └──────────────────────────────┘ │
|
||
|
|
│ ┌─숨겨진 부서──────────────────────────────────────────┐ │
|
||
|
|
│ │ 해외사업팀 [복원] 영업3팀 [복원] │ │
|
||
|
|
│ └──────────────────────────────────────────────────────┘ │
|
||
|
|
└───────────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5.2 인터랙션
|
||
|
|
|
||
|
|
| 동작 | 효과 | API 호출 |
|
||
|
|
|------|------|---------|
|
||
|
|
| 미배치 직원 → 부서 드래그 | 직원 배치 | `POST /assign` 또는 `PUT /reorder-employees` |
|
||
|
|
| 부서 내 직원 → 미배치 패널 드래그 | 직원 미배치 | `POST /unassign` |
|
||
|
|
| 부서 카드 드래그 (순서 변경) | 부서 순서/계층 변경 | `PUT /reorder-departments` |
|
||
|
|
| 부서 카드 더블클릭 → "숨기기" | 조직도에서 숨김 | `PATCH /departments/{id}/toggle-hide` |
|
||
|
|
| 숨겨진 부서 "복원" 클릭 | 조직도에 다시 표시 | `PATCH /departments/{id}/toggle-hide` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. 드래그 앤 드롭 구현
|
||
|
|
|
||
|
|
### 6.1 라이브러리 권장
|
||
|
|
|
||
|
|
- **@dnd-kit**: React 전용, 접근성 지원, 트리 구조 지원
|
||
|
|
- **대안**: react-beautiful-dnd (유지보수 중단), react-dnd
|
||
|
|
|
||
|
|
### 6.2 핵심 구현 포인트
|
||
|
|
|
||
|
|
1. **직원 드래그**: 미배치 패널 ↔ 부서 카드 간 이동
|
||
|
|
2. **부서 드래그**: 부서 카드 간 순서/계층 변경 (parent_id + sort_order)
|
||
|
|
3. **순환 참조 방지**: 부서를 자기 자손에 드롭하면 무시 (API에서도 검증하지만 UI에서도 방지)
|
||
|
|
4. **Optimistic Update**: 드래그 완료 시 로컬 상태 즉시 업데이트 → API 호출 → 실패 시 롤백
|
||
|
|
|
||
|
|
### 6.3 상태 관리
|
||
|
|
|
||
|
|
```
|
||
|
|
초기 로딩: GET /v1/org-chart → 로컬 상태 세팅
|
||
|
|
├── departments (트리 구조)
|
||
|
|
├── unassigned (미배치 직원 배열)
|
||
|
|
├── hiddenDepartments (숨겨진 부서 배열)
|
||
|
|
├── stats (통계)
|
||
|
|
└── company (회사 정보)
|
||
|
|
|
||
|
|
변경 시: API 호출 → 성공 시 로컬 상태 업데이트
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 7. MNG 참고 파일
|
||
|
|
|
||
|
|
| 파일 | 설명 |
|
||
|
|
|------|------|
|
||
|
|
| `mng/app/Http/Controllers/RdController.php` (L38-208) | 조직도 컨트롤러 로직 |
|
||
|
|
| `mng/resources/views/rd/org-chart.blade.php` | 조직도 UI (Alpine.js + SortableJS) |
|
||
|
|
| `mng/app/Models/Tenants/Department.php` | Department 모델 (options cast) |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 관련 문서
|
||
|
|
|
||
|
|
| 문서 | 경로 |
|
||
|
|
|------|------|
|
||
|
|
| 이관 계획서 | `dev/dev_plans/org-chart-service-migration-plan.md` |
|
||
|
|
| 조직도 시스템 (MNG) | `projects/org-chart/README.md` |
|
||
|
|
| React 아키텍처 | `frontend/v1/01-architecture.md` |
|
||
|
|
| API 패턴 | `frontend/v1/02-api-pattern.md` |
|
||
|
|
| 인증 흐름 | `frontend/v1/07-auth-flow.md` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**최종 업데이트**: 2026-03-22
|