# MNG 프로젝트 개발 계획서

## 📋 프로젝트 개요

### 목적
- **문제점**: 기존 admin/ (Filament v4)은 AI 없이 수정이 어려움
- **목표**: 수정 용이한 Plain Laravel 기반 관리자 패널 구축
- **도메인**: mng.sam.kr
- **철학**: **단순함 > 복잡함**, AI 없이도 수정 가능한 직관적 코드

### 핵심 전략
```
┌─────────────────────────────────────────────┐
│  MNG (mng.sam.kr)                          │
│  ┌──────────────┐     ┌─────────────────┐  │
│  │ Web Routes   │────▶│ Blade + HTMX    │  │ ← DaisyUI (심플)
│  │ (세션 인증)   │     │ (수정 용이)      │  │
│  └──────────────┘     └─────────────────┘  │
│  ┌──────────────┐     ┌─────────────────┐  │
│  │ API Routes   │────▶│ Admin API       │  │ ← 처음부터 분리
│  │ (토큰 인증)   │     │ (관리자 전용)    │  │
│  └──────────────┘     └─────────────────┘  │
│         ↓                                   │
│  ┌──────────────────────────────────────┐  │
│  │ Service Layer (비즈니스 로직)         │  │ ← admin/ 복사
│  └──────────────────────────────────────┘  │
│         ↓                                   │
│  ┌──────────────────────────────────────┐  │
│  │ Models (admin/ 복사, Filament 제거)  │  │
│  └──────────────────────────────────────┘  │
└─────────────────┬───────────────────────────┘
                  ↓
    ┌─────────────────────────────┐
    │ MySQL 8.0 (공유 DB)          │
    │ - admin/ (점차 deprecated)  │
    │ - api/ (외부 API)           │
    │ - mng/ (새 관리자) ← 최종   │
    └─────────────────────────────┘
```

### 설계 원칙
1. **단순성**: 복잡한 추상화 금지, 인라인 코드 허용
2. **수정 용이성**: AI 없이도 Blade 템플릿 수정 가능
3. **코드 재사용**: admin/ 모델/서비스 복사 후 간소화
4. **DB 공유**: 기존 테이블 최대한 활용

---

## 🏗️ 아키텍처 설계

### 1. 디렉토리 구조
```
SAM/
├── admin/          # Filament (점차 deprecated)
├── api/            # 외부 클라이언트 API
├── mng/            # ⭐ 운영 관리자 패널 (NEW)
│   ├── app/
│   │   ├── Http/
│   │   │   ├── Controllers/
│   │   │   │   ├── Web/           # Blade 컨트롤러 (단순)
│   │   │   │   │   ├── Auth/
│   │   │   │   │   ├── Dashboard/
│   │   │   │   │   ├── User/
│   │   │   │   │   └── Product/
│   │   │   │   └── Api/           # Admin API (향후)
│   │   │   │       └── Admin/
│   │   │   ├── Requests/          # FormRequest (필수)
│   │   │   └── Middleware/
│   │   ├── Services/              # admin/ 복사 후 간소화
│   │   ├── Models/                # admin/ 복사, Filament 코드 제거
│   │   └── Traits/
│   │       ├── BelongsToTenant.php   # admin/에서 복사
│   │       └── HasAuditLog.php       # admin/에서 복사
│   ├── routes/
│   │   ├── web.php                # Blade 라우트
│   │   └── api.php                # Admin API (/api/admin/*)
│   ├── resources/
│   │   └── views/
│   │       ├── layouts/
│   │       │   ├── app.blade.php     # 단순 레이아웃
│   │       │   └── guest.blade.php
│   │       ├── auth/              # 로그인 화면
│   │       ├── dashboard/         # 대시보드
│   │       ├── users/             # 사용자 관리
│   │       └── products/          # 제품 관리
│   ├── database/
│   │   └── migrations/
│   │       └── # 관리자 전용: admin_*
│   │       └── # 통계 전용: stat_*
│   ├── tests/
│   │   └── Feature/
│   └── .env
├── docker/
│   └── nginx/
│       └── mng.sam.kr.conf
└── claudedocs/
    └── mng/
        ├── MNG_PROJECT_PLAN.md    # 이 문서
        ├── API_SPEC.md            # API 명세
        └── PROGRESS.md            # 진행 상황
```

