# MNG 환경 구성 가이드

## 📋 개요

MNG 프로젝트를 위한 Docker 환경 구성 가이드입니다.
기존 SAM 프로젝트 (api, admin, react)에 mng 서비스를 추가합니다.

---

## 🎯 목표 환경

```
SAM/
├── api/         (api.sam.kr)      - 외부 API
├── admin/       (admin.sam.kr)    - Filament 관리자 (deprecated)
├── react/       (dev.sam.kr)      - React 프론트엔드
├── mng/         (mng.sam.kr)      - 새 관리자 패널 ⭐ NEW
└── docker/
    ├── docker-compose.yml
    ├── nginx/nginx.conf
    └── mng/                        ⭐ NEW
        ├── Dockerfile
        ├── nginx.conf
        └── supervisord.conf
```

### 도메인 구성
| 도메인 | 서비스 | 용도 |
|--------|--------|------|
| api.sam.kr | api | 외부 클라이언트 API |
| admin.sam.kr | admin | Filament 관리자 (점차 폐기) |
| dev.sam.kr | react | React 프론트엔드 |
| **mng.sam.kr** | **mng** | **새 관리자 패널** ⭐ |

---

## 📐 Phase 0: 환경 구성 (최초 1회)

### Step 1: Laravel 프로젝트 생성

```bash
# SAM 디렉토리로 이동
cd /Users/hskwon/Works/@KD_SAM/SAM

# Laravel 12 프로젝트 생성
composer create-project laravel/laravel mng

cd mng

# 필수 패키지 설치
composer require laravel/sanctum
composer require darkaonline/l5-swagger
composer require --dev laravel/pint

# NPM 패키지 설치
npm install -D tailwindcss daisyui @tailwindcss/forms postcss autoprefixer
npm install htmx.org
npx tailwindcss init -p
```

### Step 2: 환경 변수 설정

**mng/.env** (기본값 수정)
```env
APP_NAME=MNG
APP_ENV=local
APP_KEY=base64:... (자동 생성됨)
APP_DEBUG=true
APP_URL=http://mng.sam.kr

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=samdb
DB_USERNAME=samuser
DB_PASSWORD=sampass

CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file

SANCTUM_STATEFUL_DOMAINS=mng.sam.kr

# 이메일 설정 (Gmail SMTP)
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=your-email@gmail.com
MAIL_FROM_NAME="${APP_NAME}"
```

### 이메일 설정 (Gmail SMTP)

사용자 등록 시 임시 비밀번호 발송, 비밀번호 초기화 등 이메일 기능을 사용하려면 SMTP 설정이 필요합니다.

