Files
news-project/DEVELOPMENT_DEPLOYMENT_GUIDE.md
hyungi 016682269a 🧹 Consolidate documentation
-  Created unified DEVELOPMENT_DEPLOYMENT_GUIDE.md
- 🗑️ Removed individual setup guides:
  - TECH_STACK.md
  - HOMEBREW_SETUP.md
  - SYNOLOGY_SETUP.md
  - DS1525_OPTIMIZED_SETUP.md
  - DEV_DEPLOY_PIPELINE.md
  - DOCKER_DEV_GUIDE.md

All content consolidated into single development-deployment guide
focused on Mac → DS1525+ (32GB RAM) workflow
2025-09-14 12:58:55 +09:00

865 lines
20 KiB
Markdown

# 🚀 개발-배포 통합 가이드 (Mac → DS1525+ 32GB)
## 📋 개요
Mac에서 개발하고 Synology DS1525+ (32GB RAM, 480GB SSD)에 배포하는 완전한 개발-배포 파이프라인 가이드입니다.
---
## 🔧 하드웨어 사양
### 개발 환경: Mac
- **MacBook Pro/Mac Mini** (M1/M2 또는 Intel)
- **메모리**: 16GB 이상 권장
- **저장공간**: 100GB 이상 여유 공간
### 배포 환경: Synology DS1525+
- **CPU**: AMD Ryzen R1600 (4코어 2.6GHz)
- **메모리**: 32GB RAM (대용량!)
- **저장장치**: 시놀로지 정품 2.5" SSD 480GB
- **네트워크**: 기가비트 이더넷 x4
- **OS**: DSM 7.0+
---
## 🐳 Docker 기반 개발-배포 전략
### 아키텍처 호환성 해결
```
Mac (개발) DS1525+ (배포)
├── M1/M2: arm64 → ├── AMD Ryzen: amd64
├── Intel: amd64 → └── Linux 컨테이너
└── Docker Desktop └── Container Manager
```
**핵심 해결책: 멀티 아키텍처 빌드**
- Mac에서 개발: `arm64` 또는 `amd64`
- DS1525+에서 실행: `amd64` 보장
- 크로스 플랫폼 빌드로 호환성 문제 완전 해결
---
## 🛠️ 1단계: Mac 개발 환경 설정
### Docker Desktop 설치 및 최적화
```bash
# Homebrew로 Docker Desktop 설치
brew install --cask docker
# Docker Desktop 리소스 설정 (GUI)
# Memory: 8GB (16GB Mac 기준)
# CPUs: 4 cores
# Swap: 2GB
# Disk: 100GB
```
### Docker Buildx 설정 (멀티 아키텍처 빌드용)
```bash
# 멀티 플랫폼 빌더 생성
docker buildx create --name multiarch --driver docker-container --use
docker buildx inspect --bootstrap
# 지원 플랫폼 확인
docker buildx ls
```
### 프로젝트 구조 설정
```
project/
├── docker/
│ ├── Dockerfile.dev # Mac 개발용
│ ├── Dockerfile.prod # DS1525+ 배포용
│ ├── docker-compose.dev.yml # 로컬 개발
│ └── docker-compose.prod.yml# DS1525+ 배포
├── scripts/
│ ├── dev-start.sh # 개발 시작
│ ├── build-deploy.sh # 빌드 & 배포
│ └── rollback.sh # 롤백
├── src/
│ ├── backend/
│ └── frontend/
├── config/
│ ├── nginx/
│ ├── postgres/
│ └── monitoring/
└── environments/
├── .env.development
└── .env.production
```
---
## 🏗️ 2단계: 개발용 Docker 설정
### 개발용 Dockerfile
```dockerfile
# docker/Dockerfile.dev
FROM --platform=linux/amd64 python:3.11-slim
# 개발 도구 설치
RUN apt-get update && apt-get install -y \
gcc g++ curl vim git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Python 개발 의존성
COPY requirements.dev.txt .
RUN pip install --no-cache-dir -r requirements.dev.txt
# 환경 설정
ENV PYTHONPATH=/app
ENV PYTHONUNBUFFERED=1
ENV RELOAD=true
EXPOSE 8000 5678
# Hot Reload 개발 서버
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
```
### 개발용 Docker Compose
```yaml
# docker/docker-compose.dev.yml
version: '3.8'
services:
app:
build:
context: ..
dockerfile: docker/Dockerfile.dev
platform: linux/amd64 # DS1525+ 호환성 보장
container_name: app-dev
environment:
- DEBUG=true
- DATABASE_URL=postgresql://dev_user:dev_pass@postgres:5432/app_dev
- REDIS_URL=redis://redis:6379/0
volumes:
- ../src:/app/src:cached # Mac 성능 최적화
- ../config:/app/config:cached
ports:
- "8000:8000"
- "5678:5678" # 디버깅 포트
depends_on:
- postgres
- redis
networks:
- dev-network
postgres:
image: postgres:15-alpine
platform: linux/amd64
container_name: postgres-dev
environment:
POSTGRES_DB: app_dev
POSTGRES_USER: dev_user
POSTGRES_PASSWORD: dev_pass
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- dev-network
redis:
image: redis:7-alpine
platform: linux/amd64
container_name: redis-dev
volumes:
- redis_data:/data
ports:
- "6379:6379"
networks:
- dev-network
networks:
dev-network:
driver: bridge
volumes:
postgres_data:
redis_data:
```
### 개발 시작 스크립트
```bash
#!/bin/bash
# scripts/dev-start.sh
echo "🚀 개발 환경 시작"
# 개발 컨테이너 시작
docker-compose -f docker/docker-compose.dev.yml up -d
# 서비스 준비 대기
echo "⏳ 서비스 시작 대기..."
sleep 15
# 헬스체크
if curl -f http://localhost:8000/health > /dev/null 2>&1; then
echo "✅ 개발 환경 준비 완료!"
echo "🌐 애플리케이션: http://localhost:8000"
echo "🗄️ 데이터베이스: localhost:5432"
echo "🔴 Redis: localhost:6379"
else
echo "❌ 서비스 시작 실패"
docker-compose -f docker/docker-compose.dev.yml logs
fi
```
---
## 🏭 3단계: DS1525+ 배포 환경 설정
### DS1525+ 32GB 최적화 구성
```
총 메모리: 32GB 할당 계획
├── DSM 시스템: 2GB
├── PostgreSQL: 4GB (고성능 DB)
├── Elasticsearch: 8GB (대용량 검색)
├── Redis: 2GB (대용량 캐시)
├── 애플리케이션: 4GB (멀티 워커)
├── 모니터링: 2GB (Prometheus + Grafana)
├── 시스템 캐시: 8GB
└── 여유 공간: 2GB
```
### 배포용 Dockerfile (최적화)
```dockerfile
# docker/Dockerfile.prod
FROM --platform=$BUILDPLATFORM python:3.11-slim AS builder
ARG TARGETPLATFORM
ARG BUILDPLATFORM
WORKDIR /app
# 시스템 패키지 설치
RUN apt-get update && apt-get install -y \
gcc g++ curl \
&& rm -rf /var/lib/apt/lists/*
# Python 의존성 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 프로덕션 이미지
FROM python:3.11-slim AS production
WORKDIR /app
# 빌드된 패키지 복사
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# 애플리케이션 코드 복사
COPY src/ ./src/
COPY config/ ./config/
# 헬스체크 추가
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
EXPOSE 8000
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
```
### DS1525+ 배포용 Docker Compose
```yaml
# docker/docker-compose.prod.yml
version: '3.8'
services:
app:
build:
context: ..
dockerfile: docker/Dockerfile.prod
platforms:
- linux/amd64
container_name: app-prod
environment:
- DATABASE_URL=postgresql://app_user:${DB_PASSWORD}@postgres:5432/app_prod
- REDIS_URL=redis://redis:6379/0
- WORKERS=4
volumes:
- /volume1/docker/app/logs:/app/logs
ports:
- "8000:8000"
networks:
- prod-network
depends_on:
- postgres
- redis
restart: unless-stopped
deploy:
resources:
limits:
memory: 4G
cpus: '2.0'
postgres:
image: postgres:15-alpine
platform: linux/amd64
container_name: postgres-prod
environment:
POSTGRES_DB: app_prod
POSTGRES_USER: app_user
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- /volume1/docker/app/data/postgres:/var/lib/postgresql/data
- ../config/postgresql.conf:/etc/postgresql/postgresql.conf
ports:
- "5432:5432"
networks:
- prod-network
restart: unless-stopped
deploy:
resources:
limits:
memory: 4G
cpus: '2.0'
command: postgres -c config_file=/etc/postgresql/postgresql.conf
redis:
image: redis:7-alpine
platform: linux/amd64
container_name: redis-prod
command: redis-server --maxmemory 2gb --maxmemory-policy allkeys-lru
volumes:
- /volume1/docker/app/data/redis:/data
ports:
- "6379:6379"
networks:
- prod-network
restart: unless-stopped
deploy:
resources:
limits:
memory: 2G
cpus: '1.0'
elasticsearch:
image: elasticsearch:8.11.0
platform: linux/amd64
container_name: elasticsearch-prod
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms4g -Xmx8g"
- xpack.security.enabled=false
volumes:
- /volume1/docker/app/data/elasticsearch:/usr/share/elasticsearch/data
ports:
- "9200:9200"
networks:
- prod-network
restart: unless-stopped
deploy:
resources:
limits:
memory: 10G
cpus: '2.0'
nginx:
image: nginx:alpine
platform: linux/amd64
container_name: nginx-prod
volumes:
- ../config/nginx/nginx.conf:/etc/nginx/nginx.conf
- /volume1/docker/app/logs:/var/log/nginx
ports:
- "80:80"
- "443:443"
networks:
- prod-network
depends_on:
- app
restart: unless-stopped
# 모니터링
prometheus:
image: prom/prometheus:latest
platform: linux/amd64
container_name: prometheus
volumes:
- ../config/prometheus.yml:/etc/prometheus/prometheus.yml
- /volume1/docker/app/data/prometheus:/prometheus
ports:
- "9090:9090"
networks:
- prod-network
restart: unless-stopped
deploy:
resources:
limits:
memory: 1G
grafana:
image: grafana/grafana:latest
platform: linux/amd64
container_name: grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
volumes:
- /volume1/docker/app/data/grafana:/var/lib/grafana
ports:
- "3000:3000"
networks:
- prod-network
restart: unless-stopped
deploy:
resources:
limits:
memory: 1G
networks:
prod-network:
driver: bridge
volumes:
postgres_data:
redis_data:
elasticsearch_data:
```
---
## 🚀 4단계: 자동화 빌드 & 배포
### 통합 빌드-배포 스크립트
```bash
#!/bin/bash
# scripts/build-deploy.sh
set -e
# 설정
PROJECT_NAME="app"
NAS_HOST="192.168.1.100"
NAS_USER="admin"
VERSION=$(git describe --tags --always --dirty)
echo "🚀 빌드 & 배포 시작: $PROJECT_NAME v$VERSION"
# 1. 로컬 테스트
echo "🧪 로컬 테스트 실행..."
docker-compose -f docker/docker-compose.dev.yml up -d
sleep 30
if curl -f http://localhost:8000/health > /dev/null 2>&1; then
echo "✅ 로컬 테스트 통과"
docker-compose -f docker/docker-compose.dev.yml down
else
echo "❌ 로컬 테스트 실패"
docker-compose -f docker/docker-compose.dev.yml logs
exit 1
fi
# 2. 멀티 아키텍처 빌드 (DS1525+ 호환)
echo "🔨 DS1525+ 호환 이미지 빌드..."
docker buildx build \
--platform linux/amd64 \
--tag $PROJECT_NAME:$VERSION \
--tag $PROJECT_NAME:latest \
--file docker/Dockerfile.prod \
--load \
.
# 3. DS1525+로 이미지 전송
echo "📤 DS1525+로 이미지 전송..."
docker save $PROJECT_NAME:latest | ssh $NAS_USER@$NAS_HOST "docker load"
# 4. 환경변수 동기화
echo "⚙️ 환경변수 동기화..."
scp environments/.env.production $NAS_USER@$NAS_HOST:/volume1/docker/$PROJECT_NAME/.env
# 5. DS1525+에서 배포 실행
echo "🚢 DS1525+ 배포 실행..."
ssh $NAS_USER@$NAS_HOST << EOF
cd /volume1/docker/$PROJECT_NAME
# 기존 컨테이너 백업 (롤백용)
if docker-compose -f docker-compose.prod.yml ps | grep -q "Up"; then
echo "📦 롤백용 백업 생성..."
docker-compose -f docker-compose.prod.yml config > docker-compose.backup.yml
docker images --format "{{.Repository}}:{{.Tag}}" | grep $PROJECT_NAME | head -1 > last_image.txt
fi
# 새 버전 배포
docker-compose -f docker-compose.prod.yml down
docker-compose -f docker-compose.prod.yml up -d
# 이미지 정리
docker image prune -f
EOF
# 6. 배포 후 헬스체크
echo "🏥 배포 후 헬스체크..."
sleep 60
for i in {1..10}; do
if curl -f http://$NAS_HOST:8000/health > /dev/null 2>&1; then
echo "✅ 배포 성공 및 헬스체크 통과"
break
fi
if [ $i -eq 10 ]; then
echo "❌ 헬스체크 실패 - 롤백 필요"
exit 1
fi
echo "⏳ 헬스체크 재시도 ($i/10)..."
sleep 10
done
# 7. 배포 완료 정보
echo ""
echo "🎉 배포 완료!"
echo "📊 배포 정보:"
echo " - 프로젝트: $PROJECT_NAME"
echo " - 버전: $VERSION"
echo " - 대상: DS1525+ (32GB RAM, 480GB SSD)"
echo " - 배포 시간: $(date)"
echo ""
echo "🔗 접속 링크:"
echo " - 애플리케이션: http://$NAS_HOST"
echo " - 모니터링: http://$NAS_HOST:3000 (admin/admin123)"
echo " - Prometheus: http://$NAS_HOST:9090"
```
### 롤백 스크립트
```bash
#!/bin/bash
# scripts/rollback.sh
set -e
NAS_HOST="192.168.1.100"
NAS_USER="admin"
PROJECT_NAME="app"
echo "🔄 롤백 시작..."
ssh $NAS_USER@$NAS_HOST << EOF
cd /volume1/docker/$PROJECT_NAME
# 백업 파일 확인
if [[ ! -f "docker-compose.backup.yml" ]] || [[ ! -f "last_image.txt" ]]; then
echo "❌ 백업 파일을 찾을 수 없습니다"
exit 1
fi
# 현재 컨테이너 중지
docker-compose -f docker-compose.prod.yml down
# 이전 설정으로 복원
cp docker-compose.backup.yml docker-compose.prod.yml
# 컨테이너 시작
docker-compose -f docker-compose.prod.yml up -d
echo "✅ 롤백 완료"
EOF
# 헬스체크
sleep 30
if curl -f http://$NAS_HOST:8000/health > /dev/null 2>&1; then
echo "✅ 롤백 성공 및 헬스체크 통과"
else
echo "❌ 롤백 후 헬스체크 실패"
exit 1
fi
```
---
## 📊 5단계: DS1525+ 성능 최적화
### PostgreSQL 최적화 (32GB 활용)
```ini
# config/postgresql.conf
# DS1525+ 32GB RAM 최적화
# 메모리 설정
shared_buffers = 2GB # 32GB의 6.25%
effective_cache_size = 16GB # 32GB의 50%
maintenance_work_mem = 512MB
work_mem = 64MB
# AMD Ryzen 4코어 활용
max_worker_processes = 4
max_parallel_workers = 4
max_parallel_workers_per_gather = 2
# SSD 최적화
random_page_cost = 1.1
effective_io_concurrency = 200
# 연결 및 체크포인트
max_connections = 200
checkpoint_completion_target = 0.9
checkpoint_timeout = 15min
max_wal_size = 4GB
```
### Nginx 설정 (고성능)
```nginx
# config/nginx/nginx.conf
worker_processes 4; # AMD Ryzen 4코어
events {
worker_connections 2048;
use epoll;
multi_accept on;
}
http {
upstream app {
server app:8000;
keepalive 32;
}
server {
listen 80;
server_name _;
client_max_body_size 100M;
# 정적 파일 캐싱
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API 프록시
location / {
proxy_pass http://app;
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;
# 연결 유지
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}
```
---
## 🔧 6단계: 개발 워크플로우
### 일일 개발 루틴
```bash
# 개발 시작
./scripts/dev-start.sh
# 코드 변경 후 테스트
docker-compose -f docker/docker-compose.dev.yml logs -f app
# 개발 완료 후 배포
git add .
git commit -m "feat: 새로운 기능 추가"
git push origin main
# 배포 실행
./scripts/build-deploy.sh
# 개발 환경 정리
docker-compose -f docker/docker-compose.dev.yml down
```
### 브랜치별 배포 전략
```bash
# develop 브랜치 → 스테이징 자동 배포
git checkout develop
git merge feature/new-feature
git push origin develop
# main 브랜치 → 프로덕션 배포
git checkout main
git merge develop
git tag v1.2.0
git push origin main --tags
./scripts/build-deploy.sh
```
---
## 📈 7단계: 모니터링 및 유지보수
### 리소스 모니터링
```bash
# DS1525+ 리소스 확인
ssh admin@nas.local << 'EOF'
echo "💾 메모리 사용량:"
free -h
echo "🐳 Docker 컨테이너 상태:"
docker stats --no-stream
echo "💿 디스크 사용량:"
df -h /volume1
echo "🔥 CPU 사용률:"
top -bn1 | grep "Cpu(s)"
EOF
```
### 자동 백업 (480GB SSD 최적화)
```bash
#!/bin/bash
# scripts/backup.sh
BACKUP_DIR="/volume1/backup/app"
DATE=$(date +%Y%m%d_%H%M%S)
# 백업 디렉토리 생성
mkdir -p $BACKUP_DIR/{database,volumes,configs}
echo "💾 백업 시작: $DATE"
# 1. 데이터베이스 백업 (압축)
docker exec postgres-prod pg_dump -U app_user app_prod | gzip > $BACKUP_DIR/database/postgres_$DATE.sql.gz
# 2. 중요 볼륨만 백업 (용량 고려)
docker run --rm \
-v app_postgres_data:/source:ro \
-v $BACKUP_DIR/volumes:/backup \
alpine tar czf /backup/postgres_$DATE.tar.gz -C /source .
# 3. 설정 파일 백업
tar czf $BACKUP_DIR/configs/configs_$DATE.tar.gz \
/volume1/docker/app/docker-compose.prod.yml \
/volume1/docker/app/.env \
/volume1/docker/app/config/
# 4. 오래된 백업 정리 (SSD 수명 고려)
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
echo "✅ 백업 완료: $DATE"
```
---
## 🎯 성능 벤치마크 (DS1525+ 32GB)
### 예상 성능 지표
```
🚀 DS1525+ 32GB 성능 (최적화 후)
├── 동시 사용자: 200명
├── 응답 시간: 50-100ms
├── 처리량: 2,000 req/sec
├── 메모리 사용률: 70-80%
├── CPU 사용률: 30-50%
└── 디스크 I/O: SSD 최적화
```
### 리소스 할당 현황
```
총 32GB 메모리 활용:
├── PostgreSQL: 4GB (12.5%)
├── Elasticsearch: 8GB (25%)
├── Redis: 2GB (6.25%)
├── 애플리케이션: 4GB (12.5%)
├── 모니터링: 2GB (6.25%)
├── 시스템 캐시: 8GB (25%)
├── DSM: 2GB (6.25%)
└── 여유: 2GB (6.25%)
```
---
## 🚨 문제 해결 가이드
### 일반적인 문제들
#### 1. 아키텍처 호환성 오류
```bash
# 오류: exec format error
# 해결: 플랫폼 명시적 지정
docker run --platform linux/amd64 your-image
# 또는 Dockerfile에서
FROM --platform=linux/amd64 python:3.11-slim
```
#### 2. 메모리 부족 (32GB에서는 드물지만)
```bash
# 메모리 사용량 확인
docker stats
# Elasticsearch 메모리 줄이기 (필요시)
ES_JAVA_OPTS="-Xms2g -Xmx4g"
```
#### 3. 디스크 공간 부족 (480GB SSD)
```bash
# Docker 정리
docker system prune -a
# 로그 정리
find /volume1/docker/app/logs -name "*.log" -mtime +3 -delete
# 백업 정리
find /volume1/backup -mtime +30 -delete
```
---
## 📋 배포 체크리스트
### 배포 전 확인사항
```bash
✅ 체크리스트
- [ ] 로컬 테스트 통과
- [ ] 멀티 아키텍처 빌드 성공
- [ ] 환경변수 설정 완료
- [ ] 데이터베이스 마이그레이션 준비
- [ ] 헬스체크 엔드포인트 구현
- [ ] 백업 계획 수립
- [ ] 롤백 계획 준비
- [ ] 모니터링 설정 확인
```
### 배포 후 확인사항
```bash
✅ 배포 후 체크
- [ ] 애플리케이션 정상 동작
- [ ] 데이터베이스 연결 확인
- [ ] 캐시 동작 확인
- [ ] 검색 기능 확인
- [ ] 모니터링 대시보드 확인
- [ ] 로그 수집 확인
- [ ] 백업 자동화 확인
```
---
## 🎉 결론
### DS1525+ 32GB의 압도적 장점
-**충분한 성능**: 32GB RAM으로 모든 서비스 여유롭게 운영
-**24시간 안정성**: 전력 효율적, 저소음 운영
-**완전 자동화**: 개발부터 배포까지 스크립트 기반
-**확장 가능**: 향후 서비스 확장 시에도 여유로움
-**비용 효율**: 클라우드 대비 월등한 비용 절약
### 개발-배포 파이프라인 완성
```
Mac 개발 (Hot Reload)
멀티 아키텍처 빌드
DS1525+ 자동 배포
실시간 모니터링
자동 백업
```
**이제 개발에만 집중하고 배포는 스크립트가 알아서!** 🚀