# MNG 프로젝트 개발 프로세스 ## 🎯 개발 철학 ``` API 우선 → HTMX 연동 → 단순하고 수정 용이한 코드 ``` ### 핵심 원칙 1. **API First**: 모든 기능은 API로 먼저 개발 2. **Service-First**: 비즈니스 로직은 Service에만 3. **HTMX Driven**: JS 최소화, HTML 속성으로 인터랙션 4. **DaisyUI Only**: 커스텀 CSS 금지, DaisyUI 클래스만 사용 --- ## 📐 표준 개발 프로세스 (6단계) ### Phase 0: 환경 구성 (최초 1회) **참조**: `claudedocs/mng/SETUP_GUIDE.md` ```bash # SETUP_GUIDE.md의 Step 1-10 참조 # 1. Laravel 프로젝트 생성 # 2. Docker 설정 파일 생성 # 3. docker-compose.yml 업데이트 # 4. nginx.conf 업데이트 # 5. Tailwind + DaisyUI + HTMX 설정 # 6. admin/ 모델 복사 # 7. Docker 빌드 및 실행 # 8. 동작 확인 (http://mng.sam.kr) # 스킬 사용: /sc:implement "SETUP_GUIDE.md 따라 MNG 환경 구성" ``` ### Phase 1: 준비 단계 ```bash # 1. 기능 분석 (Sequential Thinking) /sc:analyze --think # 2. 요구사항 정리 - 입력: 어떤 데이터를 받는가? - 처리: 어떤 비즈니스 로직? - 출력: 어떤 데이터를 반환? - 화면: 어떤 UI 필요? # 3. API 명세 작성 - 엔드포인트: GET /api/admin/users - Request: { search: string, role_id?: number } - Response: { success, data, message, meta } ``` ### Phase 1: DB & Model (1단계) ```bash # 1-1. 마이그레이션 확인 # 기존 테이블 사용? → 마이그레이션 불필요 # 신규 테이블? → admin_* or stat_* 접두사 # 1-2. 모델 확인/생성 # admin/app/Models에서 복사했는지 확인 # BelongsToTenant, HasAuditLog 트레잇 적용 # 예시: mng/app/Models/User.php belongsTo(Role::class); } public function department() { return $this->belongsTo(Department::class); } } ``` ### Phase 2: Service Layer (2단계) ```bash # 2-1. Service 생성 (비즈니스 로직) # mng/app/Services/UserService.php where(function ($q) use ($filters) { $q->where('name', 'like', "%{$filters['search']}%") ->orWhere('email', 'like', "%{$filters['search']}%"); }); } // 역할 필터 if (!empty($filters['role_id'])) { $query->where('role_id', $filters['role_id']); } return $query->paginate(20); } /** * 사용자 생성 */ public function createUser(array $data): User { $data['password'] = Hash::make($data['password']); $data['tenant_id'] = auth()->user()->tenant_id; return User::create($data); } /** * 사용자 수정 */ public function updateUser(User $user, array $data): User { if (!empty($data['password'])) { $data['password'] = Hash::make($data['password']); } else { unset($data['password']); } $user->update($data); return $user->fresh(); } /** * 사용자 삭제 (Soft Delete) */ public function deleteUser(User $user): bool { return $user->delete(); } } ``` ### Phase 3: API Controller (3단계) ```bash # 3-1. FormRequest 생성 # mng/app/Http/Requests/StoreUserRequest.php 'required|string|max:255', 'email' => 'required|email|unique:users,email', 'password' => 'required|string|min:8', 'role_id' => 'required|exists:roles,id', 'department_id' => 'required|exists:departments,id', ]; } public function messages(): array { return [ 'name.required' => 'users.validation.name_required', 'email.required' => 'users.validation.email_required', 'email.email' => 'users.validation.email_invalid', 'email.unique' => 'users.validation.email_unique', ]; } } # 3-2. API Controller 생성 # mng/app/Http/Controllers/Api/Admin/UserController.php userService->getUsers($request->all()); return response()->json([ 'success' => true, 'data' => $users->items(), 'message' => 'users.retrieved', 'meta' => [ 'current_page' => $users->currentPage(), 'last_page' => $users->lastPage(), 'per_page' => $users->perPage(), 'total' => $users->total(), ], ]); } /** * 사용자 생성 (API) * POST /api/admin/users */ public function store(StoreUserRequest $request): JsonResponse { $user = $this->userService->createUser($request->validated()); return response()->json([ 'success' => true, 'data' => $user, 'message' => 'users.created', ], 201); } /** * 사용자 수정 (API) * PUT /api/admin/users/{user} */ public function update(UpdateUserRequest $request, User $user): JsonResponse { $user = $this->userService->updateUser($user, $request->validated()); return response()->json([ 'success' => true, 'data' => $user, 'message' => 'users.updated', ]); } /** * 사용자 삭제 (API) * DELETE /api/admin/users/{user} */ public function destroy(User $user): JsonResponse { $this->userService->deleteUser($user); return response()->json([ 'success' => true, 'message' => 'users.deleted', ]); } } # 3-3. 라우트 등록 # mng/routes/api.php Route::middleware(['auth:sanctum', 'admin.permission']) ->prefix('admin') ->group(function () { Route::apiResource('users', UserController::class); }); ``` ### Phase 4: Blade + HTMX (4단계) ```bash # 4-1. HTML 응답용 Controller (선택) # API + Blade 부분 HTML 반환 # mng/app/Http/Controllers/Api/Admin/UserController.php (추가) /** * 사용자 목록 (HTMX용 Blade HTML) * GET /api/admin/users?format=html */ public function index(Request $request) { $users = $this->userService->getUsers($request->all()); // HTMX 요청 시 부분 HTML 반환 if ($request->header('HX-Request')) { return view('users.partials.table', compact('users')); } // 일반 요청 시 JSON 반환 return response()->json([ 'success' => true, 'data' => $users->items(), 'message' => 'users.retrieved', 'meta' => [ 'current_page' => $users->currentPage(), 'last_page' => $users->lastPage(), 'per_page' => $users->perPage(), 'total' => $users->total(), ], ]); } # 4-2. Blade 템플릿 작성 # mng/resources/views/users/index.blade.php @extends('layouts.app') @section('content')
{{-- 헤더 --}}

