# 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: 단순하고 직관적 --}}

제목

내용

{{-- ❌ BAD: 과도한 추상화 --}} ``` ### Blade 템플릿 구조 (2레벨 최대) ```blade {{-- layouts/app.blade.php (레이아웃) --}} {{ config('app.name') }} @vite(['resources/css/app.css', 'resources/js/app.js'])
{{-- 사이드바 --}}
{{-- 메인 컨텐츠 --}}
@yield('content')
{{-- users/index.blade.php (페이지) --}} @extends('layouts.app') @section('content')

사용자 목록

{{-- Alpine.js 최소 사용 --}}
@foreach($users as $user) @endforeach
이름 이메일 역할 작업
{{ $user->name }} {{ $user->email }} {{ $user->role->name }} 수정
{{ $users->links() }} {{-- Pagination --}}
@endsection ``` ### Alpine.js 사용 원칙 (최소화) ```blade {{-- ✅ GOOD: 단순 인터랙션 --}}
{{-- ❌ BAD: 복잡한 로직 (서버에서 처리) --}}
...
``` --- ## 🚀 개발 로드맵 ### 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 --}} 로그인 - MNG @vite(['resources/css/app.css', 'resources/js/app.js'])

MNG 로그인

@csrf
@if ($errors->any())
{{ $errors->first() }}
@endif
``` #### 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 --}} {{ config('app.name') }} @vite(['resources/css/app.css', 'resources/js/app.js'])
{{-- 메인 컨텐츠 --}}
{{-- 네비게이션 바 --}} {{-- 페이지 컨텐츠 --}}
@yield('content')
{{-- 사이드바 --}}
``` #### 대시보드 컨트롤러 ```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')
{{-- 헤더 --}}

사용자 관리

사용자 추가
{{-- 검색/필터 --}}
{{-- 테이블 --}}
@foreach($users as $user) @endforeach
ID 이름 이메일 역할 부서 상태 작업
{{ $user->id }} {{ $user->name }} {{ $user->email }} {{ $user->role->name }} {{ $user->department->name }} {{ $user->is_active ? '활성' : '비활성' }}
수정
{{ $users->links() }}
@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 제거 - 철학: 단순함, 수정 용이성 최우선