🚀 배포용: PDF 뷰어 개선 및 서적별 UI 데본씽크 스타일 적용
✨ 주요 개선사항: - PDF API 500 에러 수정 (한글 파일명 UTF-8 인코딩 처리) - PDF 뷰어 기능 완전 구현 (PDF.js 통합, 네비게이션, 확대/축소) - 서적별 문서 그룹화 UI 데본씽크 스타일로 개선 - PDF Manager 페이지 서적별 보기 기능 추가 - Alpine.js 로드 순서 최적화로 JavaScript 에러 해결 🎨 UI/UX 개선: - 확장/축소 가능한 아코디언 스타일 서적 목록 - 간결하고 직관적인 데본씽크 스타일 인터페이스 - PDF 상태 표시 (HTML 연결, 서적 분류) - 반응형 디자인 및 부드러운 애니메이션 🔧 기술적 개선: - PDF.js 워커 설정 및 토큰 인증 처리 - 서적별 PDF 자동 그룹화 로직 - Alpine.js 컴포넌트 초기화 최적화
This commit is contained in:
399
scripts/deploy-synology.sh
Executable file
399
scripts/deploy-synology.sh
Executable file
@@ -0,0 +1,399 @@
|
||||
#!/bin/bash
|
||||
|
||||
# =============================================================================
|
||||
# Document Server - Synology DS1525+ 최적화 배포 스크립트
|
||||
#
|
||||
# 하드웨어 사양:
|
||||
# - CPU: AMD Ryzen R1600 (4코어/8스레드)
|
||||
# - RAM: 32GB DDR4 ECC
|
||||
# - SSD: 읽기/쓰기 캐시 활성화
|
||||
# - Storage: Volume1(SSD), Volume2(HDD)
|
||||
# =============================================================================
|
||||
|
||||
set -e # 에러 발생 시 스크립트 중단
|
||||
|
||||
# 색상 정의
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 로그 함수
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 환경 변수 설정
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
COMPOSE_FILE="docker-compose.synology.yml"
|
||||
|
||||
# 환경 변수 설정 확인
|
||||
ENV_FILE="$PROJECT_DIR/.env.synology"
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
log_info "환경 변수 파일이 없습니다. 설정을 시작합니다..."
|
||||
"$SCRIPT_DIR/setup-env.sh"
|
||||
fi
|
||||
|
||||
# 환경 변수 로드
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
log_info "환경 변수 파일을 로드합니다: $ENV_FILE"
|
||||
set -a # 자동으로 export
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
else
|
||||
log_error "환경 변수 파일을 찾을 수 없습니다"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "🚀 Synology DS1525+ 최적화 배포 시작"
|
||||
log_info "📁 프로젝트 디렉토리: $PROJECT_DIR"
|
||||
|
||||
# 1. 시스템 요구사항 확인
|
||||
log_info "🔍 시스템 요구사항 확인 중..."
|
||||
|
||||
# Docker 및 Docker Compose 확인
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker가 설치되지 않았습니다."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
log_error "Docker Compose가 설치되지 않았습니다."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 메모리 확인 (최소 16GB 권장)
|
||||
TOTAL_MEM=$(free -g | awk '/^Mem:/{print $2}')
|
||||
if [ "$TOTAL_MEM" -lt 16 ]; then
|
||||
log_warning "메모리가 ${TOTAL_MEM}GB입니다. 최소 16GB를 권장합니다."
|
||||
fi
|
||||
|
||||
log_success "시스템 요구사항 확인 완료"
|
||||
|
||||
# 2. 디렉토리 구조 생성
|
||||
log_info "📂 디렉토리 구조 생성 중..."
|
||||
|
||||
# SSD 디렉토리 (성능 최우선) - Volume3
|
||||
SSD_DIRS=(
|
||||
"/volume3/docker/document-server/database"
|
||||
"/volume3/docker/document-server/redis"
|
||||
"/volume3/docker/document-server/logs"
|
||||
"/volume3/docker/document-server/logs/nginx"
|
||||
"/volume3/docker/document-server/config"
|
||||
"/volume3/docker/document-server/nginx/conf.d"
|
||||
"/volume3/docker/document-server/nginx/cache"
|
||||
"/volume3/docker/document-server/cache"
|
||||
)
|
||||
|
||||
# HDD 디렉토리 (대용량 저장) - Volume1
|
||||
HDD_DIRS=(
|
||||
"/volume1/document-storage/uploads"
|
||||
"/volume1/document-storage/documents"
|
||||
"/volume1/document-storage/thumbnails"
|
||||
"/volume1/document-storage/backups"
|
||||
"/volume1/document-storage/archives"
|
||||
)
|
||||
|
||||
# SSD 디렉토리 생성
|
||||
for dir in "${SSD_DIRS[@]}"; do
|
||||
if [ ! -d "$dir" ]; then
|
||||
sudo mkdir -p "$dir"
|
||||
log_info "SSD 디렉토리 생성: $dir"
|
||||
fi
|
||||
done
|
||||
|
||||
# HDD 디렉토리 생성
|
||||
for dir in "${HDD_DIRS[@]}"; do
|
||||
if [ ! -d "$dir" ]; then
|
||||
sudo mkdir -p "$dir"
|
||||
log_info "HDD 디렉토리 생성: $dir"
|
||||
fi
|
||||
done
|
||||
|
||||
# 권한 설정
|
||||
sudo chown -R 1000:1000 /volume3/docker/document-server/
|
||||
sudo chown -R 1000:1000 /volume1/document-storage/
|
||||
|
||||
log_success "디렉토리 구조 생성 완료"
|
||||
|
||||
# 3. 설정 파일 복사
|
||||
log_info "⚙️ 설정 파일 생성 중..."
|
||||
|
||||
# PostgreSQL 설정 (32GB RAM 최적화)
|
||||
cat > /volume3/docker/document-server/config/postgresql.synology.conf << 'EOF'
|
||||
# PostgreSQL 설정 - Synology DS1525+ 32GB RAM 최적화
|
||||
|
||||
# 메모리 설정 (32GB RAM 기준)
|
||||
shared_buffers = 8GB # RAM의 25%
|
||||
effective_cache_size = 24GB # RAM의 75%
|
||||
work_mem = 512MB # 복잡한 쿼리용 (증가)
|
||||
maintenance_work_mem = 4GB # 인덱스 구축용 (증가)
|
||||
|
||||
# 체크포인트 설정 (SSD 최적화)
|
||||
checkpoint_completion_target = 0.9
|
||||
wal_buffers = 128MB # WAL 버퍼 (증가)
|
||||
checkpoint_timeout = 15min
|
||||
max_wal_size = 4GB
|
||||
min_wal_size = 1GB
|
||||
|
||||
# SSD 최적화
|
||||
random_page_cost = 1.1 # SSD 환경
|
||||
effective_io_concurrency = 200 # SSD 동시 I/O
|
||||
seq_page_cost = 1.0
|
||||
|
||||
# 병렬 처리 (4코어/8스레드 최적화)
|
||||
max_worker_processes = 8
|
||||
max_parallel_workers_per_gather = 4
|
||||
max_parallel_workers = 8
|
||||
max_parallel_maintenance_workers = 4
|
||||
|
||||
# 연결 설정
|
||||
max_connections = 200
|
||||
shared_preload_libraries = 'pg_stat_statements'
|
||||
|
||||
# 로깅 설정
|
||||
log_min_duration_statement = 1000 # 1초 이상 쿼리 로깅
|
||||
log_checkpoints = on
|
||||
log_connections = on
|
||||
log_disconnections = on
|
||||
log_lock_waits = on
|
||||
|
||||
# 자동 VACUUM 설정
|
||||
autovacuum = on
|
||||
autovacuum_max_workers = 4
|
||||
autovacuum_naptime = 30s
|
||||
EOF
|
||||
|
||||
# Nginx 설정 (SSD 캐시 최적화)
|
||||
cat > /volume3/docker/document-server/nginx/conf.d/default.conf << 'EOF'
|
||||
# Nginx 설정 - SSD 캐시 최적화
|
||||
|
||||
# 업스트림 백엔드
|
||||
upstream backend {
|
||||
server backend:8000;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
# 캐시 존 정의 (SSD에 저장)
|
||||
proxy_cache_path /var/cache/nginx/documents
|
||||
levels=1:2
|
||||
keys_zone=documents:100m
|
||||
max_size=2g
|
||||
inactive=60m
|
||||
use_temp_path=off;
|
||||
|
||||
proxy_cache_path /var/cache/nginx/api
|
||||
levels=1:2
|
||||
keys_zone=api:50m
|
||||
max_size=500m
|
||||
inactive=10m
|
||||
use_temp_path=off;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
# 클라이언트 설정
|
||||
client_max_body_size 500M;
|
||||
client_body_timeout 300s;
|
||||
client_header_timeout 300s;
|
||||
|
||||
# Gzip 압축
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/xml+rss
|
||||
application/json;
|
||||
|
||||
# 정적 파일 (SSD에서 서빙)
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# 정적 파일 캐시
|
||||
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
|
||||
# 업로드된 문서 (HDD에서 서빙, SSD 캐시)
|
||||
location /uploads/ {
|
||||
alias /usr/share/nginx/html/uploads/;
|
||||
|
||||
# 문서 캐시 (자주 접근하는 문서는 SSD에 캐시)
|
||||
proxy_cache documents;
|
||||
proxy_cache_valid 200 60m;
|
||||
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
expires 1h;
|
||||
}
|
||||
|
||||
# API 요청
|
||||
location /api/ {
|
||||
proxy_pass http://backend;
|
||||
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;
|
||||
|
||||
# API 응답 캐시 (GET 요청만)
|
||||
proxy_cache api;
|
||||
proxy_cache_methods GET HEAD;
|
||||
proxy_cache_valid 200 5m;
|
||||
proxy_cache_bypass $http_pragma $http_authorization;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
# 타임아웃 설정
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# 헬스체크
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
log_success "설정 파일 생성 완료"
|
||||
|
||||
# 4. 환경 변수 파일 생성
|
||||
log_info "🔐 환경 변수 설정 중..."
|
||||
|
||||
cat > "$PROJECT_DIR/.env.synology" << EOF
|
||||
# Synology DS1525+ 배포 환경 변수
|
||||
DB_PASSWORD=$DB_PASSWORD
|
||||
SECRET_KEY=$SECRET_KEY
|
||||
ADMIN_EMAIL=$ADMIN_EMAIL
|
||||
ADMIN_PASSWORD=$ADMIN_PASSWORD
|
||||
DOMAIN_NAME=$DOMAIN_NAME
|
||||
|
||||
# 성능 최적화 설정
|
||||
POSTGRES_SHARED_BUFFERS=8GB
|
||||
POSTGRES_EFFECTIVE_CACHE_SIZE=24GB
|
||||
REDIS_MAXMEMORY=8gb
|
||||
|
||||
# 경로 설정
|
||||
SSD_PATH=/volume1/docker/document-server
|
||||
HDD_PATH=/volume2/document-storage
|
||||
EOF
|
||||
|
||||
log_success "환경 변수 설정 완료"
|
||||
|
||||
# 5. Docker Compose 배포
|
||||
log_info "🐳 Docker 컨테이너 배포 중..."
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# 기존 컨테이너 중지 및 제거 (있는 경우)
|
||||
if docker-compose -f "$COMPOSE_FILE" ps -q | grep -q .; then
|
||||
log_warning "기존 컨테이너를 중지합니다..."
|
||||
docker-compose -f "$COMPOSE_FILE" down
|
||||
fi
|
||||
|
||||
# 이미지 빌드 및 컨테이너 시작
|
||||
log_info "이미지 빌드 중..."
|
||||
docker-compose -f "$COMPOSE_FILE" build --no-cache
|
||||
|
||||
log_info "컨테이너 시작 중..."
|
||||
docker-compose -f "$COMPOSE_FILE" up -d
|
||||
|
||||
# 6. 서비스 상태 확인
|
||||
log_info "🔍 서비스 상태 확인 중..."
|
||||
|
||||
# 컨테이너 시작 대기
|
||||
sleep 30
|
||||
|
||||
# 헬스체크
|
||||
services=("database" "redis" "backend" "nginx")
|
||||
for service in "${services[@]}"; do
|
||||
if docker-compose -f "$COMPOSE_FILE" ps "$service" | grep -q "Up"; then
|
||||
log_success "$service 서비스 정상 실행 중"
|
||||
else
|
||||
log_error "$service 서비스 실행 실패"
|
||||
docker-compose -f "$COMPOSE_FILE" logs "$service"
|
||||
fi
|
||||
done
|
||||
|
||||
# 7. 백업 스크립트 설정
|
||||
log_info "💾 백업 스크립트 설정 중..."
|
||||
|
||||
cat > /volume1/docker/document-server/backup.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
# 자동 백업 스크립트
|
||||
|
||||
BACKUP_DIR="/volume2/document-storage/backups"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# 데이터베이스 백업
|
||||
docker exec document-server-db pg_dump -U docuser document_db > "$BACKUP_DIR/db_backup_$DATE.sql"
|
||||
|
||||
# 설정 파일 백업
|
||||
tar -czf "$BACKUP_DIR/config_backup_$DATE.tar.gz" /volume1/docker/document-server/config/
|
||||
|
||||
# 7일 이상 된 백업 파일 삭제
|
||||
find "$BACKUP_DIR" -name "*.sql" -mtime +7 -delete
|
||||
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete
|
||||
|
||||
echo "백업 완료: $DATE"
|
||||
EOF
|
||||
|
||||
chmod +x /volume1/docker/document-server/backup.sh
|
||||
|
||||
log_success "백업 스크립트 설정 완료"
|
||||
|
||||
# 8. 배포 완료 정보 출력
|
||||
log_success "🎉 Synology DS1525+ 배포 완료!"
|
||||
|
||||
echo ""
|
||||
echo "=== 배포 정보 ==="
|
||||
echo "🌐 웹 인터페이스: http://localhost:24100"
|
||||
echo "🔧 API 서버: http://localhost:24102"
|
||||
echo "🗄️ 데이터베이스: localhost:24101"
|
||||
echo "💾 Redis: localhost:24103"
|
||||
echo ""
|
||||
echo "=== 관리자 계정 ==="
|
||||
echo "📧 이메일: $ADMIN_EMAIL"
|
||||
echo "🔑 비밀번호: $ADMIN_PASSWORD"
|
||||
echo ""
|
||||
echo "=== 스토리지 구성 ==="
|
||||
echo "💿 SSD (성능): /volume1/docker/document-server/"
|
||||
echo "💾 HDD (용량): /volume2/document-storage/"
|
||||
echo ""
|
||||
echo "=== 자동 백업 ==="
|
||||
echo "📅 매일 새벽 2시 자동 백업 (Synology 작업 스케줄러에서 설정)"
|
||||
echo "📂 백업 위치: /volume2/document-storage/backups/"
|
||||
echo ""
|
||||
echo "=== 모니터링 명령어 ==="
|
||||
echo "docker-compose -f $COMPOSE_FILE ps"
|
||||
echo "docker-compose -f $COMPOSE_FILE logs -f"
|
||||
echo "docker stats"
|
||||
|
||||
log_info "배포 스크립트 실행 완료"
|
||||
Reference in New Issue
Block a user