# 권한 관리 시스템 현황 분석

> 작성일: 2026-01-07
> 최종 수정일: 2026-01-12
> 목적: SAM 프로젝트 권한 시스템 현황 파악 및 향후 구현 계획 정리

---

## 1. 현재 상태 요약

| 구분 | 상태 | 설명 |
|------|------|------|
| 권한 설정 UI | ✅ 완성 | `/settings/permissions/[id]`에서 역할별 권한 설정 가능 |
| 백엔드 권한 API | ✅ 완성 | 권한 매트릭스 조회/설정 API 구현됨 |
| 백엔드 API 권한 체크 | ⚠️ 구조만 있음 | 미들웨어 존재하나 라우트에 미적용 |
| 프론트 권한 체크 | ❌ 미구현 | 권한 매트릭스 조회 및 UI 제어 로직 없음 |

---

## 2. 권한 타입 (5가지)

| 권한 | 영문 | 적용 대상 |
|------|------|----------|
| 조회 | `view` | 페이지 접근 |
| 생성 | `create` | 등록/추가 버튼 |
| 수정 | `update` | 수정 버튼 |
| 삭제 | `delete` | 삭제 버튼 |
| 승인 | `approve` | 승인/반려 버튼 |

> ⚠️ **참고**: `export`, `manage` 권한은 백엔드에 미구현 상태

---

## 3. 백엔드 API 구조

### 3.1 로그인 API

**엔드포인트**: `POST /api/v1/login`

**응답 구조**:
```json
{
  "access_token": "...",
  "refresh_token": "...",
  "user": { "id": 1, "name": "..." },
  "menus": [...],
  "roles": [...]
}
```

> ⚠️ **주의**: 로그인 응답에 **권한 매트릭스(permissions)는 포함되지 않음**

### 3.2 권한 매트릭스 조회 API

**사용자별 권한 조회** (프론트엔드에서 사용):
```
GET /api/v1/permissions/users/{userId}/menu-matrix
```

**실제 응답 구조**:
```json
{
  "success": true,
  "message": "유저 메뉴 권한 매트릭스 조회 성공",
  "data": {
    "actions": ["view", "create", "update", "delete", "approve"],
    "tree": [
      {
        "menu_id": 1,
        "parent_id": null,
        "name": "대시보드",
        "url": "/dashboard",
        "type": "system",
        "children": [
          {
            "menu_id": 2,
            "parent_id": 1,
            "name": "CEO 대시보드",
            "url": "/dashboard/ceo",
            "children": [],
            "actions": { ... }
          }
        ],
        "actions": {
          "view": {
            "permission_id": 123,
            "permission_code": "menu:1.view",
            "guard_name": "api",
            "state": "allow",
            "is_allowed": 1
          },
          "create": {
            "permission_id": 124,
            "permission_code": "menu:1.create",
            "guard_name": "api",
            "state": "deny",
            "is_allowed": 0
          },
          "update": null,
          "delete": null,
          "approve": null
        }
      }
    ]
  }
}
```

**권한 상태 값**:
| state | is_allowed | 의미 |
|-------|------------|------|
| `allow` | 1 | 권한 허용됨 |
| `deny` | 0 | 권한 명시적 거부 |
| `none` | 0 | 권한 미설정 (기본 거부) |

**actions가 null인 경우**: 해당 메뉴에 해당 권한이 정의되지 않음

### 3.3 권한 매트릭스 API 목록

| 엔드포인트 | 메서드 | 설명 |
|-----------|--------|------|
| `/api/v1/permissions/users/{user_id}/menu-matrix` | GET | 사용자별 권한 매트릭스 |
| `/api/v1/permissions/roles/{role_id}/menu-matrix` | GET | 역할별 권한 매트릭스 |
| `/api/v1/permissions/departments/{dept_id}/menu-matrix` | GET | 부서별 권한 매트릭스 |

### 3.4 역할 권한 관리 API

| 엔드포인트 | 메서드 | 설명 |
|-----------|--------|------|
| `/api/v1/role-permissions/menus` | GET | 권한 설정용 메뉴 트리 |
| `/api/v1/roles/{id}/permissions` | GET | 역할 권한 목록 |
| `/api/v1/roles/{id}/permissions` | POST | 역할 권한 부여 |
| `/api/v1/roles/{id}/permissions` | DELETE | 역할 권한 회수 |
| `/api/v1/roles/{id}/permissions/sync` | PUT | 역할 권한 동기화 |
| `/api/v1/roles/{id}/permissions/matrix` | GET | 역할 권한 매트릭스 (설정 UI용) |
| `/api/v1/roles/{id}/permissions/toggle` | POST | 개별 권한 토글 |
| `/api/v1/roles/{id}/permissions/allow-all` | POST | 전체 허용 |
| `/api/v1/roles/{id}/permissions/deny-all` | POST | 전체 거부 |
| `/api/v1/roles/{id}/permissions/reset` | POST | 기본값 초기화 (view만 허용) |

---

## 4. 백엔드 권한 체크 미들웨어

### 4.1 CheckPermission.php

