Files
Todo-Project/docs/DEPLOYMENT.md
Hyungi Ahn 761757c12e Initial commit: Todo Project with dashboard, classification center, and upload functionality
- 📱 PWA 지원: 홈화면 추가 가능한 Progressive Web App
- 🎨 M-Project 색상 스키마: 하늘색, 주황색, 회색, 흰색 일관된 디자인
- 📊 대시보드: 데스크톱 캘린더 뷰 + 모바일 일일 뷰 반응형 디자인
- 📥 분류 센터: Gmail 스타일 받은편지함으로 스마트 분류 시스템
- 🤖 AI 분류 제안: 키워드 기반 자동 분류 제안 및 일괄 처리
- 📷 업로드 모달: 데스크톱(파일 선택) + 모바일(카메라/갤러리) 최적화
- 🏷️ 3가지 분류: Todo(시작일), 캘린더(마감일), 체크리스트(무기한)
- 📋 체크리스트: 진행률 표시 및 완료 토글 기능
- 🔄 시놀로지 연동 준비: 메일플러스 연동을 위한 구조 설계
- 📱 반응형 UI: 모든 페이지 모바일 최적화 완료
2025-09-19 08:52:49 +09:00

9.9 KiB

배포 가이드 (DEPLOYMENT.md)

🚀 배포 개요

Todo-Project는 Docker를 사용한 컨테이너 기반 배포를 지원하며, 개인용 환경에 최적화되어 있습니다.

📋 사전 요구사항

시스템 요구사항

  • OS: Linux, macOS, Windows (Docker 지원)
  • RAM: 최소 2GB, 권장 4GB
  • Storage: 최소 10GB 여유 공간
  • Network: 인터넷 연결 (시놀로지 연동 시)

필수 소프트웨어

  • Docker 20.10+
  • Docker Compose 2.0+
  • Git (소스 코드 다운로드용)

🐳 Docker 배포

1. 소스 코드 다운로드

git clone https://github.com/your-username/Todo-Project.git
cd Todo-Project

2. 환경 설정

# 환경 변수 파일 생성
cp .env.example .env

# 환경 변수 편집
nano .env

기본 환경 변수 설정

# 데이터베이스 설정
DATABASE_URL=postgresql://todo_user:todo_password@database:5432/todo_db
POSTGRES_USER=todo_user
POSTGRES_PASSWORD=your_secure_password_here
POSTGRES_DB=todo_db

# JWT 설정 (반드시 변경!)
SECRET_KEY=your-very-long-and-random-secret-key-here-change-this-in-production
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

# 애플리케이션 설정
DEBUG=false
CORS_ORIGINS=["http://localhost:4000", "http://your-domain.com:4000"]

# 서버 설정
HOST=0.0.0.0
PORT=9000

# 시놀로지 연동 (선택사항)
SYNOLOGY_DSM_URL=https://your-nas.synology.me:5001
SYNOLOGY_USERNAME=todo_user
SYNOLOGY_PASSWORD=your_synology_password
ENABLE_SYNOLOGY_INTEGRATION=true

3. Docker Compose 실행

# 백그라운드에서 실행
docker-compose up -d

# 로그 확인
docker-compose logs -f

4. 서비스 확인

# 컨테이너 상태 확인
docker-compose ps

# 헬스 체크
curl http://localhost:9000/api/health

# 프론트엔드 접속
open http://localhost:4000

🔧 Docker Compose 구성

docker-compose.yml

version: '3.8'

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "4000:80"
    depends_on:
      - backend
    environment:
      - API_BASE_URL=http://localhost:9000/api
    volumes:
      - ./frontend/static:/usr/share/nginx/html/static
    restart: unless-stopped

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "9000:9000"
    depends_on:
      - database
    environment:
      - DATABASE_URL=postgresql://todo_user:${POSTGRES_PASSWORD}@database:5432/todo_db
      - SECRET_KEY=${SECRET_KEY}
      - DEBUG=${DEBUG:-false}
    volumes:
      - ./backend/uploads:/app/uploads
    restart: unless-stopped

  database:
    image: postgres:15-alpine
    ports:
      - "5434:5432"
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./database/init:/docker-entrypoint-initdb.d
    restart: unless-stopped

volumes:
  postgres_data:

프로덕션용 docker-compose.prod.yml

version: '3.8'

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.prod
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./ssl:/etc/nginx/ssl
      - ./nginx/nginx.prod.conf:/etc/nginx/nginx.conf
    restart: always

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.prod
    expose:
      - "9000"
    environment:
      - DEBUG=false
      - DATABASE_URL=postgresql://todo_user:${POSTGRES_PASSWORD}@database:5432/todo_db
    restart: always

  database:
    image: postgres:15-alpine
    expose:
      - "5432"
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./backups:/backups
    restart: always

volumes:
  postgres_data:

🌐 프로덕션 배포

1. SSL 인증서 설정

# Let's Encrypt 인증서 생성 (Certbot 사용)
sudo certbot certonly --standalone -d your-domain.com

