Files
sam-docs/rules/department-tree-api.md
hskwon 5d1190a0d3 docs: plans 폴더 추가 및 HR API 규칙 문서 정리
- plans/ 폴더 신규 생성 (개발 계획 임시 문서용)
- hr-api-react-sync-plan.md를 specs → plans로 이동
- INDEX.md 업데이트 (폴더 구조, 워크플로우)
- rules/ HR API 규칙 문서 추가 (employee, attendance, department-tree)
- pricing API 요청 문서 업데이트
2025-12-09 14:44:39 +09:00

6.9 KiB

Department Tree API (부서트리 조회 API) 규칙

개요

부서트리 API는 테넌트 내 조직도를 계층 구조로 조회하는 API입니다. departments 테이블의 parent_id를 통한 자기참조 관계로 무한 depth 계층 구조를 지원합니다.

핵심 모델

Department

  • 위치: App\Models\Tenants\Department
  • 역할: 부서/조직 정보
  • 특징:
    • parent_id 자기참조로 계층 구조
    • HasRoles 트레이트 (부서도 권한/역할 보유 가능)
    • ModelTrait 적용 (is_active, 날짜 처리)

엔드포인트

부서 트리 전용

Method Path 설명
GET /v1/departments/tree 부서 트리 조회

기본 CRUD (참고)

Method Path 설명
GET /v1/departments 부서 목록 조회
GET /v1/departments/{id} 부서 상세 조회
POST /v1/departments 부서 생성
PATCH /v1/departments/{id} 부서 수정
DELETE /v1/departments/{id} 부서 삭제

부서-사용자 관리

Method Path 설명
GET /v1/departments/{id}/users 부서 사용자 목록
POST /v1/departments/{id}/users 사용자 배정
DELETE /v1/departments/{id}/users/{user} 사용자 제거
PATCH /v1/departments/{id}/users/{user}/primary 주부서 설정

데이터 구조

기본 필드

필드 타입 설명
id int PK
tenant_id int 테넌트 ID
parent_id int 상위 부서 ID (nullable, 최상위는 null)
code string 부서 코드 (unique)
name string 부서명
description string 부서 설명
is_active bool 활성화 상태
sort_order int 정렬 순서
created_by int 생성자
updated_by int 수정자
deleted_by int 삭제자

트리 응답 구조

[
  {
    "id": 1,
    "tenant_id": 1,
    "parent_id": null,
    "code": "DEPT001",
    "name": "경영지원본부",
    "is_active": true,
    "sort_order": 1,
    "children": [
      {
        "id": 2,
        "tenant_id": 1,
        "parent_id": 1,
        "code": "DEPT002",
        "name": "인사팀",
        "is_active": true,
        "sort_order": 1,
        "children": [],
        "users": []
      },
      {
        "id": 3,
        "tenant_id": 1,
        "parent_id": 1,
        "code": "DEPT003",
        "name": "재무팀",
        "is_active": true,
        "sort_order": 2,
        "children": [],
        "users": []
      }
    ],
    "users": [
      { "id": 1, "name": "홍길동", "email": "hong@example.com" }
    ]
  }
]

트리 조회 로직

tree() 메서드 구현

public function tree(array $params = []): array
{
    // 1. 파라미터 검증
    $withUsers = filter_var($params['with_users'] ?? false, FILTER_VALIDATE_BOOLEAN);

    // 2. 최상위 부서 조회 (parent_id가 null)
    $query = Department::query()
        ->whereNull('parent_id')
        ->orderBy('sort_order')
        ->orderBy('name');

    // 3. 재귀적으로 자식 부서 로드
    $query->with(['children' => function ($q) use ($withUsers) {
        $q->orderBy('sort_order')->orderBy('name');
        $this->loadChildrenRecursive($q, $withUsers);
    }]);

    // 4. 사용자 포함 옵션
    if ($withUsers) {
        $query->with(['users:id,name,email']);
    }

    return $query->get()->toArray();
}

// 재귀 로딩 헬퍼
private function loadChildrenRecursive($query, bool $withUsers): void
{
    $query->with(['children' => function ($q) use ($withUsers) {
        $q->orderBy('sort_order')->orderBy('name');
        $this->loadChildrenRecursive($q, $withUsers);
    }]);

    if ($withUsers) {
        $query->with(['users:id,name,email']);
    }
}

정렬 규칙

  1. sort_order 오름차순
  2. name 오름차순 (동일 sort_order일 때)

요청 파라미터

GET /v1/departments/tree

파라미터 타입 기본값 설명
with_users bool false 부서별 사용자 목록 포함

예시

# 기본 트리 조회
GET /v1/departments/tree

# 사용자 포함 트리 조회
GET /v1/departments/tree?with_users=1

관계 (Relationships)

public function parent(): BelongsTo   // 상위 부서
public function children()            // 하위 부서들 (HasMany)
public function users()               // 소속 사용자들 (BelongsToMany)
public function departmentUsers()     // 부서-사용자 pivot (HasMany)
public function permissionOverrides() // 권한 오버라이드 (MorphMany)

부서-사용자 관계 (Pivot)

department_user 테이블

필드 타입 설명
department_id int 부서 ID
user_id int 사용자 ID
tenant_id int 테넌트 ID
is_primary bool 주부서 여부
joined_at timestamp 배정일
left_at timestamp 해제일
deleted_at timestamp Soft Delete

주부서 규칙

  • 한 사용자는 여러 부서에 소속 가능
  • 주부서(is_primary)는 사용자당 1개만 가능
  • 주부서 설정 시 기존 주부서는 자동 해제

권한 관리

부서 권한 시스템

부서는 Spatie Permission과 연동되어 권한을 가질 수 있습니다.

  • ALLOW: model_has_permissions 테이블
  • DENY: permission_overrides 테이블 (effect: -1)

관련 엔드포인트

Method Path 설명
GET /v1/departments/{id}/permissions 부서 권한 목록
POST /v1/departments/{id}/permissions 권한 부여/차단
DELETE /v1/departments/{id}/permissions/{permission} 권한 제거

주의사항

  1. 무한 재귀 방지: Eloquent eager loading으로 처리, 별도 depth 제한 없음
  2. 성능 고려: 대규모 조직도의 경우 with_users 사용 시 응답 시간 증가
  3. 정렬 일관성: 모든 레벨에서 동일한 정렬 규칙 적용
  4. 멀티테넌트: tenant_id 기반 자동 스코핑
  5. 주부서 제약: 사용자당 주부서 1개만 허용
  6. Soft Delete: department_user pivot도 Soft Delete 적용

트리 구축 예시

조직도 예시

경영지원본부 (parent_id: null)
├── 인사팀 (parent_id: 1)
│   ├── 채용파트 (parent_id: 2)
│   └── 교육파트 (parent_id: 2)
├── 재무팀 (parent_id: 1)
└── 총무팀 (parent_id: 1)

개발본부 (parent_id: null)
├── 프론트엔드팀 (parent_id: 4)
├── 백엔드팀 (parent_id: 4)
└── QA팀 (parent_id: 4)

SQL 예시 (데이터 삽입)

-- 최상위 부서
INSERT INTO departments (tenant_id, parent_id, code, name, sort_order)
VALUES (1, NULL, 'HQ', '경영지원본부', 1);

-- 하위 부서
INSERT INTO departments (tenant_id, parent_id, code, name, sort_order)
VALUES (1, 1, 'HR', '인사팀', 1);