### 2. 기술 스택 (확정)

| 레이어 | 기술 | 버전 | 비고 |
|--------|------|------|------|
| **백엔드** | Laravel | 12.x | PHP 8.4+ |
| **인증** | Sanctum | 4.x | 세션 + 토큰 |
| **DB** | **MySQL** | **8.0** | **admin, api와 공유** |
| **프론트엔드** | **Blade + HTMX** | **1.x** | **단순, 수정 용이** |
| **CSS** | **Tailwind CSS** | **3.x** | 기존과 통일 |
| **UI 컴포넌트** | **DaisyUI** | **4.x** | **심플, 클래스 기반** |
| **아이콘** | Heroicons | - | Tailwind 친화적 |
| **문서화** | L5-Swagger | - | Admin API 전용 |
| **테스트** | PHPUnit | - | Feature Test |

### 3. DB 테이블 명명 규칙 (변경)

#### 기존 테이블 재사용 (마이그레이션 없음)
```
✅ users, roles, departments
✅ products, materials, bom_items
✅ menus, menu_role
✅ audit_logs, categories, files
✅ tenants
```

#### 관리자 전용 테이블 (admin_* 접두사)
```php
// database/migrations/2025_01_20_create_admin_settings_table.php
Schema::create('admin_settings', function (Blueprint $table) {
    $table->id();
    $table->string('key')->unique();
    $table->text('value')->nullable();
    $table->string('type')->default('string'); // string, json, boolean
    $table->timestamps();
});

// 예시 테이블
- admin_settings        # 관리자 설정
- admin_logs           # 관리자 작업 로그
- admin_preferences    # 관리자 개인 설정
```

#### 통계 테이블 (stat_* 접두사)
```php
// database/migrations/2025_01_20_create_stat_daily_sales_table.php
Schema::create('stat_daily_sales', function (Blueprint $table) {
    $table->id();
    $table->date('date');
    $table->decimal('total_amount', 15, 2);
    $table->integer('order_count');
    $table->timestamps();

    $table->unique('date');
});

// 예시 테이블
- stat_daily_sales     # 일별 매출 통계
- stat_inventory       # 재고 통계
- stat_user_activity   # 사용자 활동 통계
```

### 4. 모델/서비스 복사 전략

#### admin/ → mng/ 복사 프로세스
```bash
# 1. 모델 복사 (Filament 의존성 제거)
cp -r admin/app/Models/* mng/app/Models/
# Filament 관련 코드 제거 (getNavigationLabel, form, table 등)

# 2. Traits 복사 (그대로 사용)
cp admin/app/Traits/BelongsToTenant.php mng/app/Traits/
cp admin/app/Traits/HasAuditLog.php mng/app/Traits/

# 3. Services 복사 (있다면)
cp -r admin/app/Services/* mng/app/Services/
# 또는 신규 작성 (Service-First 원칙)
```

#### 모델 예시 (Filament 제거)
```php
// admin/app/Models/User.php (Before)
class User extends Authenticatable implements FilamentUser
{
    use BelongsToTenant, HasAuditLog;

    public static function form(Form $form): Form { ... }  // ❌ 제거
    public static function table(Table $table): Table { ... }  // ❌ 제거
    public function canAccessPanel(Panel $panel): bool { ... }  // ❌ 제거
}

// mng/app/Models/User.php (After)
class User extends Authenticatable
{
    use BelongsToTenant, HasAuditLog;

    protected $fillable = [
        'tenant_id', 'email', 'password', 'name',
        'role_id', 'department_id', 'is_active',
    ];

    // 순수 Eloquent 관계만 유지
    public function role() { return $this->belongsTo(Role::class); }
    public function department() { return $this->belongsTo(Department::class); }
}
```

---

## 🎨 UI 설계 원칙 (수정 용이성 최우선)