# 인증서 파일 복사
sudo cp /etc/letsencrypt/live/your-domain.com/fullchain.pem ./ssl/
sudo cp /etc/letsencrypt/live/your-domain.com/privkey.pem ./ssl/

2. Nginx 설정 (프로덕션)

# nginx/nginx.prod.conf
server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;

    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    # Frontend
    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    # Backend API
    location /api/ {
        proxy_pass http://backend:9000/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 보안 헤더
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

3. 프로덕션 배포 실행

# 프로덕션 환경으로 배포
docker-compose -f docker-compose.prod.yml up -d

# 로그 모니터링
docker-compose -f docker-compose.prod.yml logs -f

🔄 업데이트 및 유지보수

애플리케이션 업데이트

# 소스 코드 업데이트
git pull origin main

# 컨테이너 재빌드 및 재시작
docker-compose down
docker-compose build --no-cache
docker-compose up -d

데이터베이스 백업

# 백업 스크립트 생성
cat > backup.sh << 'EOF'
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="todo_backup_${DATE}.sql"

docker-compose exec database pg_dump -U todo_user todo_db > ./backups/${BACKUP_FILE}
echo "백업 완료: ${BACKUP_FILE}"

# 7일 이상 된 백업 파일 삭제
find ./backups -name "todo_backup_*.sql" -mtime +7 -delete
EOF

chmod +x backup.sh

# 백업 실행
./backup.sh

데이터베이스 복원

# 백업에서 복원
docker-compose exec database psql -U todo_user -d todo_db < ./backups/todo_backup_20240115_120000.sql

로그 관리

# 로그 확인
docker-compose logs backend
docker-compose logs frontend
docker-compose logs database

# 로그 로테이션 설정
cat > /etc/logrotate.d/docker-compose << 'EOF'
/var/lib/docker/containers/*/*.log {
    rotate 7
    daily
    compress
    size=1M
    missingok
    delaycompress
    copytruncate
}
EOF

📊 모니터링

헬스 체크 스크립트

#!/bin/bash
# health_check.sh

API_URL="http://localhost:9000/api/health"
FRONTEND_URL="http://localhost:4000"

# API 헬스 체크
if curl -f -s $API_URL > /dev/null; then
    echo "✅ API 서버 정상"
else
    echo "❌ API 서버 오류"
    # 알림 발송 (예: 이메일, Slack 등)
fi

# 프론트엔드 체크
if curl -f -s $FRONTEND_URL > /dev/null; then
    echo "✅ 프론트엔드 정상"
else
    echo "❌ 프론트엔드 오류"
fi

# 데이터베이스 체크
if docker-compose exec database pg_isready -U todo_user > /dev/null; then
    echo "✅ 데이터베이스 정상"
else
    echo "❌ 데이터베이스 오류"
fi

시스템 리소스 모니터링

# 컨테이너 리소스 사용량 확인
docker stats

# 디스크 사용량 확인
df -h

# 메모리 사용량 확인
free -h

🔐 보안 설정

방화벽 설정 (Ubuntu/CentOS)

# UFW (Ubuntu)
sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP
sudo ufw allow 443/tcp   # HTTPS
sudo ufw enable

# firewalld (CentOS)
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

자동 보안 업데이트

# Ubuntu
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

# CentOS
sudo yum install yum-cron
sudo systemctl enable yum-cron
sudo systemctl start yum-cron

🚨 문제 해결

일반적인 문제들

1. 컨테이너 시작 실패

# 로그 확인
docker-compose logs backend

# 포트 충돌 확인
netstat -tulpn | grep :9000

# 권한 문제 확인
ls -la ./backend/uploads

2. 데이터베이스 연결 실패

# 데이터베이스 컨테이너 상태 확인
docker-compose exec database pg_isready -U todo_user

# 연결 테스트
docker-compose exec database psql -U todo_user -d todo_db -c "SELECT 1;"

3. 시놀로지 연동 문제

# 네트워크 연결 테스트
curl -k https://your-nas.synology.me:5001/webapi/auth.cgi

# DNS 해결 확인
nslookup your-nas.synology.me

성능 최적화

1. 데이터베이스 최적화

-- 인덱스 확인
SELECT schemaname, tablename, attname, n_distinct, correlation 
FROM pg_stats 
WHERE tablename = 'todo_items';

-- 쿼리 성능 분석
EXPLAIN ANALYZE SELECT * FROM todo_items WHERE user_id = 'uuid';

2. 캐싱 설정

# Redis 추가 (선택사항)
docker run -d --name redis -p 6379:6379 redis:alpine

📱 모바일 PWA 배포

PWA 설정 확인

// manifest.json 검증
{
    "name": "Todo Project",
    "short_name": "Todo",
    "start_url": "/",
    "display": "standalone",
    "background_color": "#6366f1",
    "theme_color": "#6366f1",
    "icons": [
        {
            "src": "/icons/icon-192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "/icons/icon-512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ]
}

Service Worker 등록

// sw.js 등록 확인
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js');
}

이 배포 가이드를 통해 안정적이고 확장 가능한 Todo-Project를 배포할 수 있습니다!