Files
AutonetSellCar/DEPLOYMENT_GUIDE.md
AutonetSellCar Deploy e661d91c72 fix: banner translations and deployment improvements
- Add translateCarName import from i18n.ts for proper multilingual support
- Change default API language from 'ko' to 'en' for hero banners
- Add checkbox column for Local Cars banner registration
- Update Dockerfile with Playwright dependencies
- Add PostgreSQL migration script
- Add banner translation fix script

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-31 10:41:42 +09:00

26 KiB

AutonetSellCar.com 배포 가이드

이 문서는 시스템 아키텍처와 코드 수정부터 운영 배포까지의 전체 과정을 설명합니다.


1. 시스템 아키텍처 개요

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         AutonetSellCar.com 시스템 아키텍처                        │
└─────────────────────────────────────────────────────────────────────────────────┘

                              ┌─────────────────┐
                              │   인터넷        │
                              │ 59.14.158.123   │
                              └────────┬────────┘
                                       │
                    ┌──────────────────┼──────────────────┐
                    │                  │                  │
                    ▼                  ▼                  ▼
        autonetsellcar.com    autonetsellcar.com   autonetsellcar.com
              /                    /api                /uploads
                    │                  │                  │
                    └──────────────────┼──────────────────┘
                                       │
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│                           서버1 (192.168.0.201)                                  │
│                              인프라 서버                                          │
│  ┌─────────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐ │
│  │ Nginx Proxy     │  │ PostgreSQL  │  │   Redis     │  │ Portainer/Grafana   │ │
│  │ Manager         │  │   :5432     │  │   :6379     │  │ Prometheus          │ │
│  │ :80/:443        │  │             │  │             │  │                     │ │
│  │                 │  │ DB: autonet │  │             │  │                     │ │
│  └────────┬────────┘  └──────┬──────┘  └──────┬──────┘  └─────────────────────┘ │
│           │                  │                │                                  │
└───────────┼──────────────────┼────────────────┼──────────────────────────────────┘
            │                  │                │
            │                  └────────┬───────┘
            │                           │
            ▼                           ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│                           서버2 (192.168.0.202)                                  │
│                             애플리케이션 서버                                      │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │                        Production Environment                            │   │
│  │  ┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐   │   │
│  │  │ autonet-frontend │    │ autonet-backend  │    │ carmodoo-agent   │   │   │
│  │  │ Next.js 14       │───▶│ FastAPI          │───▶│ Playwright       │   │   │
│  │  │ :3000            │    │ :8000            │    │ PDF/Spec 조회    │   │   │
│  │  └──────────────────┘    └────────┬─────────┘    └──────────────────┘   │   │
│  │                                   │                                      │   │
│  │                                   │ PostgreSQL/Redis                     │   │
│  │                                   └──────────────────────────────────────┼───┼──▶ 서버1
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │                        Staging Environment                               │   │
│  │  ┌──────────────────┐    ┌──────────────────┐                           │   │
│  │  │ frontend-staging │    │ backend-staging  │                           │   │
│  │  │ :3001            │    │ :8001            │                           │   │
│  │  └──────────────────┘    └──────────────────┘                           │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           서버4 (개발 PC)                                        │
│                                                                                 │
│  D:\Workspace\claudeCode\AutonetSellCar.com\                                    │
│  ├── frontend/     (Next.js)                                                    │
│  ├── backend/      (FastAPI)                                                    │
│  └── carmodoo-agent/                                                            │
│                                                                                 │
│  로컬 테스트: localhost:3000 / localhost:8000                                    │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

2. 서버별 역할 및 구성

서버1 (192.168.0.201) - 인프라 서버

서비스 포트 역할
Nginx Proxy Manager 80, 443, 81 리버스 프록시, SSL 인증서 관리
PostgreSQL 5432 메인 데이터베이스 (autonet)
Redis 6379 캐시, 세션 관리
Portainer 9000 Docker 관리 UI
Prometheus 9090 메트릭 수집
Grafana 3000 모니터링 대시보드

서버2 (192.168.0.202) - 애플리케이션 서버

컨테이너 포트 역할
autonet-frontend 3000 Next.js 프론트엔드 (운영)
autonet-backend 8000 FastAPI 백엔드 (운영)
carmodoo-agent - Playwright 기반 PDF/스펙 조회
autonet-frontend-staging 3001 스테이징 프론트엔드
autonet-backend-staging 8001 스테이징 백엔드

