From 0c86b390add701885c44c0e71d6858fe69939356 Mon Sep 17 00:00:00 2001 From: hskwon Date: Mon, 24 Nov 2025 18:49:02 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EB=B0=8F=20MNG=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MNG_CRITICAL_RULES.md: DB 마이그레이션 금지 등 핵심 규칙 - UserController: 사용자 CRUD API 엔드포인트 - StoreUserRequest, UpdateUserRequest: 사용자 검증 - 사용자 관리 뷰: index, create, edit, table - 시스템 관리 메뉴 UI 개선 (테이블 헤더 스타일) - docs/INDEX.md: CRITICAL_RULES 링크 추가 --- .../Controllers/Api/Admin/UserController.php | 143 +++++++++++ app/Http/Controllers/UserController.php | 44 ++++ app/Http/Requests/StoreUserRequest.php | 71 ++++++ app/Http/Requests/UpdateUserRequest.php | 83 +++++++ docs/INDEX.md | 1 + docs/MNG_CRITICAL_RULES.md | 234 ++++++++++++++++++ .../departments/partials/table.blade.php | 12 +- resources/views/partials/sidebar.blade.php | 4 +- .../views/roles/partials/table.blade.php | 12 +- .../views/tenants/partials/table.blade.php | 24 +- resources/views/users/create.blade.php | 164 ++++++++++++ resources/views/users/edit.blade.php | 194 +++++++++++++++ resources/views/users/index.blade.php | 92 +++++++ .../views/users/partials/table.blade.php | 71 ++++++ routes/api.php | 10 + routes/web.php | 8 + 16 files changed, 1141 insertions(+), 26 deletions(-) create mode 100644 app/Http/Controllers/Api/Admin/UserController.php create mode 100644 app/Http/Controllers/UserController.php create mode 100644 app/Http/Requests/StoreUserRequest.php create mode 100644 app/Http/Requests/UpdateUserRequest.php create mode 100644 docs/MNG_CRITICAL_RULES.md create mode 100644 resources/views/users/create.blade.php create mode 100644 resources/views/users/edit.blade.php create mode 100644 resources/views/users/index.blade.php create mode 100644 resources/views/users/partials/table.blade.php diff --git a/app/Http/Controllers/Api/Admin/UserController.php b/app/Http/Controllers/Api/Admin/UserController.php new file mode 100644 index 00000000..2e3ee4a3 --- /dev/null +++ b/app/Http/Controllers/Api/Admin/UserController.php @@ -0,0 +1,143 @@ +userService->getUsers( + $request->all(), + $request->integer('per_page', 15) + ); + + // HTMX 요청인 경우 HTML 반환 + if ($request->header('HX-Request')) { + $html = view('users.partials.table', compact('users'))->render(); + return response()->json(['html' => $html]); + } + + // 일반 API 요청인 경우 JSON 반환 + return response()->json([ + 'success' => true, + 'data' => $users->items(), + 'meta' => [ + 'current_page' => $users->currentPage(), + 'last_page' => $users->lastPage(), + 'per_page' => $users->perPage(), + 'total' => $users->total(), + ], + ]); + } + + /** + * 사용자 상세 조회 + */ + public function show(int $id): JsonResponse + { + $user = $this->userService->getUserById($id); + + if (!$user) { + return response()->json([ + 'success' => false, + 'message' => '사용자를 찾을 수 없습니다.', + ], 404); + } + + return response()->json([ + 'success' => true, + 'data' => $user, + ]); + } + + /** + * 사용자 생성 + */ + public function store(StoreUserRequest $request): JsonResponse + { + try { + $user = $this->userService->createUser($request->validated()); + + return response()->json([ + 'success' => true, + 'message' => '사용자가 생성되었습니다.', + 'data' => $user, + 'redirect' => route('users.index'), + ], 201); + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => '사용자 생성에 실패했습니다: ' . $e->getMessage(), + ], 500); + } + } + + /** + * 사용자 수정 + */ + public function update(UpdateUserRequest $request, int $id): JsonResponse + { + try { + $result = $this->userService->updateUser($id, $request->validated()); + + if (!$result) { + return response()->json([ + 'success' => false, + 'message' => '사용자를 찾을 수 없습니다.', + ], 404); + } + + return response()->json([ + 'success' => true, + 'message' => '사용자가 수정되었습니다.', + 'redirect' => route('users.index'), + ]); + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => '사용자 수정에 실패했습니다: ' . $e->getMessage(), + ], 500); + } + } + + /** + * 사용자 삭제 + */ + public function destroy(int $id): JsonResponse + { + try { + $result = $this->userService->deleteUser($id); + + if (!$result) { + return response()->json([ + 'success' => false, + 'message' => '사용자를 찾을 수 없습니다.', + ], 404); + } + + return response()->json([ + 'success' => true, + 'message' => '사용자가 삭제되었습니다.', + ]); + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => '사용자 삭제에 실패했습니다: ' . $e->getMessage(), + ], 500); + } + } +} \ No newline at end of file diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 00000000..cd76c2b4 --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,44 @@ +userService->getUserById($id); + + if (!$user) { + abort(404, '사용자를 찾을 수 없습니다.'); + } + + return view('users.edit', compact('user')); + } +} \ No newline at end of file diff --git a/app/Http/Requests/StoreUserRequest.php b/app/Http/Requests/StoreUserRequest.php new file mode 100644 index 00000000..3a428273 --- /dev/null +++ b/app/Http/Requests/StoreUserRequest.php @@ -0,0 +1,71 @@ +|string> + */ + public function rules(): array + { + return [ + 'user_id' => 'nullable|string|max:50|unique:users,user_id', + 'name' => 'required|string|max:100', + 'email' => 'required|email|max:255|unique:users,email', + 'phone' => 'nullable|string|max:20', + 'password' => 'required|string|min:8|confirmed', + 'role' => 'nullable|string|max:50', + 'is_active' => 'nullable|boolean', + 'is_super_admin' => 'nullable|boolean', + ]; + } + + /** + * Get custom attributes for validator errors. + * + * @return array + */ + public function attributes(): array + { + return [ + 'user_id' => '사용자 ID', + 'name' => '이름', + 'email' => '이메일', + 'phone' => '연락처', + 'password' => '비밀번호', + 'password_confirmation' => '비밀번호 확인', + 'role' => '역할', + 'is_active' => '활성 상태', + 'is_super_admin' => '슈퍼 관리자', + ]; + } + + /** + * Get custom messages for validator errors. + * + * @return array + */ + public function messages(): array + { + return [ + 'email.unique' => '이미 사용 중인 이메일입니다.', + 'user_id.unique' => '이미 사용 중인 사용자 ID입니다.', + 'password.confirmed' => '비밀번호가 일치하지 않습니다.', + 'password.min' => '비밀번호는 최소 8자 이상이어야 합니다.', + ]; + } +} \ No newline at end of file diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php new file mode 100644 index 00000000..7e404342 --- /dev/null +++ b/app/Http/Requests/UpdateUserRequest.php @@ -0,0 +1,83 @@ +|string> + */ + public function rules(): array + { + $userId = $this->route('id'); + + return [ + 'user_id' => [ + 'nullable', + 'string', + 'max:50', + Rule::unique('users', 'user_id')->ignore($userId), + ], + 'name' => 'required|string|max:100', + 'email' => [ + 'required', + 'email', + 'max:255', + Rule::unique('users', 'email')->ignore($userId), + ], + 'phone' => 'nullable|string|max:20', + 'password' => 'nullable|string|min:8|confirmed', + 'role' => 'nullable|string|max:50', + 'is_active' => 'nullable|boolean', + 'is_super_admin' => 'nullable|boolean', + ]; + } + + /** + * Get custom attributes for validator errors. + * + * @return array + */ + public function attributes(): array + { + return [ + 'user_id' => '사용자 ID', + 'name' => '이름', + 'email' => '이메일', + 'phone' => '연락처', + 'password' => '비밀번호', + 'password_confirmation' => '비밀번호 확인', + 'role' => '역할', + 'is_active' => '활성 상태', + 'is_super_admin' => '슈퍼 관리자', + ]; + } + + /** + * Get custom messages for validator errors. + * + * @return array + */ + public function messages(): array + { + return [ + 'email.unique' => '이미 사용 중인 이메일입니다.', + 'user_id.unique' => '이미 사용 중인 사용자 ID입니다.', + 'password.confirmed' => '비밀번호가 일치하지 않습니다.', + 'password.min' => '비밀번호는 최소 8자 이상이어야 합니다.', + ]; + } +} \ No newline at end of file diff --git a/docs/INDEX.md b/docs/INDEX.md index 38dbb2b8..32f982a4 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -67,6 +67,7 @@ ### 현재 진행 상황 - ⏳ **Phase 6**: BOM/카테고리 관리 ### 프로젝트 문서 +- **[🚨 MNG_CRITICAL_RULES.md](./MNG_CRITICAL_RULES.md)** - 절대 위반 금지 규칙 (필독!) - **[CURRENT_WORKS.md](../CURRENT_WORKS.md)** - 현재 작업 진행 상황 - **[MIGRATION_PLAN.md](./MIGRATION_PLAN.md)** - Admin → MNG 마이그레이션 계획 (Phase 4) - **[claudedocs/mng/MNG_PROJECT_PLAN.md](../../claudedocs/mng/MNG_PROJECT_PLAN.md)** - 전체 프로젝트 계획 diff --git a/docs/MNG_CRITICAL_RULES.md b/docs/MNG_CRITICAL_RULES.md new file mode 100644 index 00000000..85514606 --- /dev/null +++ b/docs/MNG_CRITICAL_RULES.md @@ -0,0 +1,234 @@ +# MNG 프로젝트 Critical Rules + +> 🚨 **절대 위반하지 말아야 할 규칙들** + +**작성일**: 2025-11-24 +**목적**: 반복되는 실수 방지 및 프로젝트 정책 명확화 + +--- + +## 🚫 절대 금지 사항 + +### 1. DB 마이그레이션 금지 + +**규칙:** +- ❌ mng/에서는 **절대로** 마이그레이션 파일 생성 금지 +- ❌ 기존 테이블 구조 변경 금지 +- ✅ 모델 관계 정의만 가능 +- ✅ 필요 시 api/에 마이그레이션 요청 + +**이유:** +- mng/는 api/의 DB를 **읽기 전용**으로 사용 +- DB 스키마는 **api/에서만** 관리 +- 여러 저장소(api, admin, mng)가 동일 DB 공유 + +**예외:** +- `admin_*` 접두사 테이블만 mng/에서 생성 가능 (mng 전용 기능용) +- 그래도 가능하면 api/에 요청 권장 + +**실수 사례:** +```php +// ❌ 잘못된 예: mng/에서 users 테이블 수정 시도 +Schema::table('users', function (Blueprint $table) { + $table->foreignId('tenant_id')->comment('테넌트 ID'); +}); + +// ✅ 올바른 예: User 모델에 관계만 정의 +public function tenants(): BelongsToMany +{ + return $this->belongsToMany(Tenant::class, 'user_tenants'); +} +``` + +--- + +### 2. 기존 테이블은 재사용만 + +**재사용 테이블:** +- `users` - 사용자 계정 +- `tenants` - 테넌트 (회사) +- `user_tenants` - 사용자-테넌트 관계 (pivot) +- `roles` - 역할 +- `departments` - 부서 +- `permissions` - 권한 +- `products`, `materials`, `categories` 등 모든 비즈니스 테이블 + +**작업 방법:** +1. **모델 복사**: admin/app/Models → mng/app/Models +2. **Filament 코드 제거**: form(), table() 등 제거 +3. **관계만 유지**: belongsTo, hasMany, belongsToMany +4. **Traits 적용**: BelongsToTenant (필요 시), SoftDeletes + +--- + +### 3. Multi-tenant 아키텍처 이해 + +**user_tenants pivot 테이블 구조:** +``` +user_tenants: +├── user_id (FK → users) +├── tenant_id (FK → tenants) +├── is_active (활성 여부) +├── is_default (기본 테넌트) +├── joined_at (가입일) +└── left_at (탈퇴일) +``` + +**관계 정의:** +```php +// User 모델 +public function tenants(): BelongsToMany +{ + return $this->belongsToMany(Tenant::class, 'user_tenants') + ->withTimestamps() + ->withPivot(['is_active', 'is_default', 'joined_at', 'left_at']); +} + +// Tenant 모델 +public function users(): BelongsToMany +{ + return $this->belongsToMany(User::class, 'user_tenants'); +} +``` + +**세션 기반 테넌트 선택:** +- `session('selected_tenant_id')` - 현재 선택된 테넌트 +- `currentTenant()` 헬퍼 메서드 사용 권장 + +--- + +### 4. BelongsToTenant Trait 사용 주의 + +**언제 사용하지 말아야 하나:** +- ❌ `users` 테이블 - user_tenants pivot 사용 +- ❌ `tenants` 테이블 - 테넌트 자체 +- ❌ 다대다 관계 테이블 + +**언제 사용해야 하나:** +- ✅ `roles` - tenant_id 컬럼 있음 +- ✅ `departments` - tenant_id 컬럼 있음 +- ✅ `products` - tenant_id 컬럼 있음 + +**판단 기준:** +- 테이블에 직접 `tenant_id` 컬럼이 있으면 → BelongsToTenant 사용 +- pivot 테이블로 관계가 맺어지면 → belongsToMany 관계만 정의 + +--- + +### 5. Service-First 패턴 엄수 + +**규칙:** +- ✅ 비즈니스 로직은 **Service 클래스**에만 +- ✅ Controller는 FormRequest + Service 호출만 +- ✅ Model은 관계와 accessor만 + +**잘못된 예:** +```php +// ❌ Controller에 로직 +public function store(Request $request) +{ + $user = User::create($request->all()); + $user->tenant_id = session('selected_tenant_id'); + $user->save(); +} +``` + +**올바른 예:** +```php +// ✅ Service에 로직 +class UserService +{ + public function createUser(array $data): User + { + // 비즈니스 로직 + return User::create($data); + } +} + +// Controller는 호출만 +public function store(StoreUserRequest $request, UserService $service) +{ + $user = $service->createUser($request->validated()); + return response()->json(['success' => true]); +} +``` + +--- + +### 6. FormRequest 필수 사용 + +**규칙:** +- ❌ Controller에서 `$request->validate()` 금지 +- ✅ 모든 검증은 FormRequest 클래스로 + +**예:** +```php +// ✅ StoreUserRequest.php +class StoreUserRequest extends FormRequest +{ + public function rules(): array + { + return [ + 'name' => 'required|string|max:255', + 'email' => 'required|email|unique:users', + ]; + } +} + +// ✅ Controller +public function store(StoreUserRequest $request) +{ + // $request->validated() 만 Service에 전달 +} +``` + +--- + +## 📋 작업 전 체크리스트 + +### DB 작업 시: +``` +□ mng/에서 작업 중인가? → 마이그레이션 금지! +□ 기존 테이블 수정인가? → api/에 요청! +□ 새 테이블인가? → admin_* 접두사 OR api/에 요청! +□ 관계만 추가인가? → OK, 모델만 수정 +``` + +### 모델 작업 시: +``` +□ tenant_id 컬럼 있는가? → BelongsToTenant trait +□ pivot 테이블 사용하는가? → belongsToMany 관계만 +□ 비즈니스 로직 있는가? → Service로 이동! +``` + +### Controller 작업 시: +``` +□ FormRequest 생성했는가? +□ Service 클래스 생성했는가? +□ Controller는 호출만 하는가? +``` + +--- + +## 🔗 관련 문서 + +- **[INDEX.md](./INDEX.md)** - MNG 프로젝트 개요 +- **[MIGRATION_PLAN.md](./MIGRATION_PLAN.md)** - Admin → MNG 마이그레이션 +- **[DEV_PROCESS.md](../../claudedocs/mng/DEV_PROCESS.md)** - 개발 프로세스 +- **[database-schema.md](../../docs/specs/database-schema.md)** - DB 스키마 +- **[api-rules.md](../../docs/reference/api-rules.md)** - API 개발 규칙 + +--- + +## 📝 실수 사례 로그 + +### 2025-11-24: users 테이블 마이그레이션 시도 +- **문제**: mng/에서 users 테이블에 tenant_id 추가 시도 +- **원인**: user_tenants pivot 테이블 존재를 간과 +- **교훈**: 다대다 관계는 belongsToMany로, 마이그레이션 금지 +- **해결**: User 모델에 tenants() 관계만 추가 + +--- + +**최종 업데이트**: 2025-11-24 +**다음 리뷰**: 반복 실수 발생 시 업데이트 diff --git a/resources/views/departments/partials/table.blade.php b/resources/views/departments/partials/table.blade.php index 87c66070..47fcfb70 100644 --- a/resources/views/departments/partials/table.blade.php +++ b/resources/views/departments/partials/table.blade.php @@ -1,12 +1,12 @@ - - - - - - + + + + + + diff --git a/resources/views/partials/sidebar.blade.php b/resources/views/partials/sidebar.blade.php index 206eaaad..60d321cc 100644 --- a/resources/views/partials/sidebar.blade.php +++ b/resources/views/partials/sidebar.blade.php @@ -33,8 +33,8 @@ class="flex items-center gap-3 px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-
  • - + diff --git a/resources/views/roles/partials/table.blade.php b/resources/views/roles/partials/table.blade.php index bd9bda7c..fcf4eb9e 100644 --- a/resources/views/roles/partials/table.blade.php +++ b/resources/views/roles/partials/table.blade.php @@ -2,12 +2,12 @@
  • 부서 코드부서명상위 부서상태정렬순서작업부서 코드부서명상위 부서상태정렬순서작업
    - - - - - - + + + + + + diff --git a/resources/views/tenants/partials/table.blade.php b/resources/views/tenants/partials/table.blade.php index 2a34be44..3f25e1f7 100644 --- a/resources/views/tenants/partials/table.blade.php +++ b/resources/views/tenants/partials/table.blade.php @@ -2,18 +2,18 @@
    ID역할 이름설명권한 수생성일액션ID역할 이름설명권한 수생성일액션
    - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/resources/views/users/create.blade.php b/resources/views/users/create.blade.php new file mode 100644 index 00000000..9bc0c59e --- /dev/null +++ b/resources/views/users/create.blade.php @@ -0,0 +1,164 @@ +@extends('layouts.app') + +@section('title', '사용자 생성') + +@section('content') +
    + + + + +
    +
    + + +
    +

    기본 정보

    +
    +
    + + +

    비워두면 자동 생성됩니다.

    +
    +
    + + +
    +
    +
    + + +
    +

    계정 정보

    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +

    비밀번호

    +
    +
    + + +

    최소 8자 이상 입력하세요.

    +
    +
    + + +
    +
    +
    + + +
    +

    권한 설정

    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    + + 취소 + + +
    + +
    +
    +@endsection + +@push('scripts') + + +@endpush \ No newline at end of file diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php new file mode 100644 index 00000000..d397b7f1 --- /dev/null +++ b/resources/views/users/edit.blade.php @@ -0,0 +1,194 @@ +@extends('layouts.app') + +@section('title', '사용자 수정') + +@section('content') +
    + +
    +

    👥 사용자 수정

    + + ← 목록으로 + +
    + + +
    +
    + + + +
    +

    기본 정보

    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +

    계정 정보

    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +

    비밀번호 변경

    +
    +
    + + +

    변경하지 않으려면 비워두세요.

    +
    +
    + + +
    +
    +
    + + +
    +

    권한 설정

    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +

    사용자 정보

    +
    +
    + 생성일: + {{ $user->created_at?->format('Y-m-d H:i') ?? '-' }} +
    +
    + 수정일: + {{ $user->updated_at?->format('Y-m-d H:i') ?? '-' }} +
    +
    + 마지막 로그인: + {{ $user->last_login_at?->format('Y-m-d H:i') ?? '없음' }} +
    +
    + 사용자 ID: + #{{ $user->id }} +
    +
    +
    + + +
    + + 취소 + + +
    + +
    +
    +@endsection + +@push('scripts') + + +@endpush \ No newline at end of file diff --git a/resources/views/users/index.blade.php b/resources/views/users/index.blade.php new file mode 100644 index 00000000..5fe5333f --- /dev/null +++ b/resources/views/users/index.blade.php @@ -0,0 +1,92 @@ +@extends('layouts.app') + +@section('title', '사용자 관리') + +@section('content') + + @include('partials.tenant-selector') + + +
    +

    👥 사용자 관리

    + + + 새 사용자 + +
    + + +
    +
    + +
    + +
    + + +
    + +
    + + + + +
    + + +
    + +
    +
    +
    +
    +@endsection + +@push('scripts') + + +@endpush \ No newline at end of file diff --git a/resources/views/users/partials/table.blade.php b/resources/views/users/partials/table.blade.php new file mode 100644 index 00000000..a302507a --- /dev/null +++ b/resources/views/users/partials/table.blade.php @@ -0,0 +1,71 @@ +
    +
    ID회사명코드상태이메일전화번호사용자부서메뉴역할생성일액션ID회사명코드상태이메일전화번호사용자부서메뉴역할생성일액션
    + + + + + + + + + + + + + @forelse($users as $user) + + + + + + + + + + @empty + + + + @endforelse + +
    ID이름이메일연락처테넌트상태작업
    + {{ $user->user_id ?? '-' }} + +
    {{ $user->name }}
    + @if($user->is_super_admin) + 슈퍼 관리자 + @endif +
    + {{ $user->email }} + + {{ $user->phone ?? '-' }} + + {{ $user->currentTenant()?->company_name ?? '-' }} + + @if($user->is_active) + + 활성 + + @else + + 비활성 + + @endif + + + 수정 + + +
    + 사용자가 없습니다. +
    + + + +@include('partials.pagination', [ + 'paginator' => $users, + 'target' => '#user-table', + 'includeForm' => '#filterForm' +]) \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 15b44511..939f8829 100644 --- a/routes/api.php +++ b/routes/api.php @@ -3,6 +3,7 @@ use App\Http\Controllers\Api\Admin\DepartmentController; use App\Http\Controllers\Api\Admin\RoleController; use App\Http\Controllers\Api\Admin\TenantController; +use App\Http\Controllers\Api\Admin\UserController; use Illuminate\Support\Facades\Route; /* @@ -50,4 +51,13 @@ Route::put('/{id}', [DepartmentController::class, 'update'])->name('update'); Route::delete('/{id}', [DepartmentController::class, 'destroy'])->name('destroy'); }); + + // 사용자 관리 API + Route::prefix('users')->name('users.')->group(function () { + Route::get('/', [UserController::class, 'index'])->name('index'); + Route::post('/', [UserController::class, 'store'])->name('store'); + Route::get('/{id}', [UserController::class, 'show'])->name('show'); + Route::put('/{id}', [UserController::class, 'update'])->name('update'); + Route::delete('/{id}', [UserController::class, 'destroy'])->name('destroy'); + }); }); \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index fb0408b3..ed04c7b4 100644 --- a/routes/web.php +++ b/routes/web.php @@ -4,6 +4,7 @@ use App\Http\Controllers\DepartmentController; use App\Http\Controllers\RoleController; use App\Http\Controllers\TenantController; +use App\Http\Controllers\UserController; use Illuminate\Support\Facades\Route; /* @@ -50,6 +51,13 @@ Route::get('/{id}/edit', [DepartmentController::class, 'edit'])->name('edit'); }); + // 사용자 관리 (Blade 화면만) + Route::prefix('users')->name('users.')->group(function () { + Route::get('/', [UserController::class, 'index'])->name('index'); + Route::get('/create', [UserController::class, 'create'])->name('create'); + Route::get('/{id}/edit', [UserController::class, 'edit'])->name('edit'); + }); + // 대시보드 Route::get('/dashboard', function () { return view('dashboard.index');