Files
AutonetSellCar/SERVER_INFRASTRUCTURE_PLAN.md
AutonetSellCar Deploy 1f0dcb1ddb Initial commit: AutonetSellCar platform with deployment system
- Frontend: Next.js 14 with TypeScript
- Backend: FastAPI with SQLAlchemy
- Agent: Carmodoo sync agent
- Deployment: Docker Compose based staging/production setup
- Scripts: Automated deployment with rollback support

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 13:24:39 +09:00

20 KiB

MongolCar 서버 인프라 구성 계획

1. 서버 현황

서버 IP CPU RAM SSD 상태
Server1 192.168.0.201 Ryzen 7700 64GB 2TB 신규 설치
Server2 192.168.0.202 Ryzen 7700 64GB 확인 필요 정리 필요
Server3 192.168.0.203 Ryzen 7700 64GB 확인 필요 정리 필요

2. 운영 사이트

도메인 용도
www.autonetsellcar.com 몽골 중고차 수출 플랫폼 (MongolCar)
www.grantech.kr Grantech 기업 사이트
www.cylinx.kr Cylinx 기업 사이트

3. 권장 아키텍처: Master-Worker 구성

3.1 서버 역할 분배

┌─────────────────────────────────────────────────────────────────────┐
│                        Server1 (192.168.0.201)                       │
│                           [ MASTER NODE ]                            │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │
│  │   Nginx     │  │  PostgreSQL │  │    Redis    │                  │
│  │   Proxy     │  │   (Primary) │  │   (Primary) │                  │
│  │   Manager   │  │             │  │             │                  │
│  └─────────────┘  └─────────────┘  └─────────────┘                  │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │
│  │  Portainer  │  │   Grafana   │  │ Prometheus  │                  │
│  │  (Docker)   │  │ (Monitoring)│  │  (Metrics)  │                  │
│  └─────────────┘  └─────────────┘  └─────────────┘                  │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                        Server2 (192.168.0.202)                       │
│                          [ WORKER NODE 1 ]                           │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │              www.autonetsellcar.com (MongolCar)           │       │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐       │       │
│  │  │   Next.js   │  │   FastAPI   │  │   Carmodoo  │       │       │
│  │  │  Frontend   │  │   Backend   │  │    Agent    │       │       │
│  │  │   :3000     │  │   :8000     │  │  (Cron Job) │       │       │
│  │  └─────────────┘  └─────────────┘  └─────────────┘       │       │
│  └──────────────────────────────────────────────────────────┘       │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐                                   │
│  │ PostgreSQL  │  │    Redis    │                                   │
│  │  (Replica)  │  │  (Replica)  │                                   │
│  └─────────────┘  └─────────────┘                                   │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                        Server3 (192.168.0.203)                       │
│                          [ WORKER NODE 2 ]                           │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │                   www.grantech.kr                         │       │
│  │  ┌─────────────┐  ┌─────────────┐                        │       │
│  │  │   Next.js   │  │   FastAPI   │                        │       │
│  │  │  Frontend   │  │   Backend   │                        │       │
│  │  │   :3001     │  │   :8001     │                        │       │
│  │  └─────────────┘  └─────────────┘                        │       │
│  └──────────────────────────────────────────────────────────┘       │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │                    www.cylinx.kr                          │       │
│  │  ┌─────────────┐  ┌─────────────┐                        │       │
│  │  │   Next.js   │  │   FastAPI   │                        │       │
│  │  │  Frontend   │  │   Backend   │                        │       │
│  │  │   :3002     │  │   :8002     │                        │       │
│  │  └─────────────┘  └─────────────┘                        │       │
│  └──────────────────────────────────────────────────────────┘       │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐                                   │
│  │ PostgreSQL  │  │    Redis    │                                   │
│  │  (Replica)  │  │  (Replica)  │                                   │
│  └─────────────┘  └─────────────┘                                   │
└─────────────────────────────────────────────────────────────────────┘

4. 네트워크 구성

4.1 외부 접근 (인터넷 → 서버)

인터넷
   │
   ▼
┌─────────────────┐
│   공유기/방화벽   │
│   (Port Forward) │
└─────────────────┘
   │
   ├── 80/443 ──→ Server1:80/443 (Nginx Proxy Manager)
   │
   └── 22 ──→ Server1:22 (SSH - VPN 권장)

4.2 내부 네트워크

