- 개발 단계별 문서 추가 (00_OVERVIEW ~ 06_PHASE) - 기술 표준 문서 추가 (99_TECHNICAL_STANDARDS) - 개발 프로세스 및 패턴 문서 추가 - API_FLOW_TESTER_DESIGN, DEV_PROCESS - HTMX_API_PATTERN, LAYOUT_PATTERN - SETUP_GUIDE, MNG_PROJECT_PLAN - 프로젝트 관리 문서 추가 (project-management/) - INDEX.md, MNG_CRITICAL_RULES.md 업데이트
300 lines
11 KiB
Markdown
300 lines
11 KiB
Markdown
# Phase 2: 시스템 설정
|
||
|
||
**기간:** 1주
|
||
**우선순위:** 높음 (Phase 3-6의 선행 조건)
|
||
**의존성:** Phase 1 (회원관리, 테넌트관리)
|
||
|
||
## 📋 Phase 개요
|
||
|
||
다른 기능들이 참조하는 공통 설정 기능을 구축합니다.
|
||
|
||
**포함 기능:**
|
||
1. 설정 - 카테고리 관리
|
||
2. 설정 - 관리자 계정 관리
|
||
|
||
---
|
||
|
||
## 1️⃣ 설정 - 카테고리 관리
|
||
|
||
### 기능 목록
|
||
|
||
#### 1.1 카테고리 목록 조회
|
||
- **경로:** `/mng/settings/categories`
|
||
- **기능:**
|
||
- 계층 구조 트리 뷰
|
||
- 타입별 필터 (제품, 게시판, 파일 등)
|
||
- 드래그 앤 드롭 정렬 (순서 변경)
|
||
- 검색 (카테고리명)
|
||
- **권한:** `settings.categories.index`
|
||
|
||
#### 1.2 카테고리 생성
|
||
- **경로:** `/mng/settings/categories/create`
|
||
- **기능:**
|
||
- 카테고리명 입력 (다국어 지원)
|
||
- 타입 선택 (product, board, file, custom)
|
||
- 부모 카테고리 선택 (계층 구조)
|
||
- 정렬 순서 설정
|
||
- 활성/비활성
|
||
- **권한:** `settings.categories.create`
|
||
|
||
#### 1.3 카테고리 수정
|
||
- **경로:** `/mng/settings/categories/{id}/edit`
|
||
- **기능:**
|
||
- 기본 정보 수정
|
||
- 부모 카테고리 변경
|
||
- 정렬 순서 변경
|
||
- **권한:** `settings.categories.update`
|
||
|
||
#### 1.4 카테고리 삭제
|
||
- **경로:** `/mng/settings/categories/{id}`
|
||
- **기능:**
|
||
- 하위 카테고리 확인 (있으면 삭제 불가)
|
||
- 사용 중인 항목 확인 (제품, 게시물 등)
|
||
- Soft Delete
|
||
- **권한:** `settings.categories.delete`
|
||
|
||
### DB 스키마
|
||
|
||
```sql
|
||
CREATE TABLE categories (
|
||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '소속 테넌트',
|
||
parent_id BIGINT UNSIGNED NULL COMMENT '부모 카테고리 ID',
|
||
type ENUM('product', 'board', 'file', 'custom') DEFAULT 'custom' COMMENT '카테고리 타입',
|
||
name VARCHAR(255) NOT NULL COMMENT '카테고리명',
|
||
slug VARCHAR(255) NOT NULL COMMENT 'URL 슬러그',
|
||
description TEXT NULL COMMENT '설명',
|
||
sort_order INT DEFAULT 0 COMMENT '정렬 순서',
|
||
is_active BOOLEAN DEFAULT TRUE COMMENT '활성 여부',
|
||
meta_data JSON NULL COMMENT '추가 메타데이터',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
deleted_at TIMESTAMP NULL,
|
||
|
||
INDEX idx_tenant_id (tenant_id),
|
||
INDEX idx_parent_id (parent_id),
|
||
INDEX idx_type (type),
|
||
INDEX idx_slug (slug),
|
||
INDEX idx_sort_order (sort_order),
|
||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
```
|
||
|
||
### API 엔드포인트
|
||
|
||
| Method | Endpoint | Description | FormRequest |
|
||
|--------|----------|-------------|-------------|
|
||
| GET | `/mng/settings/categories` | 카테고리 목록 (트리 구조) | - |
|
||
| GET | `/mng/settings/categories/create` | 카테고리 생성 폼 | - |
|
||
| POST | `/mng/settings/categories` | 카테고리 생성 | `StoreCategoryRequest` |
|
||
| GET | `/mng/settings/categories/{id}/edit` | 카테고리 수정 폼 | - |
|
||
| PUT | `/mng/settings/categories/{id}` | 카테고리 수정 | `UpdateCategoryRequest` |
|
||
| DELETE | `/mng/settings/categories/{id}` | 카테고리 삭제 | - |
|
||
| POST | `/mng/settings/categories/reorder` | 드래그앤드롭 정렬 | `ReorderCategoryRequest` |
|
||
|
||
### Service 클래스
|
||
|
||
```php
|
||
// app/Services/CategoryService.php
|
||
class CategoryService
|
||
{
|
||
public function getTree(string $type = null): Collection;
|
||
public function list(array $filters): Collection;
|
||
public function find(int $id): Category;
|
||
public function create(array $data): Category;
|
||
public function update(Category $category, array $data): Category;
|
||
public function delete(Category $category): bool;
|
||
public function reorder(array $order): bool;
|
||
public function getDescendants(Category $category): Collection;
|
||
public function canDelete(Category $category): bool; // 하위/사용 확인
|
||
}
|
||
```
|
||
|
||
### UI/UX 와이어프레임 (텍스트)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 카테고리 관리 [+ 새 카테고리]│
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ [타입: 전체 ▼] [검색: 카테고리명] [검색] │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ ▼ 제품 카테고리 (Product) [수정][삭제] │
|
||
│ ├─ ▶ 전자제품 [수정][삭제] │
|
||
│ ├─ ▼ 의류 [수정][삭제] │
|
||
│ │ ├─ 상의 [수정][삭제] │
|
||
│ │ └─ 하의 [수정][삭제] │
|
||
│ └─ ▶ 식품 [수정][삭제] │
|
||
│ │
|
||
│ ▼ 게시판 카테고리 (Board) [수정][삭제] │
|
||
│ ├─ 공지사항 [수정][삭제] │
|
||
│ ├─ FAQ [수정][삭제] │
|
||
│ └─ 자료실 [수정][삭제] │
|
||
└─────────────────────────────────────────────────────────┘
|
||
|
||
* 드래그 앤 드롭으로 순서 변경 가능 (Alpine.js + Sortable.js)
|
||
```
|
||
|
||
### 개발 체크리스트
|
||
|
||
- [ ] `Category` 모델 작성 (BelongsToTenant, 계층 구조)
|
||
- [ ] `CategoryService` 클래스 작성
|
||
- [ ] FormRequest 작성 (중복 체크, 순환 참조 방지)
|
||
- [ ] `CategoryController` 작성
|
||
- [ ] Blade 템플릿 작성 (트리 뷰, 재귀 렌더링)
|
||
- [ ] Alpine.js + Sortable.js 드래그앤드롭 구현
|
||
- [ ] 계층 구조 재귀 쿼리 최적화 (Nested Set 또는 Closure Table)
|
||
- [ ] 삭제 전 사용 여부 체크 로직
|
||
- [ ] i18n 키 작성
|
||
- [ ] 테스트 작성 (계층 구조, 정렬)
|
||
|
||
---
|
||
|
||
## 2️⃣ 설정 - 관리자 계정 관리
|
||
|
||
### 기능 목록
|
||
|
||
#### 2.1 관리자 목록 조회
|
||
- **경로:** `/mng/settings/admins`
|
||
- **기능:**
|
||
- 슈퍼관리자 목록 (일반 회원과 구분)
|
||
- 검색 (이름, 이메일)
|
||
- 필터 (활성/비활성, 권한 레벨)
|
||
- 정렬 (생성일, 이름)
|
||
- **권한:** `settings.admins.index` (슈퍼관리자만)
|
||
|
||
#### 2.2 관리자 생성
|
||
- **경로:** `/mng/settings/admins/create`
|
||
- **기능:**
|
||
- 기본 정보 입력
|
||
- 권한 레벨 선택 (super_admin, admin)
|
||
- 관리 범위 설정 (전체 테넌트 or 특정 테넌트)
|
||
- **권한:** `settings.admins.create`
|
||
|
||
#### 2.3 관리자 수정
|
||
- **경로:** `/mng/settings/admins/{id}/edit`
|
||
- **기능:**
|
||
- 기본 정보 수정
|
||
- 권한 레벨 변경
|
||
- 활성/비활성 전환
|
||
- **권한:** `settings.admins.update`
|
||
|
||
#### 2.4 관리자 삭제
|
||
- **경로:** `/mng/settings/admins/{id}`
|
||
- **기능:**
|
||
- Soft Delete
|
||
- 본인 계정 삭제 방지
|
||
- 최소 1명 슈퍼관리자 유지 체크
|
||
- **권한:** `settings.admins.delete`
|
||
|
||
### DB 스키마
|
||
|
||
```sql
|
||
-- users 테이블 확장 (추가 컬럼)
|
||
ALTER TABLE users ADD COLUMN is_super_admin BOOLEAN DEFAULT FALSE COMMENT '슈퍼관리자 여부';
|
||
ALTER TABLE users ADD COLUMN admin_level ENUM('user', 'admin', 'super_admin') DEFAULT 'user' COMMENT '관리자 레벨';
|
||
ALTER TABLE users ADD COLUMN accessible_tenants JSON NULL COMMENT '접근 가능한 테넌트 ID 목록 (super_admin은 전체)';
|
||
|
||
-- 또는 별도 테이블 생성 (선택적)
|
||
CREATE TABLE admins (
|
||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||
user_id BIGINT UNSIGNED UNIQUE NOT NULL COMMENT '사용자 ID',
|
||
admin_level ENUM('admin', 'super_admin') DEFAULT 'admin' COMMENT '관리자 레벨',
|
||
accessible_tenants JSON NULL COMMENT '접근 가능한 테넌트 (null = 전체)',
|
||
permissions JSON NULL COMMENT '추가 권한',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||
```
|
||
|
||
**권장 방식:** `users` 테이블에 `is_super_admin`, `admin_level` 컬럼 추가 (간결함)
|
||
|
||
### API 엔드포인트
|
||
|
||
| Method | Endpoint | Description | FormRequest |
|
||
|--------|----------|-------------|-------------|
|
||
| GET | `/mng/settings/admins` | 관리자 목록 | - |
|
||
| GET | `/mng/settings/admins/create` | 관리자 생성 폼 | - |
|
||
| POST | `/mng/settings/admins` | 관리자 생성 | `StoreAdminRequest` |
|
||
| GET | `/mng/settings/admins/{id}/edit` | 관리자 수정 폼 | - |
|
||
| PUT | `/mng/settings/admins/{id}` | 관리자 수정 | `UpdateAdminRequest` |
|
||
| DELETE | `/mng/settings/admins/{id}` | 관리자 삭제 | - |
|
||
|
||
### Service 클래스
|
||
|
||
```php
|
||
// app/Services/AdminService.php
|
||
class AdminService
|
||
{
|
||
public function list(array $filters): LengthAwarePaginator;
|
||
public function find(int $id): User;
|
||
public function create(array $data): User;
|
||
public function update(User $admin, array $data): User;
|
||
public function delete(User $admin): bool;
|
||
public function grantSuperAdmin(User $user): bool;
|
||
public function revokeSuperAdmin(User $user): bool;
|
||
public function canDelete(User $admin): bool; // 최소 1명 체크
|
||
}
|
||
```
|
||
|
||
### 개발 체크리스트
|
||
|
||
- [ ] `users` 테이블 마이그레이션 (컬럼 추가)
|
||
- [ ] `User` 모델에 `isSuperAdmin()`, `isAdmin()` 메서드 추가
|
||
- [ ] `AdminService` 클래스 작성
|
||
- [ ] FormRequest 작성 (본인 삭제 방지, 최소 1명 체크)
|
||
- [ ] `AdminController` 작성
|
||
- [ ] Blade 템플릿 작성
|
||
- [ ] 미들웨어 작성 (`EnsureSuperAdmin`)
|
||
- [ ] 권한 체크 로직 구현
|
||
- [ ] i18n 키 작성
|
||
- [ ] 테스트 작성
|
||
|
||
---
|
||
|
||
## 🎯 Phase 2 완료 조건
|
||
|
||
### 기능 완성도
|
||
- [ ] 카테고리 계층 구조 완벽 동작
|
||
- [ ] 드래그앤드롭 정렬 기능 동작
|
||
- [ ] 관리자 계정 생성/수정/삭제 동작
|
||
- [ ] 슈퍼관리자 권한 체크 정상 작동
|
||
|
||
### 코드 품질
|
||
- [ ] Service-First 패턴 준수
|
||
- [ ] FormRequest 검증 구현
|
||
- [ ] BelongsToTenant trait 적용 (Category)
|
||
- [ ] i18n 키 사용
|
||
- [ ] Pint 포맷팅 통과
|
||
- [ ] PHPStan Level 5+ 통과
|
||
|
||
### 데이터 무결성
|
||
- [ ] 카테고리 순환 참조 방지
|
||
- [ ] 하위 카테고리 있을 때 삭제 방지
|
||
- [ ] 최소 1명 슈퍼관리자 유지
|
||
- [ ] Soft Delete 동작 확인
|
||
|
||
### 테스트
|
||
- [ ] CategoryService 유닛 테스트
|
||
- [ ] AdminService 유닛 테스트
|
||
- [ ] 계층 구조 재귀 테스트
|
||
- [ ] 권한 체크 테스트
|
||
|
||
---
|
||
|
||
## 📚 다음 단계 (Phase 3)
|
||
|
||
Phase 2가 완료되면 **Phase 3: 비즈니스 핵심 기능**으로 진행합니다.
|
||
|
||
**Phase 3 포함 기능:**
|
||
- 영업관리 (Sales Management)
|
||
- 견적서관리 (Quotation Management)
|
||
- 전자결재관리 (Approval Management)
|
||
|
||
---
|
||
|
||
**최종 업데이트:** 2025-11-21
|
||
**작성자:** Claude Code
|
||
**버전:** 1.0.0 |