# 배포 가이드 (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. 소스 코드 다운로드 ```bash git clone https://github.com/your-username/Todo-Project.git cd Todo-Project ``` ### 2. 환경 설정 ```bash # 환경 변수 파일 생성 cp .env.example .env # 환경 변수 편집 nano .env ``` #### 기본 환경 변수 설정 ```bash # 데이터베이스 설정 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 실행 ```bash # 백그라운드에서 실행 docker-compose up -d # 로그 확인 docker-compose logs -f ``` ### 4. 서비스 확인 ```bash # 컨테이너 상태 확인 docker-compose ps # 헬스 체크 curl http://localhost:9000/api/health # 프론트엔드 접속 open http://localhost:4000 ``` ## 🔧 Docker Compose 구성 ### docker-compose.yml ```yaml 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 ```yaml 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 인증서 설정 ```bash # 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/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. 프로덕션 배포 실행 ```bash # 프로덕션 환경으로 배포 docker-compose -f docker-compose.prod.yml up -d # 로그 모니터링 docker-compose -f docker-compose.prod.yml logs -f ``` ## 🔄 업데이트 및 유지보수 ### 애플리케이션 업데이트 ```bash # 소스 코드 업데이트 git pull origin main # 컨테이너 재빌드 및 재시작 docker-compose down docker-compose build --no-cache docker-compose up -d ``` ### 데이터베이스 백업 ```bash # 백업 스크립트 생성 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 ``` ### 데이터베이스 복원 ```bash # 백업에서 복원 docker-compose exec database psql -U todo_user -d todo_db < ./backups/todo_backup_20240115_120000.sql ``` ### 로그 관리 ```bash # 로그 확인 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 ``` ## 📊 모니터링 ### 헬스 체크 스크립트 ```bash #!/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 ``` ### 시스템 리소스 모니터링 ```bash # 컨테이너 리소스 사용량 확인 docker stats # 디스크 사용량 확인 df -h # 메모리 사용량 확인 free -h ``` ## 🔐 보안 설정 ### 방화벽 설정 (Ubuntu/CentOS) ```bash # 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 ``` ### 자동 보안 업데이트 ```bash # 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. 컨테이너 시작 실패 ```bash # 로그 확인 docker-compose logs backend # 포트 충돌 확인 netstat -tulpn | grep :9000 # 권한 문제 확인 ls -la ./backend/uploads ``` #### 2. 데이터베이스 연결 실패 ```bash # 데이터베이스 컨테이너 상태 확인 docker-compose exec database pg_isready -U todo_user # 연결 테스트 docker-compose exec database psql -U todo_user -d todo_db -c "SELECT 1;" ``` #### 3. 시놀로지 연동 문제 ```bash # 네트워크 연결 테스트 curl -k https://your-nas.synology.me:5001/webapi/auth.cgi # DNS 해결 확인 nslookup your-nas.synology.me ``` ### 성능 최적화 #### 1. 데이터베이스 최적화 ```sql -- 인덱스 확인 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. 캐싱 설정 ```bash # Redis 추가 (선택사항) docker run -d --name redis -p 6379:6379 redis:alpine ``` ## 📱 모바일 PWA 배포 ### PWA 설정 확인 ```javascript // 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 등록 ```javascript // sw.js 등록 확인 if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js'); } ``` 이 배포 가이드를 통해 안정적이고 확장 가능한 Todo-Project를 배포할 수 있습니다!