# 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'])
{{-- 사이드바 --}}
{{-- 메인 컨텐츠 --}}
{{ auth()->user()->name }}
@yield('content')
{{-- users/index.blade.php (페이지) --}}
@extends('layouts.app')
@section('content')
사용자 목록
{{-- Alpine.js 최소 사용 --}}
이름
이메일
역할
작업
@foreach($users as $user)
{{ $user->name }}
{{ $user->email }}
{{ $user->role->name }}
수정
@endforeach
{{ $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'])
```
#### 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'])
{{-- 메인 컨텐츠 --}}
{{-- 네비게이션 바 --}}
MNG
{{ auth()->user()->name }}
{{-- 페이지 컨텐츠 --}}
@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')
{{-- 헤더 --}}
{{-- 검색/필터 --}}
{{-- 테이블 --}}
ID
이름
이메일
역할
부서
상태
작업
@foreach($users as $user)
{{ $user->id }}
{{ $user->name }}
{{ $user->email }}
{{ $user->role->name }}
{{ $user->department->name }}
{{ $user->is_active ? '활성' : '비활성' }}
@endforeach
{{ $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 제거
- 철학: 단순함, 수정 용이성 최우선