```php
// 권한 체크 로직
if (! AccessService::allows($user, $perm, $tenantId, 'api')) {
    return response()->json(['message' => '권한이 없습니다.'], 403);
}

// 단, perm 미지정 라우트는 통과 (현재 정책)
if (! $perm && ! $permsAny) {
    return $next($request);  // ← 현재 모든 API가 여기로 통과
}
```

### 4.2 PermMapper.php

HTTP 메서드에 따라 액션 자동 매핑:

| HTTP 메서드 | 권한 액션 |
|------------|----------|
| GET, HEAD | view |
| POST | create |
| PUT, PATCH | update |
| DELETE | delete |

**권한 형식**: `menu:{menuId}.{action}` (예: `menu:1.view`)

### 4.3 현재 상태

- 미들웨어 구조는 갖춰져 있음
- **라우트에 `menu_id` 설정이 안 되어 있어 실제 권한 체크 미동작**
- 모든 API가 권한 체크 없이 통과

---

## 5. 프론트엔드 현재 상태

### 5.1 구현된 것

- 로그인 시 `menus`, `roles` 데이터 저장 (localStorage)
- 사이드바 메뉴 표시 (백엔드에서 필터링된 메뉴)
- 메뉴 폴링 (30초 주기)
- 역할별 권한 설정 UI (`/settings/permissions/[id]`)

### 5.2 미구현 사항

- 권한 매트릭스 API 호출
- 권한 데이터 저장 (permissionStore)
- `usePermission` 훅
- 페이지/버튼별 권한 체크
- 환경 변수 플래그

---

## 6. 향후 구현 계획

### 6.1 프론트엔드 (1단계 - UI 제어)

```
로그인 성공
    ↓
/api/v1/permissions/users/{userId}/menu-matrix 호출
    ↓
권한 매트릭스 저장 (Zustand permissionStore)
    ↓
usePermission 훅으로 권한 체크
    ↓
버튼/기능 숨김/비활성화
```

**usePermission 훅 예시**:
```typescript
// 사용법 (메뉴명 또는 URL로 조회)
const { canView, canCreate, canUpdate, canDelete, canApprove } = usePermission('/sales/orders');

// 적용
{canCreate && <Button>등록</Button>}
{canDelete && <Button>삭제</Button>}
{canApprove && <Button>승인</Button>}
```

**환경 변수 플래그**:
```env
NEXT_PUBLIC_ENABLE_AUTHORIZATION=false  # 개발 중에는 비활성화
```

### 6.2 백엔드 (2단계 - API 보안)

라우트에 `menu_id` 설정하여 API 레벨 권한 체크 활성화:

```php
// 예시: routes/api.php
Route::get('/orders', [OrderController::class, 'index'])
    ->defaults('menu_id', 5);  // 판매관리 메뉴 ID

Route::post('/orders', [OrderController::class, 'store'])
    ->defaults('menu_id', 5);  // POST → create 권한 자동 체크
```

---

## 7. 보안 고려사항

### 7.1 현재 취약점

- 프론트에서만 UI 숨기면 개발자 도구로 우회 가능
- 직접 API 호출 시 권한 없이도 작업 가능

### 7.2 권장 구조 (이중 보안)

```
프론트엔드: UI 컨트롤 (UX 향상)
    ↓
백엔드: API 권한 체크 (실제 보안)
    ↓
권한 없으면 403 반환
```

---

## 8. 관련 파일 경로

### 프론트엔드 (sam-react-prod)

| 파일 | 설명 |
|------|------|
| `src/app/[locale]/(protected)/settings/permissions/` | 권한 설정 페이지 |
| `src/components/settings/PermissionManagement/` | 권한 관리 컴포넌트 |
| `src/layouts/AuthenticatedLayout.tsx` | 메뉴 표시 레이아웃 |
| `src/middleware.ts` | 인증 체크 (권한 체크 없음) |
| `src/store/menuStore.ts` | 메뉴 상태 관리 |

### 백엔드 (sam-api)

| 파일 | 설명 |
|------|------|
| `app/Http/Controllers/Api/V1/PermissionController.php` | 권한 매트릭스 API |
| `app/Http/Controllers/Api/V1/RolePermissionController.php` | 역할 권한 API |
| `app/Http/Middleware/CheckPermission.php` | 권한 체크 미들웨어 |
| `app/Http/Middleware/PermMapper.php` | HTTP → 액션 매핑 |
| `app/Services/PermissionService.php` | 권한 매트릭스 서비스 |
| `app/Services/Authz/AccessService.php` | 권한 판정 서비스 |
| `app/Services/Authz/RolePermissionService.php` | 역할 권한 서비스 |

---

## 9. 결론

**현재**: 권한 설정은 가능하지만, 프론트/백엔드 모두 권한 체크 미적용

**1단계 (프론트)**:
- 로그인 후 권한 매트릭스 API 호출
- usePermission 훅으로 UI 제어
- 환경 변수로 개발 중 비활성화

**2단계 (백엔드)**:
- 라우트에 menu_id 설정
- API 레벨 권한 체크 활성화

---

*이 문서는 권한 시스템 구현 시 참고용으로 작성되었습니다.*