용도 포트 서버
SSH 22 모든 서버
PostgreSQL 5432 Server1 (Primary)
Redis 6379 Server1 (Primary)
Nginx Proxy Manager 80, 443, 81 Server1
Portainer 9000 Server1
Grafana 3100 Server1
Prometheus 9090 Server1
MongolCar Frontend 3000 Server2
MongolCar Backend 8000 Server2
Grantech Frontend 3001 Server3
Grantech Backend 8001 Server3
Cylinx Frontend 3002 Server3
Cylinx Backend 8002 Server3

5. Docker 컨테이너 구성

5.1 Server1 (Master) - docker-compose.yml

version: '3.8'

services:
  # Reverse Proxy
  nginx-proxy-manager:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
      - '81:81'  # Admin UI
    volumes:
      - ./data/nginx/data:/data
      - ./data/nginx/letsencrypt:/etc/letsencrypt

  # Database
  postgres:
    image: postgres:16-alpine
    container_name: postgres-primary
    restart: unless-stopped
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: mongolcar
    ports:
      - '5432:5432'
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
      - ./init-db:/docker-entrypoint-initdb.d

  # Cache
  redis:
    image: redis:7-alpine
    container_name: redis-primary
    restart: unless-stopped
    ports:
      - '6379:6379'
    volumes:
      - ./data/redis:/data
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}

  # Docker Management
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - '9000:9000'
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data/portainer:/data

  # Monitoring
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    ports:
      - '9090:9090'
    volumes:
      - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./data/prometheus:/prometheus

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    ports:
      - '3100:3000'
    environment:
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
    volumes:
      - ./data/grafana:/var/lib/grafana

networks:
  default:
    name: master-network

5.2 Server2 (MongolCar) - docker-compose.yml

version: '3.8'

services:
  # MongolCar Frontend
  mongolcar-frontend:
    build: ./mongolcar/frontend
    container_name: mongolcar-frontend
    restart: unless-stopped
    ports:
      - '3000:3000'
    environment:
      - NEXT_PUBLIC_API_URL=http://192.168.0.202:8000
    depends_on:
      - mongolcar-backend

  # MongolCar Backend
  mongolcar-backend:
    build: ./mongolcar/backend
    container_name: mongolcar-backend
    restart: unless-stopped
    ports:
      - '8000:8000'
    environment:
      - DATABASE_URL=postgresql://admin:${DB_PASSWORD}@192.168.0.201:5432/mongolcar
      - REDIS_URL=redis://:${REDIS_PASSWORD}@192.168.0.201:6379/0
      - SECRET_KEY=${SECRET_KEY}
    volumes:
      - ./data/uploads:/app/uploads

  # Carmodoo Agent (차량 데이터 수집)
  carmodoo-agent:
    build: ./carmodoo-agent
    container_name: carmodoo-agent
    restart: unless-stopped
    environment:
      - CARMODOO_USER_ID=${CARMODOO_USER_ID}
      - CARMODOO_PASSWORD=${CARMODOO_PASSWORD}
      - API_SERVER_URL=http://mongolcar-backend:8000/api
      - AGENT_API_KEY=${AGENT_API_KEY}
    volumes:
      - ./data/agent:/app/data
      - ./logs/agent:/app/logs
    depends_on:
      - mongolcar-backend

networks:
  default:
    name: mongolcar-network

5.3 Server3 (Grantech & Cylinx) - docker-compose.yml

version: '3.8'

services:
  # Grantech Frontend
  grantech-frontend:
    build: ./grantech/frontend
    container_name: grantech-frontend
    restart: unless-stopped
    ports:
      - '3001:3000'
    environment:
      - NEXT_PUBLIC_API_URL=http://192.168.0.203:8001

  # Grantech Backend
  grantech-backend:
    build: ./grantech/backend
    container_name: grantech-backend
    restart: unless-stopped
    ports:
      - '8001:8000'
    environment:
      - DATABASE_URL=postgresql://admin:${DB_PASSWORD}@192.168.0.201:5432/grantech
      - REDIS_URL=redis://:${REDIS_PASSWORD}@192.168.0.201:6379/1

  # Cylinx Frontend
  cylinx-frontend:
    build: ./cylinx/frontend
    container_name: cylinx-frontend
    restart: unless-stopped
    ports:
      - '3002:3000'
    environment:
      - NEXT_PUBLIC_API_URL=http://192.168.0.203:8002

  # Cylinx Backend
  cylinx-backend:
    build: ./cylinx/backend
    container_name: cylinx-backend
    restart: unless-stopped
    ports:
      - '8002:8000'
    environment:
      - DATABASE_URL=postgresql://admin:${DB_PASSWORD}@192.168.0.201:5432/cylinx
      - REDIS_URL=redis://:${REDIS_PASSWORD}@192.168.0.201:6379/2

