From 215a3aa88015d8ae6f08de394d1c4d8fe5a2c959 Mon Sep 17 00:00:00 2001 From: AutonetSellCar Deploy Date: Tue, 30 Dec 2025 19:12:37 +0900 Subject: [PATCH] Add deployment guide with ASCII art diagrams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive documentation covering: - Full deployment pipeline overview - Server environment configuration - Step-by-step deployment process - Manual SCP deployment method - Docker container architecture - Rollback procedures - Quick reference commands - Troubleshooting guide πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- DEPLOYMENT_GUIDE.md | 719 ++++++++++++++++++++++++++++---------------- 1 file changed, 457 insertions(+), 262 deletions(-) diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md index 9e22ba8..c416b12 100644 --- a/DEPLOYMENT_GUIDE.md +++ b/DEPLOYMENT_GUIDE.md @@ -1,330 +1,525 @@ -# μ‚¬μ΄νŠΈ 배포 κ°€μ΄λ“œ +# AutonetSellCar.com 배포 κ°€μ΄λ“œ -## κ°œμš” - -이 λ¬Έμ„œλŠ” Next.js Frontend + FastAPI Backend μ‚¬μ΄νŠΈλ₯Ό Ubuntu μ„œλ²„μ— λ°°ν¬ν•˜λŠ” 전체 과정을 μ„€λͺ…ν•©λ‹ˆλ‹€. +이 λ¬Έμ„œλŠ” μ½”λ“œ μˆ˜μ •λΆ€ν„° 운영 λ°°ν¬κΉŒμ§€μ˜ 전체 과정을 μ„€λͺ…ν•©λ‹ˆλ‹€. --- -## 배포 μˆœμ„œλ„ +## 1. 전체 배포 흐름 κ°œμš” ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ μ‚¬μ΄νŠΈ 배포 전체 흐름 β”‚ +β”‚ 배포 νŒŒμ΄ν”„λΌμΈ 전체 흐름 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -1. 사전 μ€€λΉ„ - β”‚ - β”œβ”€β†’ DNS μ„€μ • (도메인 β†’ 곡인 IP) - β”‚ β”œβ”€ example.com β†’ 59.14.158.123 - β”‚ β”œβ”€ www.example.com β†’ 59.14.158.123 - β”‚ └─ api.example.com β†’ 59.14.158.123 β˜… μ€‘μš”: API μ„œλΈŒλ„λ©”μΈ ν•„μˆ˜ - β”‚ - β”œβ”€β†’ 곡유기 ν¬νŠΈν¬μ›Œλ”© - β”‚ β”œβ”€ 80 β†’ 192.168.0.201:80 (NPM) - β”‚ └─ 443 β†’ 192.168.0.201:443 (NPM) - β”‚ - └─→ μ„œλ²„ μ€€λΉ„ - β”œβ”€ Docker μ„€μΉ˜ - β”œβ”€ Node.js μ„€μΉ˜ - └─ Python μ„€μΉ˜ - -2. μ†ŒμŠ€μ½”λ“œ 전솑 - β”‚ - β”œβ”€β†’ μ••μΆ• (node_modules μ œμ™Έ) - β”‚ └─ 7z a -tzip project.zip frontend backend -xr!node_modules - β”‚ - β”œβ”€β†’ 전솑 (내뢀망 경유 ꢌμž₯) - β”‚ └─ scp project.zip damon@192.168.0.203:~/sites/project/ - β”‚ - └─→ μ••μΆ• ν•΄μ œ - └─ unzip project.zip - -3. Backend 배포 - β”‚ - β”œβ”€β†’ κ°€μƒν™˜κ²½ 생성 - β”‚ └─ python3 -m venv venv && source venv/bin/activate - β”‚ - β”œβ”€β†’ μ˜μ‘΄μ„± μ„€μΉ˜ - β”‚ └─ pip install -r requirements.txt - β”‚ - β”œβ”€β†’ β˜…β˜…β˜… CORS μ„€μ • μˆ˜μ • β˜…β˜…β˜… - β”‚ └─ config.py의 CORS_ORIGINS에 도메인 μΆ”κ°€ - β”‚ - http://example.com - β”‚ - https://example.com - β”‚ - http://www.example.com - β”‚ - https://www.example.com - β”‚ - β”œβ”€β†’ Admin 계정 생성/리셋 - β”‚ └─ python init_admin.py λ˜λŠ” reset_pw.py μ‹€ν–‰ - β”‚ - └─→ μ„œλ²„ μ‹€ν–‰ - └─ nohup uvicorn app.main:app --host 0.0.0.0 --port 8001 > ~/logs/backend.log 2>&1 & - -4. Frontend 배포 - β”‚ - β”œβ”€β†’ μ˜μ‘΄μ„± μ„€μΉ˜ - β”‚ └─ npm install - β”‚ - β”œβ”€β†’ β˜…β˜…β˜… ν™˜κ²½λ³€μˆ˜ μ„€μ • β˜…β˜…β˜… - β”‚ └─ echo "NEXT_PUBLIC_API_URL=http://api.example.com/api" > .env.local - β”‚ - β”œβ”€β†’ λΉŒλ“œ - β”‚ └─ npm run build - β”‚ - └─→ μ„œλ²„ μ‹€ν–‰ - └─ nohup sh -c 'PORT=3001 npm start' > ~/logs/frontend.log 2>&1 & - -5. NPM (Nginx Proxy Manager) μ„€μ • - β”‚ - β”œβ”€β†’ Frontend Proxy Host - β”‚ β”œβ”€ Domain: example.com, www.example.com - β”‚ β”œβ”€ Forward: 192.168.0.203:3001 - β”‚ └─ SSL: Let's Encrypt - β”‚ - └─→ β˜…β˜…β˜… API Proxy Host β˜…β˜…β˜… - β”œβ”€ Domain: api.example.com - β”œβ”€ Forward: 192.168.0.203:8001 - └─ SSL: Let's Encrypt - -6. ν…ŒμŠ€νŠΈ - β”‚ - β”œβ”€β†’ μ‚¬μ΄νŠΈ 접속: http://example.com - β”œβ”€β†’ API 접속: http://api.example.com/api/health - └─→ Admin 둜그인: http://example.com/admin/login + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ 1. 개발 β”‚ ───▢ β”‚ 2. 컀밋 β”‚ ───▢ β”‚ 3. μŠ€ν…Œμ΄μ§• β”‚ ───▢ β”‚ 4. 운영 β”‚ + β”‚ (μ„œλ²„4) β”‚ β”‚ & Push β”‚ β”‚ ν…ŒμŠ€νŠΈ β”‚ β”‚ 배포 β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό β–Ό + μ½”λ“œ μˆ˜μ • git commit Docker λΉŒλ“œ promote + 둜컬 ν…ŒμŠ€νŠΈ git push staging 포트 3001/8001 포트 3000/8000 ``` --- -## 핡심 체크리슀트 +## 2. μ„œλ²„ ν™˜κ²½ ꡬ성 -### 배포 μ „ ν•„μˆ˜ 확인 사항 - -- [ ] DNS에 api μ„œλΈŒλ„λ©”μΈ A λ ˆμ½”λ“œ μΆ”κ°€ν–ˆλŠ”κ°€? -- [ ] NPM에 api.도메인 ν”„λ‘μ‹œ μ„€μ •ν–ˆλŠ”κ°€? -- [ ] Backend CORS_ORIGINS에 도메인 μΆ”κ°€ν–ˆλŠ”κ°€? -- [ ] Frontend .env.local에 API URL μ„€μ •ν–ˆλŠ”κ°€? -- [ ] Admin 계정이 DB에 μ‘΄μž¬ν•˜λŠ”κ°€? - ---- - -## 자주 λ°œμƒν•˜λŠ” λ¬Έμ œμ™€ 해결법 - -### 1. μ‚¬μ΄νŠΈ λ‘œλ”©λ§Œ 계속됨 (λ±…κΈ€λ±…κΈ€) - -**원인**: Frontendκ°€ API에 μ—°κ²°ν•˜μ§€ λͺ»ν•¨ - -**확인 μˆœμ„œ**: -```bash -# 1. Backend μ‹€ν–‰ 확인 -ps aux | grep uvicorn - -# 2. API 직접 ν…ŒμŠ€νŠΈ -curl http://api.example.com/api/health - -# 3. .env.local 확인 -cat ~/sites/project/frontend/.env.local - -# 4. λΉŒλ“œμ— ν™˜κ²½λ³€μˆ˜ 적용 확인 -grep -r "api.example" ~/sites/project/frontend/.next/ | head -3 ``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ λ„€νŠΈμ›Œν¬ ꡬ성도 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -**ν•΄κ²°**: -```bash -# .env.local μ„€μ • ν›„ μž¬λΉŒλ“œ -echo "NEXT_PUBLIC_API_URL=http://api.example.com/api" > .env.local -rm -rf .next -npm run build + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ μ„œλ²„4 β”‚ β”‚ μ„œλ²„2 β”‚ + β”‚ (개발 μ„œλ²„) β”‚ β”‚ (운영 μ„œλ²„) β”‚ + β”‚ β”‚ SSH/SCP β”‚ 192.168.0.202 β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ─────────────────▢ β”‚ β”‚ + β”‚ β”‚ μ†ŒμŠ€ μ½”λ“œ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ (둜컬 개발) β”‚ β”‚ β”‚ β”‚ Staging β”‚ β”‚ Production β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ :3001/:8001β”‚ β”‚ :3000/:8000β”‚ β”‚ + β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ D:\Workspace\ β”‚ β”‚ β”‚ + β”‚ claudeCode\ β”‚ β”‚ /opt/autonet/ β”‚ + β”‚ AutonetSellCar.comβ”‚ β”‚ β”œβ”€β”€ staging/ β”‚ + β”‚ β”‚ β”‚ β”œβ”€β”€ production/ β”‚ + β”‚ β”‚ β”‚ └── git/autonet.git β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- -### 2. CORS μ—λŸ¬ +## 3. 디렉토리 ꡬ쑰 -**원인**: Backendμ—μ„œ Frontend 도메인을 ν—ˆμš©ν•˜μ§€ μ•ŠμŒ - -**증상**: λΈŒλΌμš°μ € Network νƒ­μ—μ„œ "CORS error" ν‘œμ‹œ - -**확인**: -```bash -cat ~/sites/project/backend/app/core/config.py | grep CORS ``` - -**ν•΄κ²°**: config.py의 CORS_ORIGINS에 도메인 μΆ”κ°€ -```python -CORS_ORIGINS: list = [ - "http://localhost:3000", - "http://example.com", - "https://example.com", - "http://www.example.com", - "https://www.example.com" -] -``` - -Backend μž¬μ‹œμž‘: -```bash -pkill -f uvicorn -nohup uvicorn app.main:app --host 0.0.0.0 --port 8001 > ~/logs/backend.log 2>&1 & +μ„œλ²„2 (/opt/autonet/) +β”‚ +β”œβ”€β”€ git/ +β”‚ └── autonet.git/ # Bare Git Repository +β”‚ └── hooks/ +β”‚ └── post-receive # μžλ™ 배포 ν›… +β”‚ +β”œβ”€β”€ staging/ # μŠ€ν…Œμ΄μ§• ν™˜κ²½ +β”‚ β”œβ”€β”€ frontend/ +β”‚ β”œβ”€β”€ backend/ +β”‚ └── docker-compose.staging.yml +β”‚ +β”œβ”€β”€ production/ # 운영 ν™˜κ²½ +β”‚ β”œβ”€β”€ frontend/ +β”‚ β”œβ”€β”€ backend/ +β”‚ └── docker-compose.production.yml +β”‚ +β”œβ”€β”€ releases/ # 둀백용 λ°±μ—… +β”‚ β”œβ”€β”€ 20241230_140000/ +β”‚ └── 20241230_150000/ +β”‚ +└── scripts/ + β”œβ”€β”€ deploy-staging.sh + └── deploy.sh ``` --- -### 3. 둜그인 μ•ˆ 됨 +## 4. 단계별 상세 μ„€λͺ… -**원인**: DB에 admin 계정이 μ—†κ±°λ‚˜ λΉ„λ°€λ²ˆν˜Έκ°€ 닀름 +### Step 1: μ½”λ“œ μˆ˜μ • (μ„œλ²„4) -**확인**: -```bash -# API 직접 ν…ŒμŠ€νŠΈ -curl -X POST "http://api.example.com/api/auth/login" \ - -H "Content-Type: application/json" \ - -d '{"username":"admin","password":"λΉ„λ°€λ²ˆν˜Έ"}' +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Step 1: μ½”λ“œ μˆ˜μ • β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + 개발자 PC (μ„œλ²„4) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ D:\Workspace\claudeCode\ β”‚ + β”‚ └── AutonetSellCar.com\ β”‚ + β”‚ β”œβ”€β”€ backend\ β”‚ + β”‚ β”‚ └── app\ β”‚ + β”‚ β”‚ β”œβ”€β”€ api\ ◀── μˆ˜μ • β”‚ + β”‚ β”‚ β”œβ”€β”€ models\ β”‚ + β”‚ β”‚ └── schemas\ ◀── μˆ˜μ • β”‚ + β”‚ β”‚ β”‚ + β”‚ └── frontend\ β”‚ + β”‚ └── src\ β”‚ + β”‚ β”œβ”€β”€ app\ ◀── μˆ˜μ • β”‚ + β”‚ β”œβ”€β”€ components\ ◀── μˆ˜μ • β”‚ + β”‚ └── lib\ ◀── μˆ˜μ • β”‚ + β”‚ β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ 둜컬 ν…ŒμŠ€νŠΈ μ„œλ²„ β”‚ β”‚ + β”‚ β”‚ Frontend: http://localhost:3000β”‚ β”‚ + β”‚ β”‚ Backend: http://localhost:8000β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + λͺ…λ Ήμ–΄: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ # Backend μ‹€ν–‰ β”‚ + β”‚ cd backend β”‚ + β”‚ venv\Scripts\activate β”‚ + β”‚ uvicorn app.main:app --reload --port 8000β”‚ + β”‚ β”‚ + β”‚ # Frontend μ‹€ν–‰ β”‚ + β”‚ cd frontend β”‚ + β”‚ npm run dev β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -**ν•΄κ²°**: λΉ„λ°€λ²ˆν˜Έ 리셋 슀크립트 μ‹€ν–‰ -```bash -cd ~/sites/project/backend -source venv/bin/activate -cat > reset_pw.py << 'EOF' -from app.core.database import SessionLocal -from app.models.admin import Admin -from app.core.security import get_password_hash -db = SessionLocal() -admin = db.query(Admin).filter(Admin.username == 'admin').first() -if admin: - admin.password_hash = get_password_hash('μƒˆλΉ„λ°€λ²ˆν˜Έ') - db.commit() - print('Password reset') -else: - print('Admin not found') -db.close() -EOF -python reset_pw.py +### Step 2: Git Commit & Push + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Step 2: Git Commit & Push β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ μ„œλ²„4 β”‚ β”‚ μ„œλ²„2 β”‚ + β”‚ (개발) β”‚ β”‚ (운영) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β”‚ 1. git add . β”‚ + β”‚ 2. git commit -m "message" β”‚ + β”‚ β”‚ + β–Ό β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ Local Repo β”‚ β”‚ + β”‚ (main) β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ + β”‚ 3. git push staging main β”‚ + β”‚ β”‚ + β”‚ SSH (포트 22) β”‚ + β”‚ ════════════════════════════════════▢ β”‚ + β”‚ β–Ό + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ Bare Repo β”‚ + β”‚ β”‚ autonet.git β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β”‚ β”‚ post-receive ν›… μ‹€ν–‰ + β”‚ β–Ό + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ μŠ€ν…Œμ΄μ§• β”‚ + β”‚ β”‚ μžλ™ 배포 β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + λͺ…λ Ήμ–΄: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ git status β”‚ + β”‚ git add . β”‚ + β”‚ git commit -m "feat: κΈ°λŠ₯ μ„€λͺ…" β”‚ + β”‚ git push staging main β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Step 3: μŠ€ν…Œμ΄μ§• ν…ŒμŠ€νŠΈ + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Step 3: μŠ€ν…Œμ΄μ§• ν…ŒμŠ€νŠΈ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + μ„œλ²„2 μŠ€ν…Œμ΄μ§• ν™˜κ²½ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ /opt/autonet/staging/ β”‚ + β”‚ β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ Frontend Container β”‚ β”‚ Backend Container β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ autonet-frontend β”‚ β”‚ autonet-backend β”‚ β”‚ + β”‚ β”‚ -staging β”‚ β”‚ -staging β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ Port: 3001 ─────┼─────▢ Port: 8001 β”‚ β”‚ + β”‚ β”‚ β”‚ API β”‚ β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ β”‚ + β”‚ β–Ό β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ staging-db β”‚ β”‚ + β”‚ β”‚ (SQLite/Volume) β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + ν…ŒμŠ€νŠΈ URL: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Frontend: http://192.168.0.202:3001 β”‚ + β”‚ Backend: http://192.168.0.202:8001 β”‚ + β”‚ API Docs: http://192.168.0.202:8001/docsβ”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + μˆ˜λ™ λΉŒλ“œ λͺ…λ Ήμ–΄ (SSH 접속 ν›„): + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ cd /opt/autonet/staging β”‚ + β”‚ docker compose -f docker-compose.staging.yml downβ”‚ + β”‚ docker compose -f docker-compose.staging.yml build --no-cacheβ”‚ + β”‚ docker compose -f docker-compose.staging.yml up -dβ”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Step 4: 운영 배포 (Promote) + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Step 4: 운영 배포 (Promote) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ μŠ€ν…Œμ΄μ§• β”‚ promote β”‚ 운영 β”‚ + β”‚ (ν…ŒμŠ€νŠΈ μ™„λ£Œ) β”‚ ══════════▢ β”‚ (μ„œλΉ„μŠ€ 쀑) β”‚ + β”‚ :3001 / :8001 β”‚ β”‚ :3000 / :8000 β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β”‚ β–Ό + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ λ°±μ—… 생성 β”‚ + β”‚ β”‚ /releases/ β”‚ + β”‚ β”‚ 20241230_160000/ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + 배포 흐름: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ 1. ν˜„μž¬ 운영 λ°±μ—… β”‚ + β”‚ └── /opt/autonet/releases/20241230_160000/ β”‚ + β”‚ β”‚ + β”‚ 2. 운영 μ»¨ν…Œμ΄λ„ˆ 쀑지 β”‚ + β”‚ └── docker compose down β”‚ + β”‚ β”‚ + β”‚ 3. μŠ€ν…Œμ΄μ§• β†’ 운영 볡사 (DB/uploads μ œμ™Έ) β”‚ + β”‚ └── rsync -av --exclude='*.db' staging/ production/ β”‚ + β”‚ β”‚ + β”‚ 4. 운영 μ»¨ν…Œμ΄λ„ˆ λΉŒλ“œ & μ‹œμž‘ β”‚ + β”‚ └── docker compose up -d --build β”‚ + β”‚ β”‚ + β”‚ 5. ν—¬μŠ€μ²΄ν¬ β”‚ + β”‚ └── curl http://localhost:3000 && curl http://localhost:8000 β”‚ + β”‚ β”‚ + β”‚ 6. μ‹€νŒ¨ μ‹œ μžλ™ λ‘€λ°± β”‚ + β”‚ └── deploy.sh rollback β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + λͺ…λ Ήμ–΄: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ # μŠ€ν…Œμ΄μ§• β†’ 운영 승격 β”‚ + β”‚ /opt/autonet/scripts/deploy.sh promote β”‚ + β”‚ β”‚ + β”‚ # λ‘€λ°± (문제 λ°œμƒ μ‹œ) β”‚ + β”‚ /opt/autonet/scripts/deploy.sh rollback β”‚ + β”‚ β”‚ + β”‚ # μƒνƒœ 확인 β”‚ + β”‚ /opt/autonet/scripts/deploy.sh status β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- -### 4. 포트 좩돌 (EADDRINUSE) +## 5. μˆ˜λ™ 배포 방법 (SCP 직접 전솑) -**원인**: κΈ°μ‘΄ ν”„λ‘œμ„ΈμŠ€κ°€ 포트λ₯Ό 점유 쀑 +κΈ΄κΈ‰ 배포 λ˜λŠ” post-receive ν›… λ―Έμ„€μ • μ‹œ μ‚¬μš©ν•©λ‹ˆλ‹€. -**확인**: -```bash -sudo netstat -tlnp | grep 3001 -sudo netstat -tlnp | grep 8001 ``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ μˆ˜λ™ 배포 (SCP 방식) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -**ν•΄κ²°**: -```bash -# PID 확인 ν›„ μ’…λ£Œ -sudo kill -9 + μ„œλ²„4 (개발) μ„œλ²„2 (운영) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ β”‚ + β”‚ μˆ˜μ •λœ 파일 β”‚ SCP 전솑 β”‚ production/ β”‚ + β”‚ frontend/ β”‚ ═══════════════════════▢│ frontend/ β”‚ + β”‚ backend/ β”‚ β”‚ backend/ β”‚ + β”‚ β”‚ β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Docker μž¬λΉŒλ“œ β”‚ + β”‚ β”‚ + β”‚ docker build β”‚ + β”‚ docker run β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -# λ˜λŠ” ν”„λ‘œμ„ΈμŠ€ μ΄λ¦„μœΌλ‘œ μ’…λ£Œ -pkill -f "npm start" -pkill -f uvicorn + Step 1: 파일 전솑 (PowerShellμ—μ„œ) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ # Frontend 파일 전솑 β”‚ + β”‚ scp -r frontend/src/app/admin/*.tsx \ β”‚ + β”‚ damon@192.168.0.202:/opt/autonet/production/frontend/src/app/admin/β”‚ + β”‚ β”‚ + β”‚ # Backend 파일 전솑 β”‚ + β”‚ scp -r backend/app/* \ β”‚ + β”‚ damon@192.168.0.202:/opt/autonet/production/backend/app/ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + Step 2: Docker μž¬λΉŒλ“œ (μ„œλ²„2 SSH 접속 ν›„) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ cd /opt/autonet/production β”‚ + β”‚ β”‚ + β”‚ # Frontend μž¬λΉŒλ“œ β”‚ + β”‚ docker stop autonet-frontend β”‚ + β”‚ docker rm autonet-frontend β”‚ + β”‚ docker build -t autonet-frontend-prod \ β”‚ + β”‚ --build-arg NEXT_PUBLIC_API_URL=http://192.168.0.202:8000 \ β”‚ + β”‚ ./frontend β”‚ + β”‚ docker run -d --name autonet-frontend \ β”‚ + β”‚ -p 3000:3000 \ β”‚ + β”‚ -e NEXT_PUBLIC_API_URL=http://192.168.0.202:8000 \ β”‚ + β”‚ autonet-frontend-prod β”‚ + β”‚ β”‚ + β”‚ # Backend μž¬λΉŒλ“œ β”‚ + β”‚ docker stop autonet-backend β”‚ + β”‚ docker rm autonet-backend β”‚ + β”‚ docker build -t autonet-backend-prod ./backend β”‚ + β”‚ docker run -d --name autonet-backend \ β”‚ + β”‚ -p 8000:8000 \ β”‚ + β”‚ -v $(pwd)/backend/uploads:/app/uploads \ β”‚ + β”‚ -v $(pwd)/backend/autonet.db:/app/autonet.db \ β”‚ + β”‚ autonet-backend-prod β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- -### 5. 500 Internal Server Error (정적 파일) +## 6. Docker μ»¨ν…Œμ΄λ„ˆ ꡬ성 -**원인**: λΉŒλ“œ 파일 손상 λ˜λŠ” μΊμ‹œ 문제 +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Docker μ»¨ν…Œμ΄λ„ˆ ꡬ성도 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -**ν•΄κ²°**: -```bash -cd ~/sites/project/frontend -pkill -f "npm start" -rm -rf .next -rm -rf node_modules/.cache -npm run build -nohup sh -c 'PORT=3001 npm start' > ~/logs/frontend.log 2>&1 & + 운영 ν™˜κ²½ (Production) + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ Docker Network β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ autonet-frontendβ”‚ API β”‚ autonet-backend β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ │───────▢│ β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ Next.js 14 β”‚ β”‚ FastAPI β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ Port: 3000 β”‚ β”‚ Port: 8000 β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ Volumes β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ - autonet.db β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ - uploads/ β”‚ β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ + β”‚ β”‚ β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + β”‚ β”‚ carmodoo-agent β”‚ (Playwright λΈŒλΌμš°μ € μžλ™ν™”) β”‚ + β”‚ β”‚ - PDF 생성 β”‚ β”‚ + β”‚ β”‚ - μ°¨λŸ‰ μŠ€νŽ™ 쑰회 β”‚ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + 포트 λ§€ν•‘: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ 호슀트:3000 ──▢ μ»¨ν…Œμ΄λ„ˆ:3000 (Frontend)β”‚ + β”‚ 호슀트:8000 ──▢ μ»¨ν…Œμ΄λ„ˆ:8000 (Backend) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- -## μœ μš©ν•œ λͺ…λ Ήμ–΄ λͺ¨μŒ +## 7. λ‘€λ°± 절차 -### ν”„λ‘œμ„ΈμŠ€ 관리 - -```bash -# ν”„λ‘œμ„ΈμŠ€ 확인 -ps aux | grep -E "npm|uvicorn|node" - -# 포트 μ‚¬μš© 확인 -sudo netstat -tlnp | grep -E "3001|8001" - -# 둜그 확인 -tail -f ~/logs/frontend.log -tail -f ~/logs/backend.log ``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ λ‘€λ°± 절차 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -### μ„œλΉ„μŠ€ μž¬μ‹œμž‘ + 문제 λ°œμƒ! + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” μ•„λ‹ˆμ˜€ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ μžλ™ λ‘€λ°± β”‚ ◀────────────── β”‚ ν—¬μŠ€μ²΄ν¬ 톡과?β”‚ + β”‚ 싀행됨 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ 예 + β”‚ β–Ό + β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ 배포 μ™„λ£Œ β”‚ + β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + β”‚ /opt/autonet/releases/ β”‚ + β”‚ β”‚ β”‚ + β”‚ β”œβ”€β”€ 20241230_140000/ ◀── 이전 λ²„μ „μœΌλ‘œ 볡원 β”‚ + β”‚ β”œβ”€β”€ 20241230_150000/ β”‚ + β”‚ └── 20241230_160000/ ◀── ν˜„μž¬ (문제 λ°œμƒ) β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -```bash -# Frontend μž¬μ‹œμž‘ -pkill -f "npm start" -cd ~/sites/project/frontend -nohup sh -c 'PORT=3001 npm start' > ~/logs/frontend.log 2>&1 & - -# Backend μž¬μ‹œμž‘ -pkill -f uvicorn -cd ~/sites/project/backend -source venv/bin/activate -nohup uvicorn app.main:app --host 0.0.0.0 --port 8001 > ~/logs/backend.log 2>&1 & -``` - -### API ν…ŒμŠ€νŠΈ - -```bash -# Health check -curl http://api.example.com/api/health - -# 둜그인 ν…ŒμŠ€νŠΈ -curl -X POST "http://api.example.com/api/auth/login" \ - -H "Content-Type: application/json" \ - -d '{"username":"admin","password":"password"}' + λ‘€λ°± λͺ…λ Ήμ–΄: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ # 직전 λ²„μ „μœΌλ‘œ λ‘€λ°± β”‚ + β”‚ /opt/autonet/scripts/deploy.sh rollback β”‚ + β”‚ β”‚ + β”‚ # νŠΉμ • λ²„μ „μœΌλ‘œ λ‘€λ°± β”‚ + β”‚ /opt/autonet/scripts/deploy.sh \ β”‚ + β”‚ rollback-to 20241230_140000 β”‚ + β”‚ β”‚ + β”‚ # μ‚¬μš© κ°€λŠ₯ν•œ 버전 확인 β”‚ + β”‚ ls /opt/autonet/releases/ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- -## μ„œλ²„ 정보 +## 8. λΉ λ₯Έ μ°Έμ‘° λͺ…λ Ήμ–΄ -### λ„€νŠΈμ›Œν¬ ꡬ성 +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ λΉ λ₯Έ μ°Έμ‘° λͺ…λ Ήμ–΄ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -| μ„œλ²„ | λ‚΄λΆ€ IP | μ—­ν•  | -|------|---------|------| -| Server1 | 192.168.0.201 | NPM, PostgreSQL, Redis, λͺ¨λ‹ˆν„°λ§ | -| Server2 | 192.168.0.202 | MongolCar (autonetsellcar.com) | -| Server3 | 192.168.0.203 | Grantech, Cylinx | -| Server4 | 192.168.0.204 | Windows PC (파일 전솑 쀑계) | + ╔═══════════════════════════════════════════════════════════════════════════╗ + β•‘ 개발 (μ„œλ²„4) β•‘ + ╠═══════════════════════════════════════════════════════════════════════════╣ + β•‘ git status # λ³€κ²½ 파일 확인 β•‘ + β•‘ git add . # μŠ€ν…Œμ΄μ§• β•‘ + β•‘ git commit -m "message" # 컀밋 β•‘ + β•‘ git push staging main # μ„œλ²„2둜 ν‘Έμ‹œ β•‘ + β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• -### μ™ΈλΆ€ 접속 + ╔═══════════════════════════════════════════════════════════════════════════╗ + β•‘ 운영 (μ„œλ²„2) β•‘ + ╠═══════════════════════════════════════════════════════════════════════════╣ + β•‘ docker ps # μ‹€ν–‰ 쀑인 μ»¨ν…Œμ΄λ„ˆ 확인 β•‘ + β•‘ docker logs autonet-frontend # ν”„λ‘ νŠΈμ—”λ“œ 둜그 β•‘ + β•‘ docker logs autonet-backend # λ°±μ—”λ“œ 둜그 β•‘ + β•‘ docker restart autonet-frontend # ν”„λ‘ νŠΈμ—”λ“œ μž¬μ‹œμž‘ β•‘ + β•‘ docker restart autonet-backend # λ°±μ—”λ“œ μž¬μ‹œμž‘ β•‘ + β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• -| 포트 | μš©λ„ | -|------|------| -| 80, 443 | NPM (μ›Ή μ„œλΉ„μŠ€) | -| 81 | NPM 관리 νŽ˜μ΄μ§€ | -| 201, 202, 203 | SSH (각 μ„œλ²„) | - -### 도메인 - -| 도메인 | μ„œλΉ„μŠ€ | -|--------|--------| -| autonetsellcar.com | MongolCar | -| grantech.kr | Grantech | -| api.grantech.kr | Grantech API | -| cylinx.kr | Cylinx (μ˜ˆμ •) | + ╔═══════════════════════════════════════════════════════════════════════════╗ + β•‘ 배포 슀크립트 β•‘ + ╠═══════════════════════════════════════════════════════════════════════════╣ + β•‘ ./deploy.sh promote # μŠ€ν…Œμ΄μ§• β†’ 운영 승격 β•‘ + β•‘ ./deploy.sh rollback # 직전 버전 λ‘€λ°± β•‘ + β•‘ ./deploy.sh rollback-to # νŠΉμ • 버전 λ‘€λ°± β•‘ + β•‘ ./deploy.sh status # ν˜„μž¬ μƒνƒœ 확인 β•‘ + β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +``` --- -## 버전 정보 +## 9. 체크리슀트 -- Node.js: 20.x -- Python: 3.10 -- Next.js: 16.x -- FastAPI: Latest -- Ubuntu: 22.04 +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 배포 μ „ 체크리슀트 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + 배포 μ „: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ [ ] λ‘œμ»¬μ—μ„œ ν…ŒμŠ€νŠΈ μ™„λ£Œ β”‚ + β”‚ [ ] git status둜 λ³€κ²½ 파일 확인 β”‚ + β”‚ [ ] λΆˆν•„μš”ν•œ 파일 μ œμ™Έ (.env, node_modules λ“±) β”‚ + β”‚ [ ] 컀밋 λ©”μ‹œμ§€ μž‘μ„± β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + μŠ€ν…Œμ΄μ§• ν…ŒμŠ€νŠΈ: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ [ ] Frontend 정상 μž‘λ™ (http://192.168.0.202:3001) β”‚ + β”‚ [ ] Backend API 정상 μž‘λ™ (http://192.168.0.202:8001/docs) β”‚ + β”‚ [ ] μ£Όμš” κΈ°λŠ₯ ν…ŒμŠ€νŠΈ μ™„λ£Œ β”‚ + β”‚ [ ] μ—λŸ¬ 둜그 확인 (docker logs) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + 운영 배포 ν›„: + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ [ ] ν—¬μŠ€μ²΄ν¬ 톡과 β”‚ + β”‚ [ ] μ£Όμš” νŽ˜μ΄μ§€ 접속 확인 β”‚ + β”‚ [ ] API 응닡 확인 β”‚ + β”‚ [ ] 이전 버전 λ°±μ—… 확인 (/opt/autonet/releases/) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` --- -*μ΅œμ’… μ—…λ°μ΄νŠΈ: 2025-12-05* +## 10. 문제 ν•΄κ²° + +| 문제 | ν•΄κ²° 방법 | +|------|----------| +| μ»¨ν…Œμ΄λ„ˆ μ‹œμž‘ μ•ˆλ¨ | `docker logs ` 둜그 확인 | +| 포트 좩돌 | `netstat -tlnp \| grep ` 확인 ν›„ ν”„λ‘œμ„ΈμŠ€ μ’…λ£Œ | +| 이미지 λΉŒλ“œ μ‹€νŒ¨ | `docker build --no-cache` μΊμ‹œ 없이 μž¬λΉŒλ“œ | +| DB μ—°κ²° 였λ₯˜ | Volume 마운트 확인, 파일 κΆŒν•œ 확인 | +| API 404 였λ₯˜ | Backend μ»¨ν…Œμ΄λ„ˆ μž¬μ‹œμž‘, λΌμš°ν„° 등둝 확인 | + +--- + +**μ΅œμ’… μ—…λ°μ΄νŠΈ**: 2024-12-30