**Gmail 앱 비밀번호 발급:**
1. Google 계정 → 보안 → 2단계 인증 활성화
2. 앱 비밀번호 생성 (https://myaccount.google.com/apppasswords)
3. 생성된 16자리 비밀번호를 `MAIL_PASSWORD`에 입력

**Google Groups 이메일 사용 (발신자 변경):**
- Google Groups 이메일(예: `develop@company.com`)을 발신자로 사용하려면:
1. Gmail 설정 → 계정 및 가져오기 → 다른 주소에서 메일 보내기
2. 그룹 이메일 주소 추가 및 인증
3. `.env`의 `MAIL_FROM_ADDRESS`를 그룹 이메일로 설정

**주의사항:**
- `MAIL_USERNAME`은 실제 Gmail 계정 (SMTP 인증용)
- `MAIL_FROM_ADDRESS`는 발신자 표시 주소 (Gmail에서 "다른 주소에서 메일 보내기" 설정 필요)
- 앱 비밀번호는 일반 비밀번호가 아닌 Google에서 생성한 16자리 코드

### Step 3: Tailwind + DaisyUI 설정

**mng/tailwind.config.js**
```js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./resources/**/*.blade.php",
    "./resources/**/*.js",
    "./resources/**/*.vue",
  ],
  theme: {
    extend: {},
  },
  plugins: [
    require('daisyui'),
    require('@tailwindcss/forms'),
  ],
  daisyui: {
    themes: ['light', 'dark'],
  },
}
```

**mng/resources/css/app.css**
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

**mng/resources/js/app.js**
```js
import './bootstrap';
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;
    });

    // 에러 처리
    document.body.addEventListener('htmx:responseError', (event) => {
        console.error('HTMX Error:', event.detail);
        alert('오류가 발생했습니다. 다시 시도해주세요.');
    });
});
```

**mng/vite.config.js** (확인)
```js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
    ],
});
```

### Step 4: Docker 설정 파일 생성

#### 4-1. Dockerfile 생성

**docker/mng/Dockerfile**
```dockerfile
FROM php:8.4-fpm

# 시스템 패키지 설치
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    libzip-dev \
    zip \
    unzip \
    supervisor \
    nginx

# PHP 확장 설치
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip

# Composer 설치
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Node.js 설치 (Vite 빌드용)
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
    apt-get install -y nodejs

# 작업 디렉토리 설정
WORKDIR /var/www/mng

# 권한 설정
RUN chown -R www-data:www-data /var/www/mng

# PHP-FPM 포트 노출
EXPOSE 9000

CMD ["php-fpm"]
```

#### 4-2. Nginx 설정 (PHP-FPM 연동)

**docker/mng/nginx.conf**
```nginx
server {
    listen 9000;
    server_name localhost;
    root /var/www/mng/public;
    index index.php index.html;

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

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
```

#### 4-3. Supervisor 설정 (선택)

**docker/mng/supervisord.conf**
```ini
[supervisord]
nodaemon=true

[program:php-fpm]
command=/usr/local/sbin/php-fpm
autostart=true
autorestart=true
stderr_logfile=/var/log/php-fpm.err.log
stdout_logfile=/var/log/php-fpm.out.log
```

#### 4-4. PHP 업로드 설정

**docker/mng/uploads.ini**
```ini
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 300
memory_limit = 256M
```

### Step 5: docker-compose.yml 업데이트

**docker/docker-compose.yml** (mng 서비스 추가)
```yaml
services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ../api:/var/www/api
      - ../admin:/var/www/admin
      - ../mng:/var/www/mng  # ⭐ NEW
      - ../docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - api
      - admin
      - mng  # ⭐ NEW
      - react
    networks:
      - samnet

  api:
    build:
      context: .
      dockerfile: ../docker/api/Dockerfile
    volumes:
      - ../api:/var/www/api
      - ../docker/api/nginx.conf:/etc/nginx/conf.d/default.conf
      - ../docker/api/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
      - ../docker/api/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    environment:
      - DB_HOST=mysql
      - DB_PORT=3306
      - DB_DATABASE=samdb
      - DB_USERNAME=samuser
      - DB_PASSWORD=sampass
    networks:
      - samnet
    working_dir: /var/www/api

  admin:
    build:
      context: .
      dockerfile: ../docker/admin/Dockerfile
    volumes:
      - ../admin:/var/www/admin
      - ../docker/admin/nginx.conf:/etc/nginx/conf.d/default.conf
      - ../docker/admin/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
      - ../docker/admin/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    environment:
      - DB_HOST=mysql
      - DB_PORT=3306
      - DB_DATABASE=samdb
      - DB_USERNAME=samuser
      - DB_PASSWORD=sampass
    networks:
      - samnet
    working_dir: /var/www/admin

  # ⭐ NEW: MNG 서비스
  mng:
    build:
      context: .
      dockerfile: ../docker/mng/Dockerfile
    volumes:
      - ../mng:/var/www/mng
      - ../docker/mng/nginx.conf:/etc/nginx/conf.d/default.conf
      - ../docker/mng/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
      - ../docker/mng/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    environment:
      - DB_HOST=mysql
      - DB_PORT=3306
      - DB_DATABASE=samdb
      - DB_USERNAME=samuser
      - DB_PASSWORD=sampass
    networks:
      - samnet
    working_dir: /var/www/mng

  react:
    build:
      context: ..
      dockerfile: docker/react/Dockerfile
    volumes:
      - ../react:/app
      - /app/node_modules
      - /app/.next
    environment:
      - NEXT_PUBLIC_API_BASE_URL=http://api.sam.kr
      - NEXT_PUBLIC_ADMIN_URL=http://admin.sam.kr
      - NEXT_PUBLIC_MNG_URL=http://mng.sam.kr  # ⭐ NEW
      - NEXT_PUBLIC_API_KEY=${NEXT_PUBLIC_API_KEY:-}
      - NEXT_PUBLIC_APP_NAME=SAM
      - NODE_ENV=development
    networks:
      - samnet
    working_dir: /app

  mysql:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_DATABASE: samdb
      MYSQL_USER: samuser
      MYSQL_PASSWORD: sampass
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - db_data:/var/lib/mysql
      - ../docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "3306:3306"
    networks:
      - samnet

volumes:
  db_data:

networks:
  samnet:
    driver: bridge
```

### Step 6: Nginx 메인 설정 업데이트

**docker/nginx/nginx.conf** (mng.sam.kr 서버 블록 추가)
```nginx
events {}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    client_max_body_size 100M;

    # ... 기존 서버 블록들 (dev.haisa.kr, api.sam.kr, admin.sam.kr, dev.sam.kr)

    # ⭐ NEW: MNG 서버 블록
    server {
        listen 80;
        server_name mng.sam.kr;

        root /var/www/mng/public;
        index index.php index.html;

        access_log /var/log/nginx/mng.sam.kr_access.log;
        error_log  /var/log/nginx/mng.sam.kr_error.log;

        # 🛡️ 보안: 악의적 경로 패턴 차단
        if ($request_uri ~* "(\.\.\/|\.\.\\|etc\/passwd|\.env|\.git|\.htaccess|\.sql|@fs\/)") {
            return 403;
        }

        # 🛡️ 보안: 의심스러운 User-Agent 차단
        if ($http_user_agent ~* "(sqlmap|nikto|nmap|masscan|metasploit|nessus)") {
            return 403;
        }

        # 정적 자산 처리
        location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|eot|map)$ {
            try_files $uri =404;
            access_log off;
            expires 30d;
            add_header Cache-Control "public";
        }

        # 일반 요청 처리
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_pass mng:9000;  # 서비스명 mng
            fastcgi_param SCRIPT_FILENAME /var/www/mng/public$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }
}
```

### Step 7: hosts 파일 설정

**/etc/hosts** (로컬 도메인 추가)
```bash
# SAM 프로젝트 도메인
127.0.0.1 api.sam.kr
127.0.0.1 admin.sam.kr
127.0.0.1 dev.sam.kr
127.0.0.1 mng.sam.kr  # ⭐ NEW
```

**macOS/Linux:**
```bash
sudo nano /etc/hosts
# 위 내용 추가 후 저장
```

**Windows:**
```
C:\Windows\System32\drivers\etc\hosts
# 관리자 권한으로 메모장 열어서 추가
```

### Step 8: admin/ 모델 복사

```bash
cd /Users/hskwon/Works/@KD_SAM/SAM

# Models 복사
cp -r admin/app/Models/* mng/app/Models/

# Traits 복사
mkdir -p mng/app/Traits
cp admin/app/Traits/BelongsToTenant.php mng/app/Traits/
cp admin/app/Traits/HasAuditLog.php mng/app/Traits/

# Filament 의존성 제거 (수동 작업 필요)
# - form(), table(), canAccessPanel() 등 삭제
# - FilamentUser 인터페이스 제거
```

### Step 9: Docker 빌드 및 실행

```bash
cd /Users/hskwon/Works/@KD_SAM/SAM/docker

# 기존 컨테이너 중지
docker-compose down

# mng 서비스 빌드
docker-compose build mng

# 전체 서비스 시작
docker-compose up -d

# 로그 확인
docker-compose logs -f mng

# mng 컨테이너 접속
docker-compose exec mng bash

# 컨테이너 내부에서 Laravel 설정
php artisan key:generate
php artisan migrate
php artisan storage:link

# Vite 빌드 (개발 모드)
npm run dev
# 또는 프로덕션 빌드
npm run build
```

### Step 10: 동작 확인

```bash
# 1. 브라우저에서 확인
http://mng.sam.kr

# 2. API 확인 (예시)
curl http://mng.sam.kr/api/admin/health

# 3. 로그 확인
docker-compose logs mng
```

---

## 🔧 문제 해결

### 1. "502 Bad Gateway" 에러
```bash
# PHP-FPM 상태 확인
docker-compose exec mng ps aux | grep php-fpm

# 재시작
docker-compose restart mng
```

### 2. 권한 에러
```bash
# 컨테이너 내부에서
docker-compose exec mng bash
chown -R www-data:www-data /var/www/mng/storage
chown -R www-data:www-data /var/www/mng/bootstrap/cache
chmod -R 775 /var/www/mng/storage
chmod -R 775 /var/www/mng/bootstrap/cache
```

### 3. DB 연결 실패
```bash
# MySQL 컨테이너 확인
docker-compose exec mysql mysql -u samuser -psampass -e "SHOW DATABASES;"

# mng .env 확인
docker-compose exec mng cat .env | grep DB_
```

### 4. Vite 빌드 실패
```bash
# 컨테이너 내부에서
docker-compose exec mng bash
npm install
npm run build
```

### 5. HTMX 동작 안함
- 브라우저 개발자 도구 → Network 탭 확인
- `HX-Request` 헤더 있는지 확인
- CSRF 토큰 확인 (meta 태그)

---

## 📋 환경 구성 체크리스트

```
[ ] Step 1: Laravel 프로젝트 생성 (mng/)
[ ] Step 2: .env 설정 (DB 정보)
[ ] Step 3: Tailwind + DaisyUI 설정
[ ] Step 4: Docker 설정 파일 생성 (Dockerfile, nginx.conf)
[ ] Step 5: docker-compose.yml 업데이트 (mng 서비스 추가)
[ ] Step 6: Nginx 메인 설정 업데이트 (mng.sam.kr 서버 블록)
[ ] Step 7: /etc/hosts 설정 (mng.sam.kr)
[ ] Step 8: admin/ 모델 복사 및 Filament 제거
[ ] Step 9: Docker 빌드 및 실행
[ ] Step 10: 동작 확인 (http://mng.sam.kr)
```

---

## 🚀 다음 단계

환경 구성 완료 후:

1. **Phase 1**: 인증 시스템 구현 (로그인 API + Blade)
2. **Phase 2**: 대시보드 구현 (레이아웃 + HTMX)
3. **Phase 3**: 사용자 관리 (첫 CRUD 기능)

DEV_PROCESS.md 문서를 참고하여 개발을 진행하세요.

---

**작성일**: 2025-01-20
**버전**: 1.0
**환경**: Docker + Laravel 12 + MySQL 8.0 + HTMX + DaisyUI