networks:
  default:
    name: sites-network

6. 데이터베이스 설계

6.1 PostgreSQL 데이터베이스 분리

데이터베이스 용도 Redis DB
mongolcar MongolCar 서비스 0
grantech Grantech 서비스 1
cylinx Cylinx 서비스 2

6.2 MongolCar 주요 테이블

-- 제조사
CREATE TABLE car_makers (
    id SERIAL PRIMARY KEY,
    code VARCHAR(10) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    name_en VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW()
);

-- 모델
CREATE TABLE car_models (
    id SERIAL PRIMARY KEY,
    code VARCHAR(10) NOT NULL,
    maker_id INTEGER REFERENCES car_makers(id),
    name VARCHAR(100) NOT NULL,
    name_en VARCHAR(100),
    UNIQUE(code, maker_id)
);

-- 차량
CREATE TABLE cars (
    id SERIAL PRIMARY KEY,
    source VARCHAR(50) NOT NULL DEFAULT 'carmodoo',
    source_id VARCHAR(50) NOT NULL,
    source_key TEXT,  -- encrypted key
    maker_id INTEGER REFERENCES car_makers(id),
    model_id INTEGER REFERENCES car_models(id),
    car_name VARCHAR(200),
    year INTEGER,
    month INTEGER,
    mileage INTEGER,
    price_krw BIGINT,
    price_usd DECIMAL(12,2),
    fuel VARCHAR(20),
    transmission VARCHAR(20),
    color VARCHAR(50),
    displacement INTEGER,
    car_number VARCHAR(20),
    seize_count INTEGER DEFAULT 0,
    collateral_count INTEGER DEFAULT 0,
    check_num VARCHAR(50),
    dealer_name VARCHAR(100),
    dealer_phone VARCHAR(50),
    shop_name VARCHAR(100),
    status VARCHAR(20) DEFAULT 'active',
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    synced_at TIMESTAMP,
    UNIQUE(source, source_id)
);

-- 차량 이미지
CREATE TABLE car_images (
    id SERIAL PRIMARY KEY,
    car_id INTEGER REFERENCES cars(id) ON DELETE CASCADE,
    url VARCHAR(500),
    local_path VARCHAR(500),
    is_main BOOLEAN DEFAULT FALSE,
    sort_order INTEGER DEFAULT 0
);

-- 차량 옵션
CREATE TABLE car_options (
    id SERIAL PRIMARY KEY,
    car_id INTEGER REFERENCES cars(id) ON DELETE CASCADE,
    option_name VARCHAR(100)
);

-- 사용자 (바이어)
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    name VARCHAR(100),
    phone VARCHAR(50),
    country VARCHAR(50) DEFAULT 'Mongolia',
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT NOW()
);

-- 문의
CREATE TABLE inquiries (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    car_id INTEGER REFERENCES cars(id),
    message TEXT,
    status VARCHAR(20) DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT NOW()
);

-- 인덱스
CREATE INDEX idx_cars_maker ON cars(maker_id);
CREATE INDEX idx_cars_model ON cars(model_id);
CREATE INDEX idx_cars_price ON cars(price_krw);
CREATE INDEX idx_cars_year ON cars(year);
CREATE INDEX idx_cars_status ON cars(status);

7. Nginx Proxy Manager 설정

7.1 Proxy Hosts 설정

Domain Scheme Forward Host Forward Port SSL
autonetsellcar.com http 192.168.0.202 3000 Let's Encrypt
api.autonetsellcar.com http 192.168.0.202 8000 Let's Encrypt
grantech.kr http 192.168.0.203 3001 Let's Encrypt
api.grantech.kr http 192.168.0.203 8001 Let's Encrypt
cylinx.kr http 192.168.0.203 3002 Let's Encrypt
api.cylinx.kr http 192.168.0.203 8002 Let's Encrypt
portainer.local http 192.168.0.201 9000 -
grafana.local http 192.168.0.201 3100 -

8. 설치 순서

Phase 1: Server1 (Master) 설정