### DaisyUI 사용 철학
```blade
{{-- ✅ GOOD: 단순하고 직관적 --}}
<button class="btn btn-primary">저장</button>
<div class="card bg-base-100 shadow-xl">
    <div class="card-body">
        <h2 class="card-title">제목</h2>
        <p>내용</p>
    </div>
</div>

{{-- ❌ BAD: 과도한 추상화 --}}
<x-custom-button variant="primary" size="large" />
<x-card-wrapper :config="$complexConfig" />
```

### Blade 템플릿 구조 (2레벨 최대)
```blade
{{-- layouts/app.blade.php (레이아웃) --}}
<!DOCTYPE html>
<html data-theme="light">
<head>
    <title>{{ config('app.name') }}</title>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
    <div class="drawer lg:drawer-open">
        {{-- 사이드바 --}}
        <input id="drawer" type="checkbox" class="drawer-toggle" />
        <div class="drawer-side">
            <label for="drawer" class="drawer-overlay"></label>
            <ul class="menu p-4 w-64 bg-base-200">
                @foreach($menus as $menu)
                    <li><a href="{{ $menu->url }}">{{ __($menu->name) }}</a></li>
                @endforeach
            </ul>
        </div>

        {{-- 메인 컨텐츠 --}}
        <div class="drawer-content">
            <div class="navbar bg-base-100">
                <div class="flex-1">
                    <a class="btn btn-ghost normal-case text-xl">MNG</a>
                </div>
                <div class="flex-none">
                    <div class="dropdown dropdown-end">
                        <label tabindex="0" class="btn btn-ghost">
                            {{ auth()->user()->name }}
                        </label>
                        <ul class="menu dropdown-content">
                            <li><a href="/logout">로그아웃</a></li>
                        </ul>
                    </div>
                </div>
            </div>

            <main class="p-6">
                @yield('content')
            </main>
        </div>
    </div>
</body>
</html>

{{-- users/index.blade.php (페이지) --}}
@extends('layouts.app')

@section('content')
<div class="card bg-base-100 shadow-xl">
    <div class="card-body">
        <h2 class="card-title">사용자 목록</h2>

        {{-- Alpine.js 최소 사용 --}}
        <div x-data="{ search: '' }">
            <input x-model="search" type="text"
                   placeholder="검색..."
                   class="input input-bordered w-full" />
        </div>

        <div class="overflow-x-auto">
            <table class="table w-full">
                <thead>
                    <tr>
                        <th>이름</th>
                        <th>이메일</th>
                        <th>역할</th>
                        <th>작업</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach($users as $user)
                    <tr>
                        <td>{{ $user->name }}</td>
                        <td>{{ $user->email }}</td>
                        <td>{{ $user->role->name }}</td>
                        <td>
                            <a href="/users/{{ $user->id }}/edit" class="btn btn-sm">수정</a>
                        </td>
                    </tr>
                    @endforeach
                </tbody>
            </table>
        </div>

        {{ $users->links() }} {{-- Pagination --}}
    </div>
</div>
@endsection
```

### Alpine.js 사용 원칙 (최소화)
```blade
{{-- ✅ GOOD: 단순 인터랙션 --}}
<div x-data="{ open: false }">
    <button @click="open = !open" class="btn">메뉴 열기</button>
    <div x-show="open" class="dropdown-content">메뉴 내용</div>
</div>

{{-- ❌ BAD: 복잡한 로직 (서버에서 처리) --}}
<div x-data="complexDataFetching()">
    <div x-init="loadData()">...</div>
</div>
```

---

## 🚀 개발 로드맵

### Phase 1: 인프라 구축 (1일)

#### 체크리스트
- [ ] Laravel 12 프로젝트 생성 (`mng/`)
  ```bash
  cd SAM
  composer create-project laravel/laravel mng
  cd mng
  ```
- [ ] `.env` 환경 변수 설정
  ```env
  APP_NAME=MNG
  APP_URL=http://mng.sam.kr
  DB_CONNECTION=pgsql
  DB_HOST=postgres
  DB_PORT=5432
  DB_DATABASE=sam_db
  DB_USERNAME=sam_user
  DB_PASSWORD=sam_password
  ```
- [ ] Composer 패키지 설치
  ```bash
  composer require laravel/sanctum
  composer require darkaonline/l5-swagger
  composer require --dev laravel/pint
  ```