3. 도메인 및 라우팅 설정

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         Nginx Proxy Manager 설정                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

    autonetsellcar.com (SSL: Let's Encrypt)
    │
    ├── /           ──▶  192.168.0.202:3000  (Frontend)
    │
    ├── /api/*      ──▶  192.168.0.202:8000  (Backend)
    │   └── Custom Location: /api
    │       Forward: http://192.168.0.202:8000
    │
    └── /uploads/*  ──▶  192.168.0.202:8000  (Backend Static)
        └── Custom Location: /uploads
            Forward: http://192.168.0.202:8000

    설정 방법:
    ┌─────────────────────────────────────────────────────────────────────────┐
    │ 1. Nginx Proxy Manager (http://192.168.0.201:81) 접속                   │
    │ 2. Proxy Hosts > autonetsellcar.com 선택                                │
    │ 3. Custom Locations 탭에서 /api, /uploads 추가                          │
    │    - Location: /api                                                     │
    │    - Scheme: http                                                       │
    │    - Forward Hostname: 192.168.0.202                                    │
    │    - Forward Port: 8000                                                 │
    └─────────────────────────────────────────────────────────────────────────┘

4. PostgreSQL 설정

4.1 서버1 PostgreSQL Docker 컨테이너

# PostgreSQL 컨테이너 정보 확인
docker exec postgres-primary env | grep POSTGRES

# 출력:
# POSTGRES_USER=admin
# POSTGRES_PASSWORD=roskfl@1122
# POSTGRES_DB=mongolcar

4.2 데이터베이스 생성

# autonet 데이터베이스 생성
docker exec -it postgres-primary psql -U admin -d postgres -c "CREATE DATABASE autonet;"

# 비밀번호 재설정 (필요시)
docker exec -it postgres-primary psql -U admin -d postgres -c "ALTER USER admin PASSWORD 'roskfl@1122';"

4.3 외부 접속 설정 확인

# pg_hba.conf 확인 (외부 접속 허용)
docker exec postgres-primary cat /var/lib/postgresql/data/pg_hba.conf | grep -v "^#" | grep -v "^$"

# 필수 설정:
# host all all all scram-sha-256

4.4 백엔드 PostgreSQL 연결 설정

backend/.env:

# Database
USE_SQLITE=False
DB_HOST=192.168.0.201
DB_PORT=5432
DB_NAME=autonet
DB_USER=admin
DB_PASSWORD=roskfl@1122

backend/app/config.py:

@property
def DATABASE_URL(self) -> str:
    if self.USE_SQLITE:
        base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        db_path = os.path.join(base_dir, "autonet.db")
        return f"sqlite:///{db_path}"
    # URL-encode password for special characters like @ # etc
    from urllib.parse import quote_plus
    encoded_password = quote_plus(self.DB_PASSWORD)
    return f"postgresql://{self.DB_USER}:{encoded_password}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}"

4.5 SQLite → PostgreSQL 마이그레이션

# 개발 서버(서버4)에서 실행
cd D:\Workspace\claudeCode\AutonetSellCar.com\backend

# psycopg2 설치
venv\Scripts\pip.exe install psycopg2-binary

# 마이그레이션 스크립트 실행
venv\Scripts\python.exe migrate_to_postgres.py

마이그레이션 스크립트 주요 기능:

  • PostgreSQL에 테이블 자동 생성 (SQLAlchemy 모델 기반)
  • SQLite boolean (0/1) → PostgreSQL boolean (true/false) 변환
  • FK 제약조건 임시 비활성화 후 데이터 이전
  • Sequence 자동 리셋

5. Docker Compose 설정

5.1 Docker Compose v2 설치 (서버2)

# Docker 공식 저장소 추가
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg -y
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Docker Compose 플러그인 설치
sudo apt-get update
sudo apt-get install docker-compose-plugin -y

# 버전 확인
docker compose version

5.2 docker-compose.production.yml

services:
  frontend:
    build: ./frontend
    container_name: autonet-frontend
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - NEXT_PUBLIC_API_URL=https://autonetsellcar.com
    depends_on:
      - backend
    networks:
      - autonet-production-network

  backend:
    build: ./backend
    container_name: autonet-backend
    ports:
      - "8000:8000"
    environment:
      - ENV=production
    env_file:
      - ./backend/.env
    volumes:
      - ./backend/uploads:/app/uploads
    networks:
      - autonet-production-network

  carmodoo-agent:
    build: ./carmodoo-agent
    container_name: carmodoo-agent
    networks:
      - autonet-production-network

networks:
  autonet-production-network:
    driver: bridge

5.3 주요 Docker 명령어

# 전체 시작
docker compose -f docker-compose.production.yml up -d

# 특정 서비스 재빌드 (캐시 없이)
docker compose -f docker-compose.production.yml build backend --no-cache
docker compose -f docker-compose.production.yml up -d backend

# 로그 확인
docker logs autonet-backend --tail 50 -f

# 컨테이너 상태
docker ps

# 전체 중지 및 제거
docker compose -f docker-compose.production.yml down

# 네트워크/볼륨 문제 시
docker rm -f autonet-backend autonet-frontend carmodoo-agent
docker network rm autonet-production-network
docker compose -f docker-compose.production.yml up -d

6. 배포 흐름

┌─────────────────────────────────────────────────────────────────────────────────┐
│                              배포 파이프라인                                      │
└─────────────────────────────────────────────────────────────────────────────────┘

  ┌──────────────┐      ┌──────────────┐      ┌──────────────┐      ┌──────────────┐
  │   1. 개발    │ ───▶ │  2. 커밋     │ ───▶ │  3. 스테이징 │ ───▶ │  4. 운영     │
  │   (서버4)    │      │  & Push      │      │  테스트      │      │  배포        │
  └──────────────┘      └──────────────┘      └──────────────┘      └──────────────┘
        │                     │                     │                     │
        ▼                     ▼                     ▼                     ▼
   코드 수정            git commit           Docker 빌드            promote
   로컬 테스트          git push staging     :3001/:8001            :3000/:8000

Step 1: 개발 (서버4)

# 로컬 개발 서버 실행
cd backend && venv\Scripts\activate
uvicorn app.main:app --reload --port 8000

cd frontend
npm run dev

# 테스트: http://localhost:3000

Step 2: Git Commit & Push

git status
git add .
git commit -m "feat: 기능 설명"
git push staging main

Step 3: 스테이징 테스트

# 서버2 SSH 접속 후
cd /opt/autonet/staging
docker compose -f docker-compose.staging.yml build --no-cache
docker compose -f docker-compose.staging.yml up -d

# 테스트 URL
# Frontend: http://192.168.0.202:3001
# Backend:  http://192.168.0.202:8001/docs

Step 4: 운영 배포

# 서버2에서
cd /opt/autonet/production
docker compose -f docker-compose.production.yml build --no-cache
docker compose -f docker-compose.production.yml up -d

# 또는 스크립트 사용
/opt/autonet/scripts/deploy.sh promote

# 운영 URL
# https://autonetsellcar.com
# https://autonetsellcar.com/api/docs

7. 디렉토리 구조

서버2 (/opt/autonet/)
│
├── git/
│   └── autonet.git/              # Bare Git Repository
│       └── hooks/
│           └── post-receive      # 자동 배포 훅
│
├── staging/                      # 스테이징 환경
│   ├── frontend/
│   ├── backend/
│   │   └── .env                  # 스테이징 환경변수
│   └── docker-compose.staging.yml
│
├── production/                   # 운영 환경
│   ├── frontend/
│   ├── backend/
│   │   ├── .env                  # 운영 환경변수 (PostgreSQL)
│   │   ├── requirements.txt      # psycopg2-binary 포함
│   │   └── app/
│   │       └── config.py         # URL 인코딩 적용
│   ├── carmodoo-agent/
│   └── docker-compose.production.yml
│
├── releases/                     # 롤백용 백업
│   ├── 20241230_140000/
│   └── 20241230_150000/
│
└── scripts/
    ├── deploy-staging.sh
    └── deploy.sh

8. 환경변수 설정

운영 서버 backend/.env 전체

# Database (PostgreSQL)
USE_SQLITE=False
DB_HOST=192.168.0.201
DB_PORT=5432
DB_NAME=autonet
DB_USER=admin
DB_PASSWORD=roskfl@1122

# Redis
REDIS_HOST=192.168.0.201
REDIS_PORT=6379
REDIS_PASSWORD=

# JWT
SECRET_KEY=your-secret-key-change-in-production

# App
DEBUG=False

# Azure Translator
AZURE_TRANSLATOR_KEY=your-azure-key
AZURE_TRANSLATOR_REGION=southeastasia

# Email (SMTP)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=autonetsellcar@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=autonetsellcar@gmail.com
SMTP_FROM_NAME=AutonetSellCar

# Verification
VERIFICATION_CODE_EXPIRE_MINUTES=10
EMAIL_VERIFICATION_REQUIRED=True

9. 문제 해결

PostgreSQL 연결 오류

# 에러: could not translate host name "1122@192.168.0.201"
# 원인: 비밀번호에 @ 문자가 URL 구분자로 인식됨
# 해결: config.py에서 URL 인코딩 적용

from urllib.parse import quote_plus
encoded_password = quote_plus(self.DB_PASSWORD)

Docker 네트워크 충돌

# 에러: network was found but has incorrect label
docker compose -f docker-compose.production.yml down
docker network rm autonet-production-network
docker compose -f docker-compose.production.yml up -d

컨테이너 이름 충돌

# 에러: container name is already in use
docker rm -f autonet-backend autonet-frontend carmodoo-agent
docker compose -f docker-compose.production.yml up -d

psycopg2 모듈 없음

# requirements.txt에 추가
psycopg2-binary  # PostgreSQL production

# 또는 직접 추가
echo "psycopg2-binary" >> /opt/autonet/production/backend/requirements.txt
docker compose -f docker-compose.production.yml build backend --no-cache

Mixed Content 에러

# 에러: Mixed Content - HTTPS 페이지에서 HTTP API 호출
# 해결: Frontend 빌드 시 HTTPS API URL 사용
NEXT_PUBLIC_API_URL=https://autonetsellcar.com

10. 빠른 참조 명령어

╔═══════════════════════════════════════════════════════════════════════════════╗
║  개발 (서버4)                                                                 ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║  git status                    # 변경 파일 확인                               ║
║  git add .                     # 스테이징                                     ║
║  git commit -m "message"       # 커밋                                        ║
║  git push staging main         # 서버2로 푸시                                ║
╚═══════════════════════════════════════════════════════════════════════════════╝

╔═══════════════════════════════════════════════════════════════════════════════╗
║  운영 (서버2)                                                                 ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║  docker ps                              # 실행 중인 컨테이너                   ║
║  docker logs autonet-backend --tail 50  # 백엔드 로그                         ║
║  docker compose -f docker-compose.production.yml up -d        # 시작          ║
║  docker compose -f docker-compose.production.yml down         # 중지          ║
║  docker compose -f docker-compose.production.yml build --no-cache # 재빌드    ║
╚═══════════════════════════════════════════════════════════════════════════════╝

╔═══════════════════════════════════════════════════════════════════════════════╗
║  PostgreSQL (서버1)                                                           ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║  docker exec -it postgres-primary psql -U admin -d autonet    # DB 접속       ║
║  \dt                                                          # 테이블 목록   ║
║  \q                                                           # 종료          ║
╚═══════════════════════════════════════════════════════════════════════════════╝

11. 체크리스트

최초 서버 설정

  • 서버1: PostgreSQL 컨테이너 실행 중
  • 서버1: autonet 데이터베이스 생성
  • 서버1: 외부 접속 허용 (pg_hba.conf)
  • 서버1: Nginx Proxy Manager SSL 설정
  • 서버1: Custom Location (/api, /uploads) 설정
  • 서버2: Docker Compose v2 설치
  • 서버2: backend/.env PostgreSQL 설정
  • 서버2: requirements.txt에 psycopg2-binary 추가
  • 서버2: config.py URL 인코딩 적용

배포 전

  • 로컬 테스트 완료
  • git status로 변경 파일 확인
  • 커밋 메시지 작성

배포 후

  • docker ps로 컨테이너 상태 확인
  • docker logs로 에러 확인
  • https://autonetsellcar.com 접속 테스트
  • API 응답 확인 (/api/docs)

최종 업데이트: 2024-12-30