docs: CLAUDE.md 인프라 변경 반영
- 기술 스택: Laravel 12 + PHP 8.4 + MySQL 8.0 업데이트 - 서버 접속 정보: 개발/운영 2서버 분리, Jenkins CI/CD 반영 - 배포 흐름: Jenkins 자동화 파이프라인 다이어그램 추가 - React 빌드: Jenkins 빌드 + fallback 정책으로 변경 - DB 아키텍처: 환경별 분리(samdb/sam_prod/sam_stat), --force 플래그 - 실행 환경: 3-Tier 환경 비교, 서버 구조도, 도메인 매핑 추가 - 공동 개발: 브랜치 전략(develop→개발, main→운영), 비상 수동 배포 절차
This commit is contained in:
224
CLAUDE.md
224
CLAUDE.md
@@ -12,7 +12,7 @@ SAM 프로젝트의 기술적 개요 문서입니다. 이 문서를 참조하면
|
||||
**핵심 요약**:
|
||||
- **회사**: 주일/경동 (블라인드/스크린 제조업체)
|
||||
- **프로젝트**: SAM (Smart Automation Management) - 차세대 ERP/MES 통합 시스템
|
||||
- **기술 스택**: Laravel 11 + HTMX + Tailwind CSS + MySQL 8.0
|
||||
- **기술 스택**: Laravel 12 + HTMX + Tailwind CSS + MySQL 8.0 (PHP 8.4)
|
||||
- **아키텍처**: Multi-tenant (tenant_id 기반 데이터 격리)
|
||||
- **레거시**: 5130.co.kr (PHP 기반) → SAM으로 마이그레이션 중
|
||||
|
||||
@@ -120,6 +120,10 @@ fix: [auth] 로그인 시 세션 만료 오류 수정
|
||||
|
||||
**각 폴더는 독립적인 Git 저장소입니다. 해당 폴더에서 git 명령을 실행해야 합니다.**
|
||||
|
||||
> **서버 경로 참고**:
|
||||
> - 개발/운영 서버 모두 `/home/webservice/` 하위에 동일한 구조로 배치
|
||||
> - 서버: `/home/webservice/api`, `/home/webservice/mng`, `/home/webservice/react`, `/home/webservice/sales`
|
||||
|
||||
---
|
||||
|
||||
## 서버 접근 정책 (3단계 분류)
|
||||
@@ -191,24 +195,33 @@ Claude가 **절대 직접 실행하지 않으며**, 사용자에게 명령어를
|
||||
|
||||
### 서버 접속 정보
|
||||
|
||||
| 서버 | 호스트 | 계정 |
|
||||
|------|--------|------|
|
||||
| 운영 서버 | `114.203.209.83` | `pro` |
|
||||
| 서버 | 호스트 | 계정 | 역할 |
|
||||
|------|--------|------|------|
|
||||
| 개발 서버 | `114.203.209.83` | `pro`, `hskwon` | 개발/스테이징 + Jenkins CI/CD + Gitea |
|
||||
| 운영 서버 | (신규, 미확정) | 별도 계정 | 정식 서비스 |
|
||||
|
||||
### 배포 흐름
|
||||
> **참고**: Jenkins(`114.203.209.83:8080`)와 Gitea(`114.203.209.83:3000`)는 개발 서버에서 운영한다.
|
||||
|
||||
### 배포 흐름 (Jenkins CI/CD)
|
||||
|
||||
```
|
||||
Claude 역할 사용자/팀장 역할
|
||||
┌───────────────────────┐ ┌─────────────────┐
|
||||
│ 코드 작성/수정 │ │ │
|
||||
│ git add / git commit │ │ │
|
||||
│ │──push──→ │ git push │
|
||||
│ 서버 진단 (Level 1) │ │ │
|
||||
│ 서버 변경 (Level 2) │──확인──→ │ 승인 │
|
||||
│ 위험 작업 (Level 3) │──안내──→ │ 직접 실행 │
|
||||
└───────────────────────┘ └─────────────────┘
|
||||
Claude 역할 Jenkins (자동) 운영 서버
|
||||
┌───────────────────┐ ┌──────────────────┐ ┌──────────────┐
|
||||
│ 코드 작성/수정 │ │ │ │ │
|
||||
│ git add / commit │ │ │ │ │
|
||||
│ │─push──→ │ Gitea Webhook │ │ │
|
||||
│ │(사용자) │ → Jenkins 빌드 │ │ │
|
||||
│ │ │ → Lint/Test │ │ │
|
||||
│ │ │ → SSH Deploy ────│──→ │ git pull │
|
||||
│ │ │ │ │ composer │
|
||||
│ 서버 진단 (L1) │ │ │ │ migrate │
|
||||
│ 서버 변경 (L2) │─확인──→ │ │ │ │
|
||||
│ 위험 작업 (L3) │─안내──→ │ │ │ (팀장 직접) │
|
||||
└───────────────────┘ └──────────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
> **브랜치 전략**: `develop` → 개발 서버 (자동 배포), `main`/`master` → 운영 서버 (PR 머지 + 팀장 승인)
|
||||
|
||||
### 체크리스트 (서버 작업 시)
|
||||
|
||||
- [ ] Level 1 (읽기): 사용자 요청 시 즉시 실행
|
||||
@@ -220,39 +233,43 @@ Claude 역할 사용자/팀장 역할
|
||||
|
||||
## React 빌드/배포 정책 (필수 규칙)
|
||||
|
||||
> **경고: React(Next.js) 빌드는 반드시 로컬에서 실행합니다. 서버에서 빌드 절대 금지!**
|
||||
> **경고: React(Next.js) 빌드를 운영 서버에서 직접 실행하지 않는다!**
|
||||
|
||||
### 배경
|
||||
|
||||
서버 스펙(2코어, 3.8GB RAM, Swap 없음)으로는 Next.js 빌드 시 메모리 부족으로 20분 이상 소요되거나 실패한다.
|
||||
로컬(WSL)에서 빌드 후 결과물만 서버에 배포한다.
|
||||
개발 서버(2코어, 3.8GB RAM + Swap 4GB)에서 Jenkins가 React 빌드를 수행한다.
|
||||
Jenkins 빌드 실패 시 로컬(WSL)에서 빌드 후 결과물을 서버에 배포한다(fallback).
|
||||
|
||||
### 금지 사항
|
||||
|
||||
```
|
||||
❌ 서버에서 npm run build 실행 금지
|
||||
❌ 운영 서버에서 npm run build 실행 금지
|
||||
❌ 서버 SSH 접속 후 빌드 명령 실행 금지
|
||||
❌ Claude가 직접 npm run build 실행 금지 (로컬 포함)
|
||||
```
|
||||
|
||||
### 빌드/배포 방법
|
||||
### 빌드/배포 방법 (Jenkins 자동화)
|
||||
|
||||
```
|
||||
Claude 역할 사용자/팀장 역할
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ 코드 작성/수정 │ │ │
|
||||
│ git commit │──push──→ │ git pull │
|
||||
│ │ │ npm run build │
|
||||
│ │ │ 서비스 재시작 │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
Claude 역할 Jenkins (자동) 운영 서버
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌──────────────┐
|
||||
│ 코드 작성/수정 │ │ Checkout │ │ │
|
||||
│ git commit │─push──→ │ Install + Lint │ │ │
|
||||
│ │(사용자) │ Build (Next.js) │ │ │
|
||||
│ │ │ Package (tar.gz) │──scp→ │ 압축 해제 │
|
||||
│ │ │ │ │ node 재시작 │
|
||||
└─────────────────┘ └──────────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
> **Fallback**: Jenkins 빌드 실패(OOM) 시 로컬에서 `react/deploy.sh`로 수동 배포
|
||||
|
||||
### 빌드가 필요한 상황
|
||||
|
||||
사용자에게 다음과 같이 안내한다:
|
||||
|
||||
```
|
||||
React 코드가 변경되었습니다. git push 후 서버에서 배포해주세요.
|
||||
React 코드가 변경되었습니다. git push 후 Jenkins가 자동 배포합니다.
|
||||
(Jenkins 실패 시 로컬에서 deploy.sh로 수동 배포해주세요.)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -291,12 +308,26 @@ React 코드가 변경되었습니다. git push 후 서버에서 배포해주세
|
||||
# 로컬: 마이그레이션은 반드시 API 컨테이너에서 실행
|
||||
docker exec sam-api-1 php artisan migrate
|
||||
|
||||
# 서버: Docker 없음, 직접 실행
|
||||
# 개발 서버: Docker 없음, 직접 실행
|
||||
cd /home/webservice/api && php artisan migrate
|
||||
|
||||
# 운영 서버: --force 플래그 필수 (production 환경)
|
||||
cd /home/webservice/api && php artisan migrate --force
|
||||
|
||||
# MNG에서 마이그레이션 실행 금지 (로컬/서버 모두)
|
||||
```
|
||||
|
||||
### DB 환경 분리
|
||||
|
||||
| 환경 | DB명 | 호스트 | 용도 |
|
||||
|------|------|--------|------|
|
||||
| 로컬 (Docker) | `samdb` | `sam-mysql-1:3306` | 개발/테스트 |
|
||||
| 개발 서버 | `samdb` | `localhost` | 스테이징 |
|
||||
| 운영 서버 | `sam_prod` | `localhost` | 정식 서비스 |
|
||||
| 통계 DB | `sam_stat` | 동일 서버 | StatMonitorService 전용 |
|
||||
|
||||
> **참고**: `sam_stat`은 API/MNG 모두 `config/database.php`의 별도 connection으로 접속한다.
|
||||
|
||||
### 이유
|
||||
|
||||
- MNG: 프론트엔드/관리자 화면 담당 (컨트롤러, 뷰, 라우트)
|
||||
@@ -336,7 +367,8 @@ cd /home/webservice/api && php artisan migrate
|
||||
```
|
||||
메뉴를 추가하려면 아래 명령을 서버에서 실행해 주세요:
|
||||
|
||||
ssh sam-server "cd /home/webservice/mng && php artisan tinker --execute=\"
|
||||
# 개발 서버
|
||||
ssh pro@114.203.209.83 "cd /home/webservice/mng && php artisan tinker --execute=\"
|
||||
App\\Models\\Commons\\Menu::create([
|
||||
'tenant_id' => 1,
|
||||
'parent_id' => <부모ID>,
|
||||
@@ -347,6 +379,9 @@ App\\Models\\Commons\\Menu::create([
|
||||
'is_active' => true,
|
||||
]);
|
||||
\""
|
||||
|
||||
# 운영 서버 (동일 경로, 서버 주소만 변경)
|
||||
ssh <운영계정>@<운영서버IP> "cd /home/webservice/mng && php artisan tinker --execute=\"...동일...\""
|
||||
```
|
||||
|
||||
### 체크리스트 (메뉴 변경 요청 시)
|
||||
@@ -360,17 +395,20 @@ App\\Models\\Commons\\Menu::create([
|
||||
|
||||
## 실행 환경 (필수 인지)
|
||||
|
||||
> **중요: 로컬과 서버의 환경이 다릅니다!**
|
||||
> **중요: 로컬 / 개발 서버 / 운영 서버의 환경이 다릅니다!**
|
||||
|
||||
### 환경 비교
|
||||
### 환경 비교 (3-Tier)
|
||||
|
||||
| 항목 | 로컬 (WSL) | 서버 (운영) |
|
||||
|------|-----------|------------|
|
||||
| **구성 방식** | Docker 컨테이너 | 네이티브 설치 (Docker 없음) |
|
||||
| **PHP/Laravel** | 컨테이너 내부 | 서버에 직접 설치 |
|
||||
| **MySQL** | 컨테이너 (sam-mysql-1) | 서버에 직접 설치 |
|
||||
| **Nginx** | 컨테이너 (sam-nginx-1) | 서버에 직접 설치 |
|
||||
| **명령 실행** | `docker exec` 필요 | 직접 실행 |
|
||||
| 항목 | 로컬 (WSL) | 개발 서버 | 운영 서버 |
|
||||
|------|-----------|----------|----------|
|
||||
| **구성 방식** | Docker 컨테이너 | Bare-metal (네이티브) | Bare-metal (네이티브) |
|
||||
| **PHP** | 컨테이너 내부 (8.4) | 직접 설치 (8.4) | 직접 설치 (8.4) |
|
||||
| **MySQL** | 컨테이너 (sam-mysql-1) | 직접 설치 (8.0) | 직접 설치 (8.0) |
|
||||
| **Nginx** | 컨테이너 (sam-nginx-1) | 직접 설치 | 직접 설치 |
|
||||
| **명령 실행** | `docker exec` 필요 | 직접 실행 | 직접 실행 |
|
||||
| **서버 IP** | localhost | `114.203.209.83` | (신규, 미확정) |
|
||||
| **추가 서비스** | — | Jenkins, Gitea | — |
|
||||
| **DB** | `samdb` | `samdb` | `sam_prod` |
|
||||
|
||||
> **배경**: 서버는 Docker가 무거워서 PHP, Nginx, MySQL 등을 네이티브로 설치하여 운영한다.
|
||||
|
||||
@@ -388,27 +426,50 @@ PHP, Laravel, Node.js 등이 **Docker 컨테이너 안에** 설치되어 있다.
|
||||
└── sam-nginx-1 ← Nginx 웹서버
|
||||
```
|
||||
|
||||
### 서버 환경 (네이티브)
|
||||
### 서버 환경 (Bare-metal — 개발/운영 동일 구조)
|
||||
|
||||
서버에는 Docker가 없다. PHP, Nginx, MySQL이 직접 설치되어 있다.
|
||||
서버에는 Docker가 없다. PHP 8.4, Nginx, MySQL 8.0이 직접 설치되어 있다.
|
||||
|
||||
```
|
||||
운영 서버 (114.203.209.83)
|
||||
├── Nginx ← 웹서버 (직접 설치)
|
||||
├── PHP-FPM ← PHP 처리 (직접 설치)
|
||||
├── MySQL ← DB (직접 설치)
|
||||
├── /home/webservice/mng ← MNG 앱
|
||||
└── /home/webservice/api ← API 앱
|
||||
개발 서버 (114.203.209.83) 운영 서버 (신규)
|
||||
├── Nginx ├── Nginx
|
||||
├── PHP-FPM (3 pools) ├── PHP-FPM (3 pools)
|
||||
│ ├── api.sock │ ├── api.sock
|
||||
│ ├── mng.sock │ ├── mng.sock
|
||||
│ └── sales.sock │ └── sales.sock
|
||||
├── MySQL 8.0 (samdb) ├── MySQL 8.0 (sam_prod)
|
||||
├── Supervisor ├── Supervisor
|
||||
│ ├── sam-api-worker (x1) │ ├── sam-api-worker (x1)
|
||||
│ ├── sam-mng-worker (x2) │ ├── sam-mng-worker (x2)
|
||||
│ └── sam-api-scheduler │ └── sam-api-scheduler
|
||||
├── Node.js (React SSR :3000) ├── Node.js (React SSR :3000)
|
||||
├── Jenkins (:8080) │
|
||||
├── Gitea (:3000) │
|
||||
├── /home/webservice/api ├── /home/webservice/api
|
||||
├── /home/webservice/mng ├── /home/webservice/mng
|
||||
├── /home/webservice/react ├── /home/webservice/react
|
||||
└── /home/webservice/sales └── /home/webservice/sales
|
||||
```
|
||||
|
||||
### 명령어 비교 (로컬 vs 서버)
|
||||
### 도메인 매핑
|
||||
|
||||
| 작업 | 로컬 (Docker) | 서버 (네이티브) |
|
||||
|------|--------------|----------------|
|
||||
| 서비스 | 로컬 (Docker) | 개발 서버 | 운영 서버 |
|
||||
|--------|--------------|----------|----------|
|
||||
| React (사용자) | `dev.sam.kr` | `dev.codebridge-x.com` | `codebridge-x.com` |
|
||||
| API | `api.sam.kr` | `api.dev.codebridge-x.com` | `api.codebridge-x.com` |
|
||||
| MNG (관리자) | `mng.sam.kr` | `mng.dev.codebridge-x.com` | `mng.codebridge-x.com` |
|
||||
| Sales | `sales.sam.kr` | `sales.dev.codebridge-x.com` | `sales.codebridge-x.com` |
|
||||
| 5130 (레거시) | `5130.sam.kr` | — | — |
|
||||
|
||||
### 명령어 비교 (로컬 vs 개발 vs 운영)
|
||||
|
||||
| 작업 | 로컬 (Docker) | 개발/운영 서버 (네이티브) |
|
||||
|------|--------------|-------------------------|
|
||||
| artisan 실행 | `docker exec sam-api-1 php artisan <명령>` | `cd /home/webservice/api && php artisan <명령>` |
|
||||
| composer 실행 | `docker exec sam-api-1 composer install` | `cd /home/webservice/api && composer install` |
|
||||
| 마이그레이션 | `docker exec sam-api-1 php artisan migrate` | `cd /home/webservice/api && php artisan migrate` |
|
||||
| 마이그레이션 | `docker exec sam-api-1 php artisan migrate` | 개발: `php artisan migrate` / 운영: `php artisan migrate --force` |
|
||||
| 캐시 클리어 | `docker exec sam-mng-1 php artisan cache:clear` | `cd /home/webservice/mng && php artisan cache:clear` |
|
||||
| Queue 재시작 | — | `sudo supervisorctl restart sam-api-worker:*` |
|
||||
|
||||
### 로컬 Docker 명령어 패턴
|
||||
|
||||
@@ -434,6 +495,7 @@ docker exec sam-mng-1 php artisan cache:clear
|
||||
- [ ] **로컬**: `php artisan` → `docker exec sam-mng-1 php artisan` 또는 `sam-api-1` 사용
|
||||
- [ ] **로컬**: `composer` → `docker exec sam-mng-1 composer` 또는 `sam-api-1` 사용
|
||||
- [ ] **서버**: `php artisan`, `composer` 직접 실행 (Docker 없음)
|
||||
- [ ] **운영 서버 마이그레이션**: `--force` 플래그 필수
|
||||
- [ ] **마이그레이션은 반드시 API에서 실행** (로컬: `docker exec sam-api-1`, 서버: 직접)
|
||||
|
||||
---
|
||||
@@ -442,6 +504,22 @@ docker exec sam-mng-1 php artisan cache:clear
|
||||
|
||||
> **중요: 코드를 pull 받은 후 반드시 필요한 명령을 실행하세요!**
|
||||
|
||||
### 브랜치 전략
|
||||
|
||||
| 브랜치 | 배포 대상 | 트리거 | 승인 |
|
||||
|--------|----------|--------|------|
|
||||
| `feature/*` | — | — | — |
|
||||
| `develop` | 개발 서버 (`dev.codebridge-x.com`) | Push 시 자동 배포 | 불필요 |
|
||||
| `main`/`master` | 운영 서버 (`codebridge-x.com`) | PR 머지 시 Jenkins 배포 | 팀장 승인 필수 |
|
||||
|
||||
```
|
||||
feature/* ──→ develop ──→ main/master
|
||||
(push) (PR merge)
|
||||
↓ ↓
|
||||
개발 서버 운영 서버
|
||||
(자동 배포) (Jenkins CI/CD)
|
||||
```
|
||||
|
||||
### 로컬 환경 (Docker) 업데이트
|
||||
|
||||
```bash
|
||||
@@ -464,38 +542,64 @@ docker exec sam-api-1 php artisan config:clear
|
||||
docker exec sam-mng-1 php artisan config:clear
|
||||
```
|
||||
|
||||
### 서버 환경 업데이트 (네이티브 — Docker 없음)
|
||||
### 개발 서버 업데이트 (자동)
|
||||
|
||||
> 서버에는 Docker가 없다. PHP, Composer 등이 직접 설치되어 있으므로 명령어를 그대로 실행한다.
|
||||
> `develop` 브랜치에 Push 시 Gitea Webhook → Jenkins가 자동으로 배포한다.
|
||||
> 수동 배포가 필요한 경우:
|
||||
|
||||
```bash
|
||||
# API 프로젝트
|
||||
cd /home/webservice/api
|
||||
git pull
|
||||
git pull origin develop
|
||||
composer install
|
||||
php artisan migrate
|
||||
php artisan config:clear
|
||||
|
||||
# MNG 프로젝트 (마이그레이션 없음)
|
||||
cd /home/webservice/mng
|
||||
git pull
|
||||
git pull origin develop
|
||||
composer install
|
||||
php artisan config:clear
|
||||
```
|
||||
|
||||
### 운영 서버 배포 (Jenkins 자동화)
|
||||
|
||||
> `main`/`master` 브랜치에 PR 머지 시 Jenkins가 자동으로 배포한다.
|
||||
> 수동 배포는 **비상 절차**로만 사용한다.
|
||||
|
||||
```bash
|
||||
# 비상 수동 배포 (Jenkins 장애 시에만)
|
||||
# API 프로젝트
|
||||
cd /home/webservice/api
|
||||
git pull origin main
|
||||
composer install --no-dev --optimize-autoloader
|
||||
php artisan migrate --force
|
||||
php artisan config:clear && php artisan cache:clear && php artisan route:cache && php artisan view:cache
|
||||
sudo supervisorctl restart sam-api-worker:*
|
||||
|
||||
# MNG 프로젝트
|
||||
cd /home/webservice/mng
|
||||
git pull origin master
|
||||
composer install --no-dev --optimize-autoloader
|
||||
php artisan config:clear && php artisan cache:clear && php artisan view:cache
|
||||
sudo supervisorctl restart sam-mng-worker:*
|
||||
```
|
||||
|
||||
### 요약 표
|
||||
|
||||
| 작업 | 로컬 (Docker) | 서버 (네이티브) |
|
||||
|------|--------------|----------------|
|
||||
| git pull | WSL에서 직접 | 서버에서 직접 |
|
||||
| composer install | `docker exec sam-api-1 composer install` | `composer install` (직접) |
|
||||
| migrate | `docker exec sam-api-1 php artisan migrate` | `php artisan migrate` (직접) |
|
||||
| config:clear | `docker exec sam-api-1 php artisan config:clear` | `php artisan config:clear` (직접) |
|
||||
| 작업 | 로컬 (Docker) | 개발 서버 | 운영 서버 |
|
||||
|------|--------------|----------|----------|
|
||||
| 배포 방식 | 수동 | Jenkins 자동 (develop push) | Jenkins 자동 (main/master PR) |
|
||||
| git pull | WSL에서 직접 | Jenkins 자동 | Jenkins 자동 |
|
||||
| composer install | `docker exec sam-api-1 composer install` | Jenkins 자동 | `--no-dev --optimize-autoloader` |
|
||||
| migrate | `docker exec sam-api-1 php artisan migrate` | Jenkins 자동 | `--force` 플래그 포함 |
|
||||
| config:clear | `docker exec sam-api-1 php artisan config:clear` | Jenkins 자동 | `route:cache` + `view:cache` 포함 |
|
||||
|
||||
### 체크리스트 (pull 후)
|
||||
|
||||
- [ ] API: `git pull` → `composer install` → `php artisan migrate` → `config:clear`
|
||||
- [ ] MNG: `git pull` → `composer install` → `config:clear` (마이그레이션 없음)
|
||||
- [ ] 운영 배포: `main`/`master`에 PR 머지 → Jenkins 자동 처리 (수동 금지)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user