- [ ] Tailwind + DaisyUI + HTMX 설정
  ```bash
  npm install -D tailwindcss daisyui @tailwindcss/forms
  npm install htmx.org
  ```
  ```js
  // tailwind.config.js
  module.exports = {
    plugins: [require('daisyui')],
    daisyui: {
      themes: ['light', 'dark'],
    },
  }
  ```
- [ ] Docker Nginx 설정 (mng.sam.kr)
  ```nginx
  server {
      listen 80;
      server_name mng.sam.kr;
      root /var/www/mng/public;
      index index.php;

      location / {
          try_files $uri $uri/ /index.php?$query_string;
      }

      location ~ \.php$ {
          fastcgi_pass mng:9000;
          fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
          include fastcgi_params;
      }
  }
  ```
- [ ] admin/ 모델 복사
  ```bash
  cp -r admin/app/Models/* mng/app/Models/
  cp -r admin/app/Traits/* mng/app/Traits/
  # Filament 관련 코드 제거 후 커밋
  ```

#### 산출물
- `mng/` 디렉토리 (Git 독립 저장소)
- DaisyUI + Alpine.js 환경
- 복사된 모델 (Filament 제거)

---

### Phase 2: 인증 시스템 (2일)

#### 로그인 화면 (DaisyUI)
```blade
{{-- resources/views/auth/login.blade.php --}}
<!DOCTYPE html>
<html data-theme="light">
<head>
    <title>로그인 - MNG</title>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="bg-base-200">
    <div class="hero min-h-screen">
        <div class="hero-content flex-col">
            <div class="card w-96 bg-base-100 shadow-xl">
                <div class="card-body">
                    <h2 class="card-title justify-center mb-4">MNG 로그인</h2>

                    <form method="POST" action="/login">
                        @csrf

                        <div class="form-control">
                            <label class="label">
                                <span class="label-text">이메일</span>
                            </label>
                            <input type="email" name="email"
                                   placeholder="email@example.com"
                                   class="input input-bordered"
                                   required autofocus />
                        </div>

                        <div class="form-control mt-4">
                            <label class="label">
                                <span class="label-text">비밀번호</span>
                            </label>
                            <input type="password" name="password"
                                   class="input input-bordered"
                                   required />
                        </div>

                        @if ($errors->any())
                        <div class="alert alert-error mt-4">
                            {{ $errors->first() }}
                        </div>
                        @endif

                        <div class="form-control mt-6">
                            <button class="btn btn-primary">로그인</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
```

#### AuthService (admin/ 참고)
```php
// app/Services/AuthService.php
namespace App\Services;

use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class AuthService
{
    public function login(array $credentials): bool
    {
        return Auth::attempt($credentials);
    }

    public function logout(): void
    {
        Auth::logout();
    }

    public function createToken(array $credentials): ?string
    {
        $user = User::where('email', $credentials['email'])->first();

        if (!$user || !Hash::check($credentials['password'], $user->password)) {
            return null;
        }

        return $user->createToken('mng-token')->plainTextToken;
    }
}
```

#### 체크리스트
- [ ] LoginRequest (FormRequest)
- [ ] AuthService 작성
- [ ] Web 로그인 구현 (세션)
- [ ] API 로그인 구현 (토큰)
- [ ] BelongsToTenant 적용 확인
- [ ] Feature Test 작성

---

### Phase 3: 대시보드 (1-2일)