# 1. Docker 설치
sudo apt update && sudo apt upgrade -y
sudo apt install -y docker.io docker-compose
sudo systemctl enable docker
sudo usermod -aG docker $USER

# 2. 디렉토리 구조 생성
mkdir -p ~/master/{data,config,init-db}
mkdir -p ~/master/data/{nginx,postgres,redis,portainer,prometheus,grafana}

# 3. docker-compose.yml 작성 및 실행
cd ~/master
# docker-compose.yml 파일 생성
docker-compose up -d

# 4. PostgreSQL 초기 DB 생성
docker exec -it postgres-primary psql -U admin -c "CREATE DATABASE grantech;"
docker exec -it postgres-primary psql -U admin -c "CREATE DATABASE cylinx;"

Phase 2: Server2 (MongolCar) 설정

# 1. Docker 설치 (동일)
# 2. 프로젝트 디렉토리 구조
mkdir -p ~/mongolcar/{frontend,backend,carmodoo-agent,data,logs}

# 3. 코드 배포 및 실행
cd ~/mongolcar
# docker-compose.yml 파일 생성
docker-compose up -d

Phase 3: Server3 (Grantech & Cylinx) 설정

# 1. Docker 설치 (동일)
# 2. 프로젝트 디렉토리 구조
mkdir -p ~/sites/{grantech,cylinx}
mkdir -p ~/sites/grantech/{frontend,backend}
mkdir -p ~/sites/cylinx/{frontend,backend}

# 3. 코드 배포 및 실행
cd ~/sites
# docker-compose.yml 파일 생성
docker-compose up -d

Phase 4: DNS 및 SSL 설정

# 1. 도메인 DNS A 레코드 설정 (공인 IP로)
# autonetsellcar.com → 공인IP
# grantech.kr → 공인IP
# cylinx.kr → 공인IP

# 2. 공유기 포트포워딩
# 80 → 192.168.0.201:80
# 443 → 192.168.0.201:443

# 3. Nginx Proxy Manager에서 SSL 인증서 발급
# http://192.168.0.201:81 접속
# Proxy Hosts 추가 및 Let's Encrypt SSL 설정

9. 백업 전략

9.1 자동 백업 스크립트 (Server1)

#!/bin/bash
# /home/user/backup.sh

BACKUP_DIR="/backup/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# PostgreSQL 백업
docker exec postgres-primary pg_dumpall -U admin > $BACKUP_DIR/postgres_all.sql

# Redis 백업
docker exec redis-primary redis-cli -a $REDIS_PASSWORD BGSAVE
cp ~/master/data/redis/dump.rdb $BACKUP_DIR/

# 7일 이상 된 백업 삭제
find /backup -type d -mtime +7 -exec rm -rf {} \;

9.2 Cron 설정

# 매일 새벽 3시 백업
0 3 * * * /home/user/backup.sh

10. 모니터링 항목

10.1 Prometheus 수집 대상

  • Node Exporter (각 서버 시스템 메트릭)
  • PostgreSQL Exporter
  • Redis Exporter
  • Docker Container 메트릭
  • Nginx 메트릭

10.2 Grafana 대시보드

  • 서버 리소스 (CPU, Memory, Disk, Network)
  • 컨테이너 상태
  • 데이터베이스 연결/쿼리 성능
  • API 응답시간
  • 에러율

11. 보안 체크리스트

  • SSH 키 기반 인증 설정
  • 방화벽 (UFW) 설정
  • Fail2ban 설치
  • 불필요한 포트 차단
  • PostgreSQL 외부 접근 제한
  • Redis 비밀번호 설정
  • HTTPS 강제 리다이렉트
  • 환경변수로 비밀정보 관리
  • 정기 보안 업데이트

12. 예상 리소스 사용량

서버 CPU 예상 RAM 예상 Disk 예상
Server1 (Master) 10-20% 8-12GB 100GB+
Server2 (MongolCar) 20-40% 8-16GB 500GB+ (이미지)
Server3 (Sites) 10-30% 4-8GB 50GB

13. 다음 단계

  1. Server2, Server3 SSD 용량 확인
  2. Server1 Docker 환경 구축
  3. MongolCar Backend API 개발 (FastAPI)
  4. MongolCar Frontend 개발 (Next.js)
  5. Carmodoo Agent Docker화
  6. DNS 설정 및 SSL 인증서 발급

Generated by Claude Code - 2025-11-28