사용자 관리

사용자 추가
{{-- 검색/필터 --}}
{{-- 테이블 영역 --}}
{{-- 초기 로드 시 서버에서 HTML 받아서 여기 삽입 --}}
@endsection # 4-3. 부분 템플릿 (HTMX 응답용) # mng/resources/views/users/partials/table.blade.php
@foreach($users as $user) @endforeach
ID 이름 이메일 역할 부서 상태 작업
{{ $user->id }} {{ $user->name }} {{ $user->email }} {{ $user->role->name }} {{ $user->department->name }} {{ $user->is_active ? '활성' : '비활성' }}
수정
{{-- 페이징 (HTMX) --}}
@if($users->hasPages())
@foreach($users->getUrlRange(1, $users->lastPage()) as $page => $url) @endforeach
@endif
``` ### Phase 5: 테스트 & 검증 (5단계) ```bash # 5-1. Feature Test 작성 # mng/tests/Feature/UserControllerTest.php create(); $response = $this->actingAs($user) ->getJson('/api/admin/users'); $response->assertStatus(200) ->assertJsonStructure([ 'success', 'data', 'message', 'meta', ]); } public function test_사용자_생성() { $admin = User::factory()->create(); $role = Role::factory()->create(); $response = $this->actingAs($admin) ->postJson('/api/admin/users', [ 'name' => '홍길동', 'email' => 'hong@example.com', 'password' => 'password123', 'role_id' => $role->id, 'department_id' => 1, ]); $response->assertStatus(201) ->assertJson([ 'success' => true, 'message' => 'users.created', ]); $this->assertDatabaseHas('users', [ 'email' => 'hong@example.com', ]); } } # 5-2. 테스트 실행 php artisan test --filter=UserControllerTest # 5-3. 코드 스타일 검증 ./vendor/bin/pint # 5-4. 품질 체크리스트 □ Service-First (비즈니스 로직 → Service) □ FormRequest (컨트롤러 검증 금지) □ BelongsToTenant (multi-tenant 스코프) □ i18n 키 (하드코딩 금지) □ Soft Delete (deleted_at) □ 감사 로그 (HasAuditLog trait) □ API 응답 형식 ({success, data, message, meta}) □ HTMX 속성 (hx-get, hx-target, hx-swap) □ DaisyUI 클래스만 사용 □ Feature Test 통과 □ Pint 통과 ``` --- ## 🔄 실전 워크플로 (스킬 활용) ### 신규 기능 개발 시 ```bash # Step 1: 기능 분석 및 설계 /sc:design "사용자 관리 기능" # → Sequential Thinking으로 요구사항 분석 # → API 명세 도출 # Step 2: 구현 /sc:implement "사용자 관리 API 구현" # → Model, Service, Controller, FormRequest 생성 # → 자동으로 5단계 프로세스 진행 # Step 3: Blade + HTMX 구현 # 직접 작성 (단순하므로 AI 불필요) # 또는 /sc:implement "사용자 목록 Blade 화면" # Step 4: 테스트 /sc:test "UserController" # → Feature Test 자동 생성 및 실행 # Step 5: 검증 및 커밋 code-workflow 스킬 사용 # → 분석 → 수정 → 검증 → 정리 → 커밋 ``` ### 버그 수정 시 ```bash # Step 1: 문제 분석 /sc:troubleshoot "사용자 목록 페이징 안됨" # → Root Cause 분석 # Step 2: 수정 /sc:improve "UserService 페이징 로직" # Step 3: 테스트 /sc:test # Step 4: 커밋 code-workflow ``` ### 리팩토링 시 ```bash /sc:improve --focus quality "UserController" /sc:analyze --think-hard "전체 아키텍처" ``` --- ## 📋 체크리스트 템플릿 ### 기능 개발 완료 체크리스트 ``` 기능명: _______________ [ ] Phase 1: DB & Model [ ] 마이그레이션 (필요 시) [ ] 모델 생성/복사 [ ] BelongsToTenant 적용 [ ] HasAuditLog 적용 [ ] 관계 설정 (belongsTo, hasMany) [ ] Phase 2: Service Layer [ ] Service 생성 [ ] 비즈니스 로직 구현 [ ] 트랜잭션 처리 [ ] 예외 처리 [ ] Phase 3: API Controller [ ] FormRequest 생성 (Validation) [ ] Controller 생성 [ ] API 응답 형식 준수 [ ] i18n 키 사용 [ ] 라우트 등록 [ ] Phase 4: Blade + HTMX [ ] 메인 페이지 (index.blade.php) [ ] 부분 템플릿 (partials/*.blade.php) [ ] HTMX 속성 (hx-get, hx-post, hx-delete) [ ] DaisyUI 컴포넌트만 사용 [ ] HX-Request 헤더 처리 [ ] Phase 5: 테스트 & 검증 [ ] Feature Test 작성 [ ] 테스트 통과 (php artisan test) [ ] Pint 통과 (./vendor/bin/pint) [ ] Swagger 문서화 (선택) [ ] 커밋 [ ] code-workflow 스킬 사용 [ ] CURRENT_WORKS.md 업데이트 ``` --- ## 🎨 HTMX 패턴 라이브러리 ### 1. 목록 조회 (Load) ```blade
``` ### 2. 검색/필터 (Submit) ```blade
``` ### 3. 생성 (POST) ```blade
``` ### 4. 수정 (PUT) ```blade
``` ### 5. 삭제 (DELETE) ```blade ``` ### 6. 무한 스크롤 ```blade
더보기...
``` ### 7. 폴링 (자동 갱신) ```blade
통계: {{ $stats }}
``` ### 8. 디바운싱 (입력 지연) ```blade ``` --- ## 🔧 개발 환경 설정 ### 필수 패키지 설치 ```bash # Composer composer require laravel/sanctum composer require darkaonline/l5-swagger composer require --dev laravel/pint # NPM npm install -D tailwindcss daisyui @tailwindcss/forms npm install htmx.org ``` ### HTMX 설정 ```js // resources/js/app.js import htmx from 'htmx.org'; window.htmx = htmx; // HTMX 전역 설정 document.addEventListener('DOMContentLoaded', () => { // CSRF 토큰 자동 추가 document.body.addEventListener('htmx:configRequest', (event) => { event.detail.headers['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').content; }); }); ``` ### Blade 레이아웃 ```blade {{ config('app.name') }} @vite(['resources/css/app.css', 'resources/js/app.js']) @yield('content') ``` --- ## 📝 다음 단계 1. **Phase 1 시작**: Laravel 프로젝트 생성 및 환경 구성 2. **인증 구현**: 로그인 API + Blade 화면 3. **첫 기능 개발**: 사용자 관리 (이 프로세스 적용) --- **작성일**: 2025-01-20 **버전**: 1.0 **기술 스택**: Laravel 12 + MySQL 8.0 + HTMX + DaisyUI **목표**: API 우선, 단순함, 수정 용이성