#### DaisyUI Drawer 레이아웃
```blade
{{-- resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html data-theme="light">
<head>
    <title>{{ config('app.name') }}</title>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
    <div class="drawer lg:drawer-open">
        <input id="drawer" type="checkbox" class="drawer-toggle" />

        {{-- 메인 컨텐츠 --}}
        <div class="drawer-content flex flex-col">
            {{-- 네비게이션 바 --}}
            <div class="w-full navbar bg-base-300">
                <div class="flex-none lg:hidden">
                    <label for="drawer" class="btn btn-square btn-ghost">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-6 h-6 stroke-current"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
                    </label>
                </div>
                <div class="flex-1 px-2 mx-2">MNG</div>
                <div class="flex-none">
                    <div class="dropdown dropdown-end">
                        <label tabindex="0" class="btn btn-ghost">
                            {{ auth()->user()->name }}
                        </label>
                        <ul tabindex="0" class="menu menu-compact dropdown-content mt-3 p-2 shadow bg-base-100 rounded-box w-52">
                            <li><a href="/profile">프로필</a></li>
                            <li>
                                <form method="POST" action="/logout">
                                    @csrf
                                    <button type="submit">로그아웃</button>
                                </form>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>

            {{-- 페이지 컨텐츠 --}}
            <main class="p-6 flex-1">
                @yield('content')
            </main>
        </div>

        {{-- 사이드바 --}}
        <div class="drawer-side">
            <label for="drawer" class="drawer-overlay"></label>
            <ul class="menu p-4 w-64 bg-base-200 text-base-content">
                @foreach($menus as $menu)
                    @if($menu->children->isEmpty())
                        <li>
                            <a href="{{ $menu->url }}"
                               class="{{ request()->is($menu->url) ? 'active' : '' }}">
                                {{ __($menu->name) }}
                            </a>
                        </li>
                    @else
                        <li>
                            <details>
                                <summary>{{ __($menu->name) }}</summary>
                                <ul>
                                    @foreach($menu->children as $child)
                                        <li><a href="{{ $child->url }}">{{ __($child->name) }}</a></li>
                                    @endforeach
                                </ul>
                            </details>
                        </li>
                    @endif
                @endforeach
            </ul>
        </div>
    </div>
</body>
</html>
```

#### 대시보드 컨트롤러
```php
// app/Http/Controllers/Web/DashboardController.php
namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Services\MenuService;

class DashboardController extends Controller
{
    public function __construct(
        private MenuService $menuService
    ) {}

    public function index()
    {
        $menus = $this->menuService->getMenusForUser(auth()->user());

        return view('dashboard.index', compact('menus'));
    }
}
```

#### 체크리스트
- [ ] 레이아웃 템플릿 (DaisyUI Drawer)
- [ ] 메뉴 서비스 (MenuService)
- [ ] 역할별 메뉴 필터링
- [ ] 대시보드 메인 페이지

---

### Phase 4: 핵심 기능 (주 단위)

#### 4.1 사용자 관리 (3-5일)
```blade
{{-- resources/views/users/index.blade.php --}}
@extends('layouts.app')

@section('content')
<div class="space-y-4">
    {{-- 헤더 --}}
    <div class="flex justify-between items-center">
        <h1 class="text-2xl font-bold">사용자 관리</h1>
        <a href="/users/create" class="btn btn-primary">사용자 추가</a>
    </div>

    {{-- 검색/필터 --}}
    <div class="card bg-base-100 shadow-xl">
        <div class="card-body">
            <form method="GET" action="/users">
                <div class="grid grid-cols-3 gap-4">
                    <div class="form-control">
                        <input type="text" name="search"
                               placeholder="이름 또는 이메일"
                               class="input input-bordered"
                               value="{{ request('search') }}" />
                    </div>
                    <div class="form-control">
                        <select name="role_id" class="select select-bordered">
                            <option value="">전체 역할</option>
                            @foreach($roles as $role)
                                <option value="{{ $role->id }}"
                                        {{ request('role_id') == $role->id ? 'selected' : '' }}>
                                    {{ $role->name }}
                                </option>
                            @endforeach
                        </select>
                    </div>
                    <div class="form-control">
                        <button type="submit" class="btn btn-primary">검색</button>
                    </div>
                </div>
            </form>
        </div>
    </div>

    {{-- 테이블 --}}
    <div class="card bg-base-100 shadow-xl">
        <div class="card-body">
            <div class="overflow-x-auto">
                <table class="table w-full">
                    <thead>
                        <tr>
                            <th>ID</th>
                            <th>이름</th>
                            <th>이메일</th>
                            <th>역할</th>
                            <th>부서</th>
                            <th>상태</th>
                            <th>작업</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach($users as $user)
                        <tr>
                            <td>{{ $user->id }}</td>
                            <td>{{ $user->name }}</td>
                            <td>{{ $user->email }}</td>
                            <td>{{ $user->role->name }}</td>
                            <td>{{ $user->department->name }}</td>
                            <td>
                                <span class="badge {{ $user->is_active ? 'badge-success' : 'badge-error' }}">
                                    {{ $user->is_active ? '활성' : '비활성' }}
                                </span>
                            </td>
                            <td>
                                <div class="btn-group">
                                    <a href="/users/{{ $user->id }}/edit" class="btn btn-sm">수정</a>
                                    <button class="btn btn-sm btn-error"
                                            onclick="confirmDelete({{ $user->id }})">삭제</button>
                                </div>
                            </td>
                        </tr>
                        @endforeach
                    </tbody>
                </table>
            </div>

            {{ $users->links() }}
        </div>
    </div>
</div>

<script>
function confirmDelete(userId) {
    if (confirm('정말 삭제하시겠습니까?')) {
        document.getElementById('delete-form-' + userId).submit();
    }
}
</script>
@endsection
```

#### 체크리스트
- [ ] 사용자 목록 (검색, 필터, 페이징)
- [ ] 사용자 생성 (FormRequest)
- [ ] 사용자 수정
- [ ] 사용자 삭제 (Soft Delete)
- [ ] Feature Test

---

## 📊 데이터베이스 전략

### DB 테이블 전략 (최종)
```
✅ 기존 테이블 재사용 (마이그레이션 없음)
   - users, roles, departments
   - products, materials
   - menus, audit_logs

🆕 관리자 전용 (admin_*)
   - admin_settings
   - admin_logs
   - admin_preferences

📊 통계 (stat_*)
   - stat_daily_sales
   - stat_inventory
   - stat_user_activity
```

### 모델 관리 전략
```
초기 복사: admin/app/Models → mng/app/Models
Filament 제거: form(), table(), canAccessPanel() 등
이후 운영: mng/ 독립 (admin 점차 deprecated)
```

---

## 🛡️ 품질 관리

### 코드 품질 체크리스트
```
□ Service-First (비즈니스 로직 → Service)
□ FormRequest (컨트롤러 검증 금지)
□ BelongsToTenant (multi-tenant 스코프)
□ i18n 키 (하드코딩 금지)
□ Soft Delete (deleted_at)
□ 감사 로그 (HasAuditLog trait)
□ Feature Test
□ Pint (코드 스타일)
```

### UI 수정 용이성 체크리스트
```
□ DaisyUI 클래스 직접 사용 (추상화 최소)
□ Alpine.js 단순 인터랙션만
□ Blade 템플릿 2레벨 이하
□ 인라인 Tailwind 허용
□ AI 없이 수정 가능
```

---

## 🎯 예상 타임라인

### MVP (최소 기능 제품) - 2주
```
Day 1-2:   Phase 1 (인프라) + admin/ 모델 복사
Day 3-4:   Phase 2 (인증)
Day 5-6:   Phase 3 (대시보드)
Day 7-14:  Phase 4 (사용자, 역할, 제품 관리)
```

### 전체 기능 이식 - 4-6주
```
Week 3-4: 제품, 자재 관리
Week 5:   게시판, 통계
Week 6:   테스트, 최적화
```

---

## 📚 참고 문서

- [DaisyUI Components](https://daisyui.com/components/)
- [Alpine.js Documentation](https://alpinejs.dev/)
- [Laravel 12 Blade](https://laravel.com/docs/12.x/blade)

---

## ✅ 다음 단계

### 즉시 시작 가능
- [ ] `mng/` Laravel 프로젝트 생성
- [ ] DaisyUI + Alpine.js 설치
- [ ] admin/ 모델 복사 및 Filament 제거
- [ ] 로그인 화면 구현

---

**작성일**: 2025-01-20
**버전**: 2.0
**상태**: 정책 반영 완료 ✅
**변경사항**:
- 폴더명: `adm2/` → `mng/`
- UI: DaisyUI + Blade + Alpine.js 확정
- DB: 기존 테이블 재사용, `admin_*`, `stat_*` 접두사
- 모델: admin/ 복사 후 Filament 제거
- 철학: 단순함, 수정 용이성 최우선