🧹 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
This commit is contained in:
864
DEVELOPMENT_DEPLOYMENT_GUIDE.md
Normal file
864
DEVELOPMENT_DEPLOYMENT_GUIDE.md
Normal file
@@ -0,0 +1,864 @@
|
|||||||
|
# 🚀 개발-배포 통합 가이드 (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+ 자동 배포
|
||||||
|
↓
|
||||||
|
실시간 모니터링
|
||||||
|
↓
|
||||||
|
자동 백업
|
||||||
|
```
|
||||||
|
|
||||||
|
**이제 개발에만 집중하고 배포는 스크립트가 알아서!** 🚀
|
||||||
@@ -1,607 +0,0 @@
|
|||||||
# 🏠 DS1525+ 최적화 설치 가이드
|
|
||||||
|
|
||||||
## 📋 하드웨어 사양
|
|
||||||
|
|
||||||
### 대상 기기: Synology DS1525+
|
|
||||||
- **CPU**: AMD Ryzen R1600 (4코어 2.6GHz)
|
|
||||||
- **메모리**: 32GB RAM (대폭 업그레이드됨!)
|
|
||||||
- **저장장치**: 시놀로지 정품 2.5" SSD 480GB
|
|
||||||
- **네트워크**: 기가비트 이더넷 x4
|
|
||||||
- **DSM**: 7.0 이상
|
|
||||||
|
|
||||||
### 성능 특징
|
|
||||||
- **고성능 CPU**: AMD Ryzen으로 NLP 처리 우수
|
|
||||||
- **대용량 메모리**: 32GB로 모든 서비스 여유롭게 운영
|
|
||||||
- **SSD 스토리지**: 빠른 I/O, 낮은 지연시간
|
|
||||||
- **멀티 기가비트**: 네트워크 병목 없음
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 DS1525+ 32GB 최적화 구성
|
|
||||||
|
|
||||||
### 메모리 할당 계획 (32GB 활용)
|
|
||||||
```
|
|
||||||
총 메모리: 32GB
|
|
||||||
├── DSM 시스템: 2GB
|
|
||||||
├── PostgreSQL: 4GB (대폭 증량)
|
|
||||||
├── Elasticsearch: 8GB (고성능 검색)
|
|
||||||
├── Redis: 2GB (대용량 캐시)
|
|
||||||
├── 애플리케이션: 4GB (멀티 워커)
|
|
||||||
├── NLP 처리: 4GB (동시 처리)
|
|
||||||
├── 시스템 캐시: 6GB (파일 시스템 캐시)
|
|
||||||
└── 여유 공간: 2GB
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker Compose 최적화 (DS1525+ 전용)
|
|
||||||
```yaml
|
|
||||||
# /volume1/docker/industrial-info/docker-compose.yml
|
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
industrial-net:
|
|
||||||
driver: bridge
|
|
||||||
ipam:
|
|
||||||
config:
|
|
||||||
- subnet: 172.20.0.0/16
|
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: industrial-postgres
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: industrial_info
|
|
||||||
POSTGRES_USER: industrial_user
|
|
||||||
POSTGRES_PASSWORD: secure_password_here
|
|
||||||
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/postgres:/var/lib/postgresql/data
|
|
||||||
- /volume1/docker/industrial-info/config/postgresql.conf:/etc/postgresql/postgresql.conf
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G # 32GB 활용
|
|
||||||
cpus: '2.0' # Ryzen 4코어 활용
|
|
||||||
reservations:
|
|
||||||
memory: 2G
|
|
||||||
cpus: '1.0'
|
|
||||||
command: postgres -c config_file=/etc/postgresql/postgresql.conf
|
|
||||||
|
|
||||||
elasticsearch:
|
|
||||||
image: elasticsearch:8.11.0
|
|
||||||
container_name: industrial-elasticsearch
|
|
||||||
environment:
|
|
||||||
- discovery.type=single-node
|
|
||||||
- "ES_JAVA_OPTS=-Xms4g -Xmx8g" # 대폭 증량!
|
|
||||||
- xpack.security.enabled=false
|
|
||||||
- xpack.security.enrollment.enabled=false
|
|
||||||
- bootstrap.memory_lock=true
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/elasticsearch:/usr/share/elasticsearch/data
|
|
||||||
- /volume1/docker/industrial-info/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
- "9300:9300"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 10G # 8GB JVM + 2GB 시스템
|
|
||||||
cpus: '2.0'
|
|
||||||
reservations:
|
|
||||||
memory: 6G
|
|
||||||
cpus: '1.0'
|
|
||||||
ulimits:
|
|
||||||
memlock:
|
|
||||||
soft: -1
|
|
||||||
hard: -1
|
|
||||||
nofile:
|
|
||||||
soft: 65536
|
|
||||||
hard: 65536
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
container_name: industrial-redis
|
|
||||||
command: redis-server /etc/redis/redis.conf
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/redis:/data
|
|
||||||
- /volume1/docker/industrial-info/config/redis.conf:/etc/redis/redis.conf
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 2G # 대용량 캐시
|
|
||||||
cpus: '1.0'
|
|
||||||
reservations:
|
|
||||||
memory: 1G
|
|
||||||
cpus: '0.5'
|
|
||||||
|
|
||||||
app:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-app
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
- PYTHONPATH=/app
|
|
||||||
- WORKERS=4 # 멀티 워커
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G # 멀티 워커 지원
|
|
||||||
cpus: '2.0'
|
|
||||||
reservations:
|
|
||||||
memory: 2G
|
|
||||||
cpus: '1.0'
|
|
||||||
|
|
||||||
# NLP 전용 워커 (고성능)
|
|
||||||
nlp-worker:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-nlp-worker
|
|
||||||
command: celery -A main.celery worker --loglevel=info --concurrency=4 -Q nlp
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
- SPACY_MODEL_PATH=/app/models
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
- /volume1/docker/industrial-info/data/models:/app/models
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G # NLP 모델 로딩용
|
|
||||||
cpus: '2.0'
|
|
||||||
reservations:
|
|
||||||
memory: 2G
|
|
||||||
cpus: '1.0'
|
|
||||||
|
|
||||||
# 데이터 수집 워커
|
|
||||||
collector-worker:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-collector
|
|
||||||
command: celery -A main.celery worker --loglevel=info --concurrency=2 -Q collector
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 2G
|
|
||||||
cpus: '1.0'
|
|
||||||
reservations:
|
|
||||||
memory: 1G
|
|
||||||
cpus: '0.5'
|
|
||||||
|
|
||||||
# 스케줄러
|
|
||||||
scheduler:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-scheduler
|
|
||||||
command: celery -A main.celery beat --loglevel=info
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512M
|
|
||||||
cpus: '0.5'
|
|
||||||
|
|
||||||
# 모니터링 (Prometheus)
|
|
||||||
prometheus:
|
|
||||||
image: prom/prometheus:latest
|
|
||||||
container_name: industrial-prometheus
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/config/prometheus.yml:/etc/prometheus/prometheus.yml
|
|
||||||
- /volume1/docker/industrial-info/data/prometheus:/prometheus
|
|
||||||
ports:
|
|
||||||
- "9090:9090"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
cpus: '0.5'
|
|
||||||
|
|
||||||
# 모니터링 대시보드 (Grafana)
|
|
||||||
grafana:
|
|
||||||
image: grafana/grafana:latest
|
|
||||||
container_name: industrial-grafana
|
|
||||||
environment:
|
|
||||||
- GF_SECURITY_ADMIN_PASSWORD=admin123
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/grafana:/var/lib/grafana
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
cpus: '0.5'
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: industrial-nginx
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/config/nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/var/log/nginx
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- app
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512M
|
|
||||||
cpus: '0.5'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚙️ 고성능 설정 파일들
|
|
||||||
|
|
||||||
### PostgreSQL 최적화 (32GB 활용)
|
|
||||||
```ini
|
|
||||||
# /volume1/docker/industrial-info/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 # 정렬/해시 작업용
|
|
||||||
|
|
||||||
# 체크포인트 설정
|
|
||||||
checkpoint_completion_target = 0.9
|
|
||||||
checkpoint_timeout = 15min
|
|
||||||
max_wal_size = 4GB
|
|
||||||
min_wal_size = 1GB
|
|
||||||
|
|
||||||
# 연결 설정
|
|
||||||
max_connections = 200
|
|
||||||
shared_preload_libraries = 'pg_stat_statements'
|
|
||||||
|
|
||||||
# 로그 설정
|
|
||||||
log_destination = 'stderr'
|
|
||||||
logging_collector = on
|
|
||||||
log_directory = '/var/lib/postgresql/data/log'
|
|
||||||
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
|
|
||||||
log_rotation_age = 1d
|
|
||||||
log_rotation_size = 100MB
|
|
||||||
log_min_duration_statement = 1000 # 1초 이상 쿼리 로깅
|
|
||||||
|
|
||||||
# 성능 최적화
|
|
||||||
random_page_cost = 1.1 # SSD 최적화
|
|
||||||
effective_io_concurrency = 200 # SSD 동시 I/O
|
|
||||||
max_worker_processes = 4 # Ryzen 4코어 활용
|
|
||||||
max_parallel_workers = 4
|
|
||||||
max_parallel_workers_per_gather = 2
|
|
||||||
|
|
||||||
# 자동 VACUUM 최적화
|
|
||||||
autovacuum = on
|
|
||||||
autovacuum_max_workers = 2
|
|
||||||
autovacuum_naptime = 30s
|
|
||||||
```
|
|
||||||
|
|
||||||
### Elasticsearch 최적화 (8GB JVM)
|
|
||||||
```yaml
|
|
||||||
# /volume1/docker/industrial-info/config/elasticsearch.yml
|
|
||||||
cluster.name: "industrial-cluster"
|
|
||||||
node.name: "industrial-node-1"
|
|
||||||
path.data: /usr/share/elasticsearch/data
|
|
||||||
path.logs: /usr/share/elasticsearch/logs
|
|
||||||
|
|
||||||
# 네트워크 설정
|
|
||||||
network.host: 0.0.0.0
|
|
||||||
http.port: 9200
|
|
||||||
transport.port: 9300
|
|
||||||
|
|
||||||
# 메모리 설정 (32GB 환경)
|
|
||||||
bootstrap.memory_lock: true
|
|
||||||
indices.memory.index_buffer_size: 2GB
|
|
||||||
indices.fielddata.cache.size: 2GB
|
|
||||||
|
|
||||||
# 성능 최적화
|
|
||||||
thread_pool.write.queue_size: 1000
|
|
||||||
thread_pool.search.queue_size: 1000
|
|
||||||
indices.queries.cache.size: 1GB
|
|
||||||
|
|
||||||
# SSD 최적화
|
|
||||||
index.store.type: niofs
|
|
||||||
index.merge.scheduler.max_thread_count: 2
|
|
||||||
|
|
||||||
# 한국어 분석 설정
|
|
||||||
index.analysis.analyzer.nori.type: custom
|
|
||||||
index.analysis.analyzer.nori.tokenizer: nori_tokenizer
|
|
||||||
index.analysis.analyzer.nori.filter: [nori_part_of_speech, lowercase]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Redis 최적화 (2GB)
|
|
||||||
```ini
|
|
||||||
# /volume1/docker/industrial-info/config/redis.conf
|
|
||||||
# DS1525+ 32GB RAM 최적화
|
|
||||||
|
|
||||||
# 메모리 설정
|
|
||||||
maxmemory 2gb
|
|
||||||
maxmemory-policy allkeys-lru
|
|
||||||
|
|
||||||
# 영속성 설정 (SSD 최적화)
|
|
||||||
save 900 1
|
|
||||||
save 300 10
|
|
||||||
save 60 10000
|
|
||||||
|
|
||||||
# AOF 설정
|
|
||||||
appendonly yes
|
|
||||||
appendfsync everysec
|
|
||||||
auto-aof-rewrite-percentage 100
|
|
||||||
auto-aof-rewrite-min-size 64mb
|
|
||||||
|
|
||||||
# 네트워크 최적화
|
|
||||||
tcp-keepalive 300
|
|
||||||
timeout 0
|
|
||||||
|
|
||||||
# 성능 최적화
|
|
||||||
hash-max-ziplist-entries 512
|
|
||||||
hash-max-ziplist-value 64
|
|
||||||
list-max-ziplist-size -2
|
|
||||||
set-max-intset-entries 512
|
|
||||||
zset-max-ziplist-entries 128
|
|
||||||
zset-max-ziplist-value 64
|
|
||||||
|
|
||||||
# 로그 설정
|
|
||||||
loglevel notice
|
|
||||||
logfile ""
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 성능 벤치마크 (DS1525+ 32GB)
|
|
||||||
|
|
||||||
### 예상 성능 지표
|
|
||||||
```
|
|
||||||
동시 사용자: 100명 (여유롭게)
|
|
||||||
검색 응답시간: 50-100ms (매우 빠름)
|
|
||||||
RSS 수집: 500개 피드/분 (대용량 처리)
|
|
||||||
NLP 처리: 10,000건/시간 (고속 처리)
|
|
||||||
데이터베이스: 1,000 TPS (높은 처리량)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 리소스 사용률 목표
|
|
||||||
```
|
|
||||||
CPU 사용률: 평균 30-40% (여유)
|
|
||||||
메모리 사용률: 평균 70-80% (효율적)
|
|
||||||
디스크 I/O: SSD 성능 최대 활용
|
|
||||||
네트워크: 기가비트 대역폭 활용
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💾 SSD 480GB 최적화
|
|
||||||
|
|
||||||
### 디스크 공간 할당
|
|
||||||
```
|
|
||||||
총 용량: 480GB
|
|
||||||
├── DSM 시스템: 50GB
|
|
||||||
├── Docker 이미지: 20GB
|
|
||||||
├── PostgreSQL 데이터: 100GB
|
|
||||||
├── Elasticsearch 인덱스: 150GB
|
|
||||||
├── 애플리케이션 로그: 30GB
|
|
||||||
├── 백업 공간: 80GB
|
|
||||||
└── 여유 공간: 50GB (10% 여유)
|
|
||||||
```
|
|
||||||
|
|
||||||
### SSD 수명 연장 설정
|
|
||||||
```bash
|
|
||||||
# SSD 최적화 스크립트
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# TRIM 활성화
|
|
||||||
echo 'deadline' > /sys/block/sda/queue/scheduler
|
|
||||||
|
|
||||||
# 로그 로테이션 최적화
|
|
||||||
cat > /etc/logrotate.d/docker << EOF
|
|
||||||
/volume1/docker/industrial-info/data/logs/*.log {
|
|
||||||
daily
|
|
||||||
rotate 7
|
|
||||||
compress
|
|
||||||
delaycompress
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
create 644 root root
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 스왑 사용 최소화
|
|
||||||
echo 'vm.swappiness=1' >> /etc/sysctl.conf
|
|
||||||
echo 'vm.vfs_cache_pressure=50' >> /etc/sysctl.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
### 자동 정리 스크립트
|
|
||||||
```bash
|
|
||||||
# /volume1/docker/industrial-info/scripts/cleanup.sh
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Docker 이미지 정리 (주간)
|
|
||||||
docker system prune -f
|
|
||||||
|
|
||||||
# 로그 파일 압축 (일일)
|
|
||||||
find /volume1/docker/industrial-info/data/logs -name "*.log" -mtime +1 -exec gzip {} \;
|
|
||||||
|
|
||||||
# 오래된 백업 삭제 (월간)
|
|
||||||
find /volume1/docker/industrial-info/backup -name "*.gz" -mtime +30 -delete
|
|
||||||
|
|
||||||
# Elasticsearch 인덱스 최적화 (주간)
|
|
||||||
curl -X POST "localhost:9200/_forcemerge?max_num_segments=1"
|
|
||||||
|
|
||||||
echo "Cleanup completed: $(date)"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 모니터링 및 알림
|
|
||||||
|
|
||||||
### Prometheus 설정
|
|
||||||
```yaml
|
|
||||||
# /volume1/docker/industrial-info/config/prometheus.yml
|
|
||||||
global:
|
|
||||||
scrape_interval: 15s
|
|
||||||
|
|
||||||
scrape_configs:
|
|
||||||
- job_name: 'industrial-app'
|
|
||||||
static_configs:
|
|
||||||
- targets: ['app:8000']
|
|
||||||
|
|
||||||
- job_name: 'postgres'
|
|
||||||
static_configs:
|
|
||||||
- targets: ['postgres:5432']
|
|
||||||
|
|
||||||
- job_name: 'elasticsearch'
|
|
||||||
static_configs:
|
|
||||||
- targets: ['elasticsearch:9200']
|
|
||||||
|
|
||||||
- job_name: 'redis'
|
|
||||||
static_configs:
|
|
||||||
- targets: ['redis:6379']
|
|
||||||
|
|
||||||
- job_name: 'node-exporter'
|
|
||||||
static_configs:
|
|
||||||
- targets: ['localhost:9100']
|
|
||||||
```
|
|
||||||
|
|
||||||
### 알림 규칙
|
|
||||||
```yaml
|
|
||||||
# 메모리 사용률 80% 초과 시 알림
|
|
||||||
- alert: HighMemoryUsage
|
|
||||||
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 80
|
|
||||||
for: 5m
|
|
||||||
labels:
|
|
||||||
severity: warning
|
|
||||||
annotations:
|
|
||||||
summary: "High memory usage detected"
|
|
||||||
|
|
||||||
# 디스크 사용률 85% 초과 시 알림
|
|
||||||
- alert: HighDiskUsage
|
|
||||||
expr: (1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100 > 85
|
|
||||||
for: 5m
|
|
||||||
labels:
|
|
||||||
severity: critical
|
|
||||||
annotations:
|
|
||||||
summary: "High disk usage detected"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 배포 및 실행
|
|
||||||
|
|
||||||
### 원클릭 설치 스크립트
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# /volume1/docker/industrial-info/install.sh
|
|
||||||
|
|
||||||
echo "🚀 DS1525+ 산업정보시스템 설치 시작..."
|
|
||||||
|
|
||||||
# 디렉토리 생성
|
|
||||||
mkdir -p /volume1/docker/industrial-info/{app,data/{postgres,elasticsearch,redis,logs,grafana,prometheus},config,backup,scripts}
|
|
||||||
|
|
||||||
# 권한 설정
|
|
||||||
chown -R 1000:1000 /volume1/docker/industrial-info
|
|
||||||
|
|
||||||
# Docker 네트워크 생성
|
|
||||||
docker network create industrial-net 2>/dev/null || true
|
|
||||||
|
|
||||||
# 환경 변수 파일 생성
|
|
||||||
cat > /volume1/docker/industrial-info/.env << EOF
|
|
||||||
POSTGRES_PASSWORD=$(openssl rand -base64 32)
|
|
||||||
SECRET_KEY=$(openssl rand -base64 64)
|
|
||||||
ELASTICSEARCH_PASSWORD=$(openssl rand -base64 32)
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 컨테이너 시작
|
|
||||||
cd /volume1/docker/industrial-info
|
|
||||||
docker-compose up --build -d
|
|
||||||
|
|
||||||
echo "✅ 설치 완료! 접속 URL:"
|
|
||||||
echo " 애플리케이션: http://$(hostname -I | awk '{print $1}'):80"
|
|
||||||
echo " 모니터링: http://$(hostname -I | awk '{print $1}'):3000"
|
|
||||||
echo " Elasticsearch: http://$(hostname -I | awk '{print $1}'):9200"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📈 성능 비교 요약
|
|
||||||
|
|
||||||
### DS1525+ vs 일반 NAS vs Mac
|
|
||||||
| 항목 | DS1525+ 32GB | 일반 NAS 8GB | Mac Mini M2 |
|
|
||||||
|------|--------------|--------------|-------------|
|
|
||||||
| 동시 사용자 | 100명 | 20명 | 50명 |
|
|
||||||
| 검색 속도 | 50ms | 200ms | 30ms |
|
|
||||||
| NLP 처리 | 10K건/시간 | 1K건/시간 | 15K건/시간 |
|
|
||||||
| 전력 소모 | 60W | 40W | 150W |
|
|
||||||
| 24시간 운영 | ✅ 최적 | ✅ 가능 | ❌ 비효율 |
|
|
||||||
| 확장성 | ✅ 우수 | ⚠️ 제한적 | ❌ 제한적 |
|
|
||||||
| 비용 효율 | ✅ 최고 | ✅ 좋음 | ❌ 높음 |
|
|
||||||
|
|
||||||
**결론**: DS1525+ 32GB는 이 프로젝트에 **과분할 정도로 좋은 성능**을 제공합니다! 🚀
|
|
||||||
|
|
||||||
480GB SSD도 충분하고, 32GB RAM으로 모든 서비스를 여유롭게 돌릴 수 있어요. 완벽한 선택입니다! 👍
|
|
||||||
@@ -1,592 +0,0 @@
|
|||||||
# 🍺 Homebrew 기반 개발환경 설정 가이드
|
|
||||||
|
|
||||||
## 📋 개요
|
|
||||||
|
|
||||||
macOS에서 Homebrew를 사용하여 산업 전문 정보 수집 시스템의 개발환경을 설정하는 단계별 가이드입니다.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 사전 요구사항
|
|
||||||
|
|
||||||
### 시스템 요구사항
|
|
||||||
- **macOS**: 12.0+ (Monterey 이상 권장)
|
|
||||||
- **메모리**: 8GB 이상 (16GB 권장)
|
|
||||||
- **저장공간**: 20GB 이상 여유 공간
|
|
||||||
- **네트워크**: 인터넷 연결 (패키지 다운로드용)
|
|
||||||
|
|
||||||
### 개발자 도구
|
|
||||||
```bash
|
|
||||||
# Xcode Command Line Tools 설치 (Homebrew 설치 전 필수)
|
|
||||||
xcode-select --install
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🍺 1단계: Homebrew 설치
|
|
||||||
|
|
||||||
### Homebrew 설치
|
|
||||||
```bash
|
|
||||||
# Homebrew 설치 스크립트 실행
|
|
||||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
||||||
|
|
||||||
# 설치 확인
|
|
||||||
brew --version
|
|
||||||
|
|
||||||
# PATH 설정 (M1/M2 Mac의 경우)
|
|
||||||
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc
|
|
||||||
source ~/.zshrc
|
|
||||||
```
|
|
||||||
|
|
||||||
### Homebrew 업데이트
|
|
||||||
```bash
|
|
||||||
# Homebrew 자체 업데이트
|
|
||||||
brew update
|
|
||||||
|
|
||||||
# 설치된 패키지 업그레이드
|
|
||||||
brew upgrade
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐍 2단계: Python 환경 설정
|
|
||||||
|
|
||||||
### Python 설치
|
|
||||||
```bash
|
|
||||||
# Python 3.11 설치 (최신 안정 버전)
|
|
||||||
brew install python@3.11
|
|
||||||
|
|
||||||
# 설치 확인
|
|
||||||
python3 --version
|
|
||||||
pip3 --version
|
|
||||||
|
|
||||||
# 심볼릭 링크 설정 (선택사항)
|
|
||||||
brew link python@3.11
|
|
||||||
```
|
|
||||||
|
|
||||||
### 가상환경 도구 설치
|
|
||||||
```bash
|
|
||||||
# virtualenv 설치
|
|
||||||
pip3 install virtualenv
|
|
||||||
|
|
||||||
# 또는 pyenv 사용 (Python 버전 관리)
|
|
||||||
brew install pyenv
|
|
||||||
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
|
|
||||||
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
|
|
||||||
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
|
|
||||||
source ~/.zshrc
|
|
||||||
```
|
|
||||||
|
|
||||||
### 프로젝트 가상환경 생성
|
|
||||||
```bash
|
|
||||||
# 프로젝트 디렉토리로 이동
|
|
||||||
cd /Users/hyungi/news-project
|
|
||||||
|
|
||||||
# 가상환경 생성
|
|
||||||
python3 -m venv venv
|
|
||||||
|
|
||||||
# 가상환경 활성화
|
|
||||||
source venv/bin/activate
|
|
||||||
|
|
||||||
# 가상환경 활성화 확인 (프롬프트에 (venv) 표시됨)
|
|
||||||
which python
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🟢 3단계: Node.js 환경 설정
|
|
||||||
|
|
||||||
### Node.js 설치
|
|
||||||
```bash
|
|
||||||
# Node.js 18 LTS 설치
|
|
||||||
brew install node@18
|
|
||||||
|
|
||||||
# 설치 확인
|
|
||||||
node --version
|
|
||||||
npm --version
|
|
||||||
|
|
||||||
# 글로벌 패키지 업데이트
|
|
||||||
npm install -g npm@latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### 선택적: Node 버전 관리자 설치
|
|
||||||
```bash
|
|
||||||
# nvm 설치 (Node Version Manager)
|
|
||||||
brew install nvm
|
|
||||||
|
|
||||||
# nvm 설정
|
|
||||||
mkdir ~/.nvm
|
|
||||||
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc
|
|
||||||
echo '[ -s "/opt/homebrew/share/nvm/nvm.sh" ] && \. "/opt/homebrew/share/nvm/nvm.sh"' >> ~/.zshrc
|
|
||||||
echo '[ -s "/opt/homebrew/share/nvm/bash_completion" ] && \. "/opt/homebrew/share/nvm/bash_completion"' >> ~/.zshrc
|
|
||||||
source ~/.zshrc
|
|
||||||
|
|
||||||
# Node.js 18 설치 및 사용
|
|
||||||
nvm install 18
|
|
||||||
nvm use 18
|
|
||||||
nvm alias default 18
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🗄️ 4단계: 데이터베이스 설치
|
|
||||||
|
|
||||||
### PostgreSQL 설치
|
|
||||||
```bash
|
|
||||||
# PostgreSQL 설치
|
|
||||||
brew install postgresql@15
|
|
||||||
|
|
||||||
# 서비스 시작
|
|
||||||
brew services start postgresql@15
|
|
||||||
|
|
||||||
# 데이터베이스 생성
|
|
||||||
createdb industrial_info
|
|
||||||
|
|
||||||
# 연결 테스트
|
|
||||||
psql industrial_info
|
|
||||||
# \q 로 종료
|
|
||||||
```
|
|
||||||
|
|
||||||
### PostgreSQL 설정
|
|
||||||
```bash
|
|
||||||
# 사용자 생성 (선택사항)
|
|
||||||
createuser --interactive --pwprompt industrial_user
|
|
||||||
|
|
||||||
# 데이터베이스 권한 부여
|
|
||||||
psql -c "GRANT ALL PRIVILEGES ON DATABASE industrial_info TO industrial_user;"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Redis 설치
|
|
||||||
```bash
|
|
||||||
# Redis 설치
|
|
||||||
brew install redis
|
|
||||||
|
|
||||||
# 서비스 시작
|
|
||||||
brew services start redis
|
|
||||||
|
|
||||||
# 연결 테스트
|
|
||||||
redis-cli ping
|
|
||||||
# PONG 응답 확인
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 5단계: Elasticsearch 설치
|
|
||||||
|
|
||||||
### Elasticsearch 설치
|
|
||||||
```bash
|
|
||||||
# Elasticsearch 설치
|
|
||||||
brew install elasticsearch
|
|
||||||
|
|
||||||
# 설정 파일 위치 확인
|
|
||||||
brew --prefix elasticsearch
|
|
||||||
|
|
||||||
# JVM 메모리 설정 (8GB Mac 기준)
|
|
||||||
echo 'export ELASTICSEARCH_JAVA_OPTS="-Xms512m -Xmx1g"' >> ~/.zshrc
|
|
||||||
source ~/.zshrc
|
|
||||||
|
|
||||||
# 서비스 시작
|
|
||||||
brew services start elasticsearch
|
|
||||||
|
|
||||||
# 연결 테스트 (약 30초 후)
|
|
||||||
curl http://localhost:9200
|
|
||||||
```
|
|
||||||
|
|
||||||
### Elasticsearch 한국어 분석기 설치
|
|
||||||
```bash
|
|
||||||
# nori 분석기 설치
|
|
||||||
/opt/homebrew/bin/elasticsearch-plugin install analysis-nori
|
|
||||||
|
|
||||||
# 서비스 재시작
|
|
||||||
brew services restart elasticsearch
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐳 6단계: Docker 설치
|
|
||||||
|
|
||||||
### Docker Desktop 설치
|
|
||||||
```bash
|
|
||||||
# Docker Desktop 설치
|
|
||||||
brew install --cask docker
|
|
||||||
|
|
||||||
# Docker 실행 확인 (GUI에서 Docker Desktop 실행 필요)
|
|
||||||
docker --version
|
|
||||||
docker-compose --version
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker 설정 최적화
|
|
||||||
```bash
|
|
||||||
# Docker Desktop 설정 권장사항:
|
|
||||||
# - Memory: 4GB (8GB Mac 기준)
|
|
||||||
# - Swap: 1GB
|
|
||||||
# - Disk image size: 64GB
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ 7단계: 개발 도구 설치
|
|
||||||
|
|
||||||
### 필수 개발 도구
|
|
||||||
```bash
|
|
||||||
# Git (이미 설치되어 있을 수 있음)
|
|
||||||
brew install git
|
|
||||||
|
|
||||||
# 시스템 모니터링 도구
|
|
||||||
brew install htop
|
|
||||||
|
|
||||||
# 텍스트 처리 도구
|
|
||||||
brew install jq # JSON 처리
|
|
||||||
brew install ripgrep # 빠른 텍스트 검색
|
|
||||||
|
|
||||||
# 네트워크 도구
|
|
||||||
brew install curl
|
|
||||||
brew install wget
|
|
||||||
```
|
|
||||||
|
|
||||||
### IDE 및 에디터
|
|
||||||
```bash
|
|
||||||
# Visual Studio Code
|
|
||||||
brew install --cask visual-studio-code
|
|
||||||
|
|
||||||
# 또는 다른 에디터들
|
|
||||||
brew install --cask sublime-text
|
|
||||||
brew install --cask atom
|
|
||||||
brew install vim # 터미널 에디터
|
|
||||||
```
|
|
||||||
|
|
||||||
### 선택적 도구
|
|
||||||
```bash
|
|
||||||
# 데이터베이스 GUI 도구
|
|
||||||
brew install --cask dbeaver-community # 다중 DB 클라이언트
|
|
||||||
brew install --cask tableplus # macOS 네이티브 DB 클라이언트
|
|
||||||
|
|
||||||
# API 테스트 도구
|
|
||||||
brew install --cask postman
|
|
||||||
brew install --cask insomnia
|
|
||||||
|
|
||||||
# 터미널 개선
|
|
||||||
brew install zsh-autosuggestions
|
|
||||||
brew install zsh-syntax-highlighting
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 8단계: 프로젝트 설정
|
|
||||||
|
|
||||||
### 프로젝트 클론 및 설정
|
|
||||||
```bash
|
|
||||||
# 프로젝트 디렉토리로 이동
|
|
||||||
cd /Users/hyungi/news-project
|
|
||||||
|
|
||||||
# 가상환경 활성화
|
|
||||||
source venv/bin/activate
|
|
||||||
|
|
||||||
# 환경 변수 파일 생성
|
|
||||||
cp .env.example .env
|
|
||||||
```
|
|
||||||
|
|
||||||
### 환경 변수 설정 (.env 파일)
|
|
||||||
```bash
|
|
||||||
# .env 파일 편집
|
|
||||||
cat > .env << EOF
|
|
||||||
# 데이터베이스 설정
|
|
||||||
DATABASE_URL=postgresql://industrial_user:password@localhost:5432/industrial_info
|
|
||||||
REDIS_URL=redis://localhost:6379/0
|
|
||||||
ELASTICSEARCH_URL=http://localhost:9200
|
|
||||||
|
|
||||||
# 개발 환경 설정
|
|
||||||
DEBUG=True
|
|
||||||
SECRET_KEY=your-secret-key-here
|
|
||||||
|
|
||||||
# API 키 (필요시)
|
|
||||||
PUBMED_API_KEY=your-pubmed-api-key
|
|
||||||
IEEE_API_KEY=your-ieee-api-key
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
### Python 의존성 설치
|
|
||||||
```bash
|
|
||||||
# requirements.txt가 있는 경우
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# 또는 기본 패키지 설치
|
|
||||||
pip install fastapi uvicorn sqlalchemy psycopg2-binary redis elasticsearch celery spacy beautifulsoup4 requests pandas numpy
|
|
||||||
```
|
|
||||||
|
|
||||||
### Node.js 의존성 설치 (프론트엔드가 있는 경우)
|
|
||||||
```bash
|
|
||||||
# frontend 디렉토리가 있는 경우
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
cd ..
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 9단계: 서비스 관리
|
|
||||||
|
|
||||||
### 서비스 시작/중지 명령어
|
|
||||||
```bash
|
|
||||||
# 모든 서비스 시작
|
|
||||||
brew services start postgresql@15
|
|
||||||
brew services start redis
|
|
||||||
brew services start elasticsearch
|
|
||||||
|
|
||||||
# 서비스 상태 확인
|
|
||||||
brew services list
|
|
||||||
|
|
||||||
# 특정 서비스 중지
|
|
||||||
brew services stop postgresql@15
|
|
||||||
brew services stop redis
|
|
||||||
brew services stop elasticsearch
|
|
||||||
|
|
||||||
# 서비스 재시작
|
|
||||||
brew services restart postgresql@15
|
|
||||||
```
|
|
||||||
|
|
||||||
### 자동 시작 설정
|
|
||||||
```bash
|
|
||||||
# 시스템 부팅 시 자동 시작 (이미 설정됨)
|
|
||||||
# brew services start 명령어로 설치한 서비스들은 자동으로 부팅 시 시작됨
|
|
||||||
|
|
||||||
# 수동으로 자동 시작 해제하려면
|
|
||||||
brew services stop postgresql@15
|
|
||||||
# 그리고 수동으로 시작하려면
|
|
||||||
pg_ctl -D /opt/homebrew/var/postgresql@15 start
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 10단계: 성능 최적화
|
|
||||||
|
|
||||||
### 메모리 사용량 최적화 (8GB Mac 기준)
|
|
||||||
```bash
|
|
||||||
# ~/.zshrc에 추가
|
|
||||||
cat >> ~/.zshrc << EOF
|
|
||||||
|
|
||||||
# 개발환경 메모리 최적화
|
|
||||||
export ELASTICSEARCH_JAVA_OPTS="-Xms512m -Xmx1g"
|
|
||||||
export REDIS_MAXMEMORY="256mb"
|
|
||||||
export PYTHONOPTIMIZE=1
|
|
||||||
|
|
||||||
# PostgreSQL 설정 최적화
|
|
||||||
export PGDATA="/opt/homebrew/var/postgresql@15"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
source ~/.zshrc
|
|
||||||
```
|
|
||||||
|
|
||||||
### PostgreSQL 설정 최적화
|
|
||||||
```bash
|
|
||||||
# postgresql.conf 편집
|
|
||||||
vim /opt/homebrew/var/postgresql@15/postgresql.conf
|
|
||||||
|
|
||||||
# 다음 설정 추가/수정:
|
|
||||||
# shared_buffers = 256MB
|
|
||||||
# effective_cache_size = 1GB
|
|
||||||
# maintenance_work_mem = 64MB
|
|
||||||
# checkpoint_completion_target = 0.9
|
|
||||||
# wal_buffers = 16MB
|
|
||||||
# default_statistics_target = 100
|
|
||||||
|
|
||||||
# 설정 적용을 위해 재시작
|
|
||||||
brew services restart postgresql@15
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 11단계: 개발환경 테스트
|
|
||||||
|
|
||||||
### 연결 테스트 스크립트
|
|
||||||
```bash
|
|
||||||
# test_connections.py 생성
|
|
||||||
cat > test_connections.py << EOF
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
import psycopg2
|
|
||||||
import redis
|
|
||||||
import requests
|
|
||||||
|
|
||||||
def test_postgresql():
|
|
||||||
try:
|
|
||||||
conn = psycopg2.connect(
|
|
||||||
host="localhost",
|
|
||||||
database="industrial_info",
|
|
||||||
user="industrial_user",
|
|
||||||
password="password"
|
|
||||||
)
|
|
||||||
print("✅ PostgreSQL 연결 성공")
|
|
||||||
conn.close()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ PostgreSQL 연결 실패: {e}")
|
|
||||||
|
|
||||||
def test_redis():
|
|
||||||
try:
|
|
||||||
r = redis.Redis(host='localhost', port=6379, db=0)
|
|
||||||
r.ping()
|
|
||||||
print("✅ Redis 연결 성공")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Redis 연결 실패: {e}")
|
|
||||||
|
|
||||||
def test_elasticsearch():
|
|
||||||
try:
|
|
||||||
response = requests.get('http://localhost:9200')
|
|
||||||
if response.status_code == 200:
|
|
||||||
print("✅ Elasticsearch 연결 성공")
|
|
||||||
else:
|
|
||||||
print(f"❌ Elasticsearch 연결 실패: {response.status_code}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Elasticsearch 연결 실패: {e}")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("🔍 개발환경 연결 테스트")
|
|
||||||
test_postgresql()
|
|
||||||
test_redis()
|
|
||||||
test_elasticsearch()
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 테스트 실행
|
|
||||||
python test_connections.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### 시스템 리소스 모니터링
|
|
||||||
```bash
|
|
||||||
# 시스템 리소스 확인
|
|
||||||
htop
|
|
||||||
|
|
||||||
# Docker 컨테이너 리소스 확인 (Docker 사용 시)
|
|
||||||
docker stats
|
|
||||||
|
|
||||||
# 디스크 사용량 확인
|
|
||||||
df -h
|
|
||||||
|
|
||||||
# 메모리 사용량 확인
|
|
||||||
vm_stat
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚨 문제 해결
|
|
||||||
|
|
||||||
### 일반적인 문제들
|
|
||||||
|
|
||||||
#### 1. Homebrew 설치 실패
|
|
||||||
```bash
|
|
||||||
# 권한 문제 해결
|
|
||||||
sudo chown -R $(whoami) /opt/homebrew
|
|
||||||
|
|
||||||
# 또는 Rosetta 2 설치 (M1/M2 Mac)
|
|
||||||
softwareupdate --install-rosetta
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. PostgreSQL 연결 실패
|
|
||||||
```bash
|
|
||||||
# 서비스 상태 확인
|
|
||||||
brew services list | grep postgresql
|
|
||||||
|
|
||||||
# 로그 확인
|
|
||||||
tail -f /opt/homebrew/var/log/postgresql@15.log
|
|
||||||
|
|
||||||
# 포트 충돌 확인
|
|
||||||
lsof -i :5432
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Elasticsearch 시작 실패
|
|
||||||
```bash
|
|
||||||
# Java 설치 확인
|
|
||||||
java --version
|
|
||||||
|
|
||||||
# 메모리 부족 시 설정 조정
|
|
||||||
export ELASTICSEARCH_JAVA_OPTS="-Xms256m -Xmx512m"
|
|
||||||
|
|
||||||
# 로그 확인
|
|
||||||
tail -f /opt/homebrew/var/log/elasticsearch.log
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. Redis 연결 문제
|
|
||||||
```bash
|
|
||||||
# Redis 서비스 확인
|
|
||||||
brew services list | grep redis
|
|
||||||
|
|
||||||
# 설정 파일 확인
|
|
||||||
cat /opt/homebrew/etc/redis.conf
|
|
||||||
|
|
||||||
# 포트 확인
|
|
||||||
lsof -i :6379
|
|
||||||
```
|
|
||||||
|
|
||||||
### 성능 문제 해결
|
|
||||||
|
|
||||||
#### 메모리 부족 시
|
|
||||||
```bash
|
|
||||||
# 불필요한 서비스 중지
|
|
||||||
brew services stop elasticsearch # 임시로 중지
|
|
||||||
|
|
||||||
# Swap 사용량 확인
|
|
||||||
sysctl vm.swapusage
|
|
||||||
|
|
||||||
# 메모리 정리
|
|
||||||
sudo purge
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 디스크 공간 부족 시
|
|
||||||
```bash
|
|
||||||
# Homebrew 캐시 정리
|
|
||||||
brew cleanup
|
|
||||||
|
|
||||||
# Docker 이미지 정리
|
|
||||||
docker system prune -a
|
|
||||||
|
|
||||||
# 로그 파일 정리
|
|
||||||
sudo rm -rf /opt/homebrew/var/log/*.log.*
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 추가 리소스
|
|
||||||
|
|
||||||
### 유용한 명령어 모음
|
|
||||||
```bash
|
|
||||||
# 모든 Homebrew 서비스 상태 확인
|
|
||||||
brew services list
|
|
||||||
|
|
||||||
# 설치된 패키지 목록
|
|
||||||
brew list
|
|
||||||
|
|
||||||
# 패키지 정보 확인
|
|
||||||
brew info postgresql@15
|
|
||||||
|
|
||||||
# 의존성 확인
|
|
||||||
brew deps --tree postgresql@15
|
|
||||||
|
|
||||||
# 업데이트 가능한 패키지 확인
|
|
||||||
brew outdated
|
|
||||||
```
|
|
||||||
|
|
||||||
### 개발 워크플로우
|
|
||||||
```bash
|
|
||||||
# 일일 개발 시작 루틴
|
|
||||||
cd /Users/hyungi/news-project
|
|
||||||
source venv/bin/activate
|
|
||||||
brew services start postgresql@15 redis elasticsearch
|
|
||||||
|
|
||||||
# 일일 개발 종료 루틴
|
|
||||||
deactivate
|
|
||||||
brew services stop elasticsearch # 메모리 절약을 위해
|
|
||||||
```
|
|
||||||
|
|
||||||
### 백업 및 복원
|
|
||||||
```bash
|
|
||||||
# PostgreSQL 백업
|
|
||||||
pg_dump industrial_info > backup.sql
|
|
||||||
|
|
||||||
# PostgreSQL 복원
|
|
||||||
psql industrial_info < backup.sql
|
|
||||||
|
|
||||||
# 설정 파일 백업
|
|
||||||
cp ~/.zshrc ~/.zshrc.backup
|
|
||||||
cp .env .env.backup
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
이 가이드를 따라하면 macOS에서 Homebrew를 사용하여 완전한 개발환경을 구축할 수 있습니다. 각 단계별로 진행하면서 문제가 발생하면 문제 해결 섹션을 참조하세요.
|
|
||||||
@@ -1,721 +0,0 @@
|
|||||||
# 🏠 시놀로지 NAS 설치 가이드
|
|
||||||
|
|
||||||
## 📋 개요
|
|
||||||
|
|
||||||
시놀로지 NAS에서 산업 전문 정보 수집 시스템을 Docker 기반으로 설치하는 가이드입니다. 24시간 안정적인 서비스 운영이 가능하며, 480GB SSD 환경에 최적화된 설정을 제공합니다.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 사전 요구사항
|
|
||||||
|
|
||||||
### 하드웨어 요구사항
|
|
||||||
- **시놀로지 NAS**: DS220+, DS720+, DS920+ 이상 (Docker 지원 모델)
|
|
||||||
- **메모리**: 4GB 이상 (8GB 권장)
|
|
||||||
- **저장공간**: 480GB SSD (충분함)
|
|
||||||
- **네트워크**: 기가비트 이더넷
|
|
||||||
|
|
||||||
### 소프트웨어 요구사항
|
|
||||||
- **DSM**: 7.0 이상
|
|
||||||
- **Docker**: Container Manager 패키지
|
|
||||||
- **Git Server**: Git 저장소 관리용 (선택사항)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐳 1단계: Docker 환경 설정
|
|
||||||
|
|
||||||
### Container Manager 설치
|
|
||||||
```
|
|
||||||
1. 패키지 센터 → Container Manager 검색 및 설치
|
|
||||||
2. Container Manager 실행
|
|
||||||
3. 레지스트리 탭에서 필요한 이미지 다운로드 준비
|
|
||||||
```
|
|
||||||
|
|
||||||
### 필요한 Docker 이미지 다운로드
|
|
||||||
```bash
|
|
||||||
# SSH로 NAS 접속 후 실행
|
|
||||||
docker pull python:3.11-slim
|
|
||||||
docker pull postgres:15-alpine
|
|
||||||
docker pull redis:7-alpine
|
|
||||||
docker pull elasticsearch:8.11.0
|
|
||||||
docker pull nginx:alpine
|
|
||||||
```
|
|
||||||
|
|
||||||
### 볼륨 및 네트워크 설정
|
|
||||||
```bash
|
|
||||||
# 전용 네트워크 생성
|
|
||||||
docker network create industrial-net
|
|
||||||
|
|
||||||
# 데이터 볼륨 생성
|
|
||||||
docker volume create postgres-data
|
|
||||||
docker volume create elasticsearch-data
|
|
||||||
docker volume create redis-data
|
|
||||||
docker volume create app-logs
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 2단계: 디렉토리 구조 설정
|
|
||||||
|
|
||||||
### NAS 내 프로젝트 디렉토리 생성
|
|
||||||
```bash
|
|
||||||
# SSH 접속 후 디렉토리 생성
|
|
||||||
mkdir -p /volume1/docker/industrial-info/{
|
|
||||||
app,
|
|
||||||
data/{postgres,elasticsearch,redis,logs},
|
|
||||||
config,
|
|
||||||
backup
|
|
||||||
}
|
|
||||||
|
|
||||||
# 권한 설정
|
|
||||||
chown -R 1000:1000 /volume1/docker/industrial-info
|
|
||||||
```
|
|
||||||
|
|
||||||
### 디렉토리 구조
|
|
||||||
```
|
|
||||||
/volume1/docker/industrial-info/
|
|
||||||
├── app/ # 애플리케이션 코드
|
|
||||||
├── data/ # 데이터 저장소
|
|
||||||
│ ├── postgres/ # PostgreSQL 데이터
|
|
||||||
│ ├── elasticsearch/ # Elasticsearch 데이터
|
|
||||||
│ ├── redis/ # Redis 데이터
|
|
||||||
│ └── logs/ # 애플리케이션 로그
|
|
||||||
├── config/ # 설정 파일들
|
|
||||||
└── backup/ # 백업 파일들
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐘 3단계: PostgreSQL 설정
|
|
||||||
|
|
||||||
### PostgreSQL 컨테이너 생성
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml의 PostgreSQL 부분
|
|
||||||
version: '3.8'
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: industrial-postgres
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: industrial_info
|
|
||||||
POSTGRES_USER: industrial_user
|
|
||||||
POSTGRES_PASSWORD: secure_password_here
|
|
||||||
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/postgres:/var/lib/postgresql/data
|
|
||||||
- /volume1/docker/industrial-info/config/postgres.conf:/etc/postgresql/postgresql.conf
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
reservations:
|
|
||||||
memory: 512M
|
|
||||||
```
|
|
||||||
|
|
||||||
### PostgreSQL 최적화 설정
|
|
||||||
```bash
|
|
||||||
# /volume1/docker/industrial-info/config/postgres.conf 생성
|
|
||||||
cat > /volume1/docker/industrial-info/config/postgres.conf << EOF
|
|
||||||
# 시놀로지 NAS 최적화 설정
|
|
||||||
shared_buffers = 256MB
|
|
||||||
effective_cache_size = 1GB
|
|
||||||
maintenance_work_mem = 64MB
|
|
||||||
checkpoint_completion_target = 0.9
|
|
||||||
wal_buffers = 16MB
|
|
||||||
default_statistics_target = 100
|
|
||||||
random_page_cost = 1.1
|
|
||||||
effective_io_concurrency = 200
|
|
||||||
|
|
||||||
# 로그 설정
|
|
||||||
log_destination = 'stderr'
|
|
||||||
logging_collector = on
|
|
||||||
log_directory = '/var/log/postgresql'
|
|
||||||
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
|
|
||||||
log_rotation_age = 1d
|
|
||||||
log_rotation_size = 100MB
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 4단계: Elasticsearch 설정
|
|
||||||
|
|
||||||
### Elasticsearch 컨테이너 (경량화 버전)
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml의 Elasticsearch 부분
|
|
||||||
elasticsearch:
|
|
||||||
image: elasticsearch:8.11.0
|
|
||||||
container_name: industrial-elasticsearch
|
|
||||||
environment:
|
|
||||||
- discovery.type=single-node
|
|
||||||
- "ES_JAVA_OPTS=-Xms512m -Xmx1g" # NAS 메모리 고려
|
|
||||||
- xpack.security.enabled=false
|
|
||||||
- xpack.security.enrollment.enabled=false
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/elasticsearch:/usr/share/elasticsearch/data
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1.5G
|
|
||||||
reservations:
|
|
||||||
memory: 1G
|
|
||||||
ulimits:
|
|
||||||
memlock:
|
|
||||||
soft: -1
|
|
||||||
hard: -1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Elasticsearch 한국어 분석기 설정
|
|
||||||
```bash
|
|
||||||
# 컨테이너 실행 후 nori 플러그인 설치
|
|
||||||
docker exec industrial-elasticsearch elasticsearch-plugin install analysis-nori
|
|
||||||
docker restart industrial-elasticsearch
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔴 5단계: Redis 설정
|
|
||||||
|
|
||||||
### Redis 컨테이너
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml의 Redis 부분
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
container_name: industrial-redis
|
|
||||||
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/redis:/data
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512M
|
|
||||||
reservations:
|
|
||||||
memory: 256M
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐍 6단계: 애플리케이션 설정
|
|
||||||
|
|
||||||
### 애플리케이션 Dockerfile
|
|
||||||
```dockerfile
|
|
||||||
# /volume1/docker/industrial-info/app/Dockerfile
|
|
||||||
FROM python:3.11-slim
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
# 애플리케이션 코드 복사
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# 포트 노출
|
|
||||||
EXPOSE 8000
|
|
||||||
|
|
||||||
# 애플리케이션 실행
|
|
||||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 애플리케이션 컨테이너
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml의 애플리케이션 부분
|
|
||||||
app:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-app
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
reservations:
|
|
||||||
memory: 512M
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 7단계: Nginx 리버스 프록시
|
|
||||||
|
|
||||||
### Nginx 설정
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml의 Nginx 부분
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: industrial-nginx
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/config/nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/var/log/nginx
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- app
|
|
||||||
restart: unless-stopped
|
|
||||||
```
|
|
||||||
|
|
||||||
### Nginx 설정 파일
|
|
||||||
```nginx
|
|
||||||
# /volume1/docker/industrial-info/config/nginx.conf
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
upstream app {
|
|
||||||
server app:8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
client_max_body_size 100M;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 8단계: 통합 Docker Compose
|
|
||||||
|
|
||||||
### 완전한 docker-compose.yml
|
|
||||||
```yaml
|
|
||||||
# /volume1/docker/industrial-info/docker-compose.yml
|
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
industrial-net:
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: industrial-postgres
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: industrial_info
|
|
||||||
POSTGRES_USER: industrial_user
|
|
||||||
POSTGRES_PASSWORD: secure_password_here
|
|
||||||
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/postgres:/var/lib/postgresql/data
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
container_name: industrial-redis
|
|
||||||
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/redis:/data
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512M
|
|
||||||
|
|
||||||
elasticsearch:
|
|
||||||
image: elasticsearch:8.11.0
|
|
||||||
container_name: industrial-elasticsearch
|
|
||||||
environment:
|
|
||||||
- discovery.type=single-node
|
|
||||||
- "ES_JAVA_OPTS=-Xms512m -Xmx1g"
|
|
||||||
- xpack.security.enabled=false
|
|
||||||
- xpack.security.enrollment.enabled=false
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/data/elasticsearch:/usr/share/elasticsearch/data
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1.5G
|
|
||||||
ulimits:
|
|
||||||
memlock:
|
|
||||||
soft: -1
|
|
||||||
hard: -1
|
|
||||||
|
|
||||||
app:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-app
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
- PYTHONPATH=/app
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: industrial-nginx
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/config/nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/var/log/nginx
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- app
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
# 데이터 수집 워커 (Celery)
|
|
||||||
worker:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-worker
|
|
||||||
command: celery -A main.celery worker --loglevel=info
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512M
|
|
||||||
|
|
||||||
# 스케줄러 (Celery Beat)
|
|
||||||
scheduler:
|
|
||||||
build: ./app
|
|
||||||
container_name: industrial-scheduler
|
|
||||||
command: celery -A main.celery beat --loglevel=info
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/industrial-info/app:/app
|
|
||||||
- /volume1/docker/industrial-info/data/logs:/app/logs
|
|
||||||
networks:
|
|
||||||
- industrial-net
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
- elasticsearch
|
|
||||||
restart: unless-stopped
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 256M
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 9단계: 배포 및 실행
|
|
||||||
|
|
||||||
### 시스템 실행
|
|
||||||
```bash
|
|
||||||
# 프로젝트 디렉토리로 이동
|
|
||||||
cd /volume1/docker/industrial-info
|
|
||||||
|
|
||||||
# 컨테이너 빌드 및 실행
|
|
||||||
docker-compose up --build -d
|
|
||||||
|
|
||||||
# 로그 확인
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# 서비스 상태 확인
|
|
||||||
docker-compose ps
|
|
||||||
```
|
|
||||||
|
|
||||||
### 데이터베이스 초기화
|
|
||||||
```bash
|
|
||||||
# 애플리케이션 컨테이너에서 마이그레이션 실행
|
|
||||||
docker exec industrial-app python manage.py migrate
|
|
||||||
|
|
||||||
# 슈퍼유저 생성
|
|
||||||
docker exec -it industrial-app python manage.py createsuperuser
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 10단계: 모니터링 및 최적화
|
|
||||||
|
|
||||||
### 리소스 모니터링
|
|
||||||
```bash
|
|
||||||
# 컨테이너 리소스 사용량 확인
|
|
||||||
docker stats
|
|
||||||
|
|
||||||
# 디스크 사용량 확인
|
|
||||||
df -h /volume1
|
|
||||||
|
|
||||||
# 메모리 사용량 확인
|
|
||||||
free -h
|
|
||||||
```
|
|
||||||
|
|
||||||
### 로그 관리
|
|
||||||
```bash
|
|
||||||
# 로그 로테이션 설정 (crontab)
|
|
||||||
# 매일 자정에 로그 압축 및 정리
|
|
||||||
0 0 * * * find /volume1/docker/industrial-info/data/logs -name "*.log" -mtime +7 -exec gzip {} \;
|
|
||||||
0 0 * * * find /volume1/docker/industrial-info/data/logs -name "*.gz" -mtime +30 -delete
|
|
||||||
```
|
|
||||||
|
|
||||||
### 성능 최적화 설정
|
|
||||||
```bash
|
|
||||||
# 시놀로지 NAS 최적화
|
|
||||||
echo 'vm.swappiness=10' >> /etc/sysctl.conf
|
|
||||||
echo 'vm.vfs_cache_pressure=50' >> /etc/sysctl.conf
|
|
||||||
|
|
||||||
# Docker 로그 크기 제한
|
|
||||||
cat > /etc/docker/daemon.json << EOF
|
|
||||||
{
|
|
||||||
"log-driver": "json-file",
|
|
||||||
"log-opts": {
|
|
||||||
"max-size": "10m",
|
|
||||||
"max-file": "3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 11단계: 백업 및 복원
|
|
||||||
|
|
||||||
### 자동 백업 스크립트
|
|
||||||
```bash
|
|
||||||
# /volume1/docker/industrial-info/backup/backup.sh
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
BACKUP_DIR="/volume1/docker/industrial-info/backup"
|
|
||||||
DATE=$(date +%Y%m%d_%H%M%S)
|
|
||||||
|
|
||||||
# PostgreSQL 백업
|
|
||||||
docker exec industrial-postgres pg_dump -U industrial_user industrial_info > $BACKUP_DIR/postgres_$DATE.sql
|
|
||||||
|
|
||||||
# Elasticsearch 백업 (인덱스 설정만)
|
|
||||||
curl -X GET "localhost:9200/_cat/indices?v" > $BACKUP_DIR/elasticsearch_indices_$DATE.txt
|
|
||||||
|
|
||||||
# 애플리케이션 코드 백업
|
|
||||||
tar -czf $BACKUP_DIR/app_$DATE.tar.gz /volume1/docker/industrial-info/app
|
|
||||||
|
|
||||||
# 7일 이상 된 백업 파일 삭제
|
|
||||||
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
|
|
||||||
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
|
|
||||||
|
|
||||||
echo "Backup completed: $DATE"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 백업 스케줄 설정
|
|
||||||
```bash
|
|
||||||
# crontab 설정
|
|
||||||
# 매일 새벽 2시에 백업 실행
|
|
||||||
0 2 * * * /volume1/docker/industrial-info/backup/backup.sh >> /volume1/docker/industrial-info/data/logs/backup.log 2>&1
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 12단계: 외부 접근 설정
|
|
||||||
|
|
||||||
### 시놀로지 방화벽 설정
|
|
||||||
```
|
|
||||||
제어판 → 보안 → 방화벽 → 규칙 편집
|
|
||||||
- 포트 80 (HTTP) 허용
|
|
||||||
- 포트 443 (HTTPS) 허용 (SSL 인증서 설정 시)
|
|
||||||
- 포트 8000 (개발용, 선택사항)
|
|
||||||
```
|
|
||||||
|
|
||||||
### DDNS 설정
|
|
||||||
```
|
|
||||||
제어판 → 외부 액세스 → DDNS
|
|
||||||
- Synology DDNS 서비스 활용
|
|
||||||
- 또는 외부 DDNS 서비스 연동
|
|
||||||
```
|
|
||||||
|
|
||||||
### SSL 인증서 설정
|
|
||||||
```
|
|
||||||
제어판 → 보안 → 인증서
|
|
||||||
- Let's Encrypt 무료 인증서 발급
|
|
||||||
- 자동 갱신 설정
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚨 문제 해결
|
|
||||||
|
|
||||||
### 일반적인 문제들
|
|
||||||
|
|
||||||
#### 1. 메모리 부족
|
|
||||||
```bash
|
|
||||||
# Elasticsearch 메모리 줄이기
|
|
||||||
# docker-compose.yml에서 ES_JAVA_OPTS 수정
|
|
||||||
- "ES_JAVA_OPTS=-Xms256m -Xmx512m"
|
|
||||||
|
|
||||||
# 불필요한 컨테이너 중지
|
|
||||||
docker-compose stop worker scheduler
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 디스크 공간 부족
|
|
||||||
```bash
|
|
||||||
# Docker 이미지 정리
|
|
||||||
docker system prune -a
|
|
||||||
|
|
||||||
# 로그 파일 정리
|
|
||||||
docker-compose exec app find /app/logs -name "*.log" -mtime +3 -delete
|
|
||||||
|
|
||||||
# 백업 파일 정리
|
|
||||||
find /volume1/docker/industrial-info/backup -mtime +30 -delete
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. 네트워크 연결 문제
|
|
||||||
```bash
|
|
||||||
# 네트워크 재생성
|
|
||||||
docker network rm industrial-net
|
|
||||||
docker network create industrial-net
|
|
||||||
|
|
||||||
# 컨테이너 재시작
|
|
||||||
docker-compose restart
|
|
||||||
```
|
|
||||||
|
|
||||||
### 성능 튜닝
|
|
||||||
|
|
||||||
#### SSD 최적화
|
|
||||||
```bash
|
|
||||||
# SSD 수명 연장을 위한 설정
|
|
||||||
echo 'deadline' > /sys/block/sda/queue/scheduler
|
|
||||||
echo '1' > /sys/block/sda/queue/iosched/fifo_batch
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 네트워크 최적화
|
|
||||||
```bash
|
|
||||||
# TCP 버퍼 크기 조정
|
|
||||||
echo 'net.core.rmem_max = 16777216' >> /etc/sysctl.conf
|
|
||||||
echo 'net.core.wmem_max = 16777216' >> /etc/sysctl.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📈 시놀로지 vs Mac 비교
|
|
||||||
|
|
||||||
### 시놀로지 NAS 장점
|
|
||||||
- ✅ **24시간 안정 운영**: 전력 효율적, 저소음
|
|
||||||
- ✅ **자동 백업**: RAID 구성, 스냅샷 기능
|
|
||||||
- ✅ **원격 접근**: DDNS, VPN 지원
|
|
||||||
- ✅ **비용 효율**: 전력비 절약, 별도 서버 불필요
|
|
||||||
- ✅ **확장성**: 패키지 센터, Docker 지원
|
|
||||||
|
|
||||||
### Mac 개발 환경 장점
|
|
||||||
- ✅ **개발 편의성**: 네이티브 도구, IDE 지원
|
|
||||||
- ✅ **성능**: 더 빠른 CPU, 메모리
|
|
||||||
- ✅ **디버깅**: 직접적인 로그 접근
|
|
||||||
- ✅ **유연성**: 패키지 관리 용이
|
|
||||||
|
|
||||||
### 권장 사용 시나리오
|
|
||||||
```
|
|
||||||
개발 단계: Mac (HOMEBREW_SETUP.md)
|
|
||||||
↓
|
|
||||||
테스트/스테이징: 시놀로지 NAS (현재 문서)
|
|
||||||
↓
|
|
||||||
프로덕션: 클라우드 또는 전용 서버
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 결론
|
|
||||||
|
|
||||||
시놀로지 NAS는 다음과 같은 경우에 최적입니다:
|
|
||||||
|
|
||||||
1. **24시간 서비스 운영**이 필요한 경우
|
|
||||||
2. **전력 효율성**을 중시하는 경우
|
|
||||||
3. **자동 백업 및 데이터 보호**가 중요한 경우
|
|
||||||
4. **원격 접근**이 필요한 경우
|
|
||||||
5. **비용 절약**을 원하는 경우
|
|
||||||
|
|
||||||
480GB SSD는 이 프로젝트에 충분하며, 적절한 로그 관리와 백업 정책으로 장기간 안정적인 운영이 가능합니다.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**시놀로지 NAS로 더 안정적이고 효율적인 산업 정보 시스템을 구축해보세요!** 🏠🚀
|
|
||||||
285
TECH_STACK.md
285
TECH_STACK.md
@@ -1,285 +0,0 @@
|
|||||||
# 🛠️ 기술 스택 (Tech Stack)
|
|
||||||
|
|
||||||
## 📋 개요
|
|
||||||
|
|
||||||
산업 전문 정보 수집 시스템의 기술 스택을 정리한 문서입니다. 각 기술의 선택 이유와 역할을 포함하여 설명합니다.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🖥️ Backend
|
|
||||||
|
|
||||||
### 핵심 프레임워크
|
|
||||||
- **Python 3.11+**
|
|
||||||
- 선택 이유: 풍부한 NLP 라이브러리 생태계, 데이터 처리 최적화
|
|
||||||
- 역할: 메인 백엔드 언어
|
|
||||||
|
|
||||||
- **FastAPI**
|
|
||||||
- 선택 이유: 고성능 비동기 처리, 자동 API 문서 생성, 타입 힌팅 지원
|
|
||||||
- 역할: REST API 서버, 웹 애플리케이션 백엔드
|
|
||||||
|
|
||||||
### 데이터베이스 & 검색
|
|
||||||
- **PostgreSQL**
|
|
||||||
- 선택 이유: 구조화된 메타데이터 저장, ACID 트랜잭션, JSON 지원
|
|
||||||
- 역할: 메인 데이터베이스, 사용자 정보, 문서 메타데이터
|
|
||||||
|
|
||||||
- **Elasticsearch**
|
|
||||||
- 선택 이유: 전문 검색, 다차원 필터링, 실시간 검색 성능
|
|
||||||
- 역할: 문서 검색 엔진, 태그 기반 필터링, 전문 검색
|
|
||||||
|
|
||||||
- **Redis**
|
|
||||||
- 선택 이유: 고속 캐싱, 세션 관리, 실시간 데이터 처리
|
|
||||||
- 역할: 캐시 레이어, 검색 결과 캐싱, 트렌딩 데이터
|
|
||||||
|
|
||||||
### NLP & 데이터 처리
|
|
||||||
- **spaCy**
|
|
||||||
- 선택 이유: 산업용 NLP, 커스텀 모델 지원, 한국어 지원
|
|
||||||
- 역할: 개체명 인식(NER), 기술 용어 추출
|
|
||||||
|
|
||||||
- **Transformers (Hugging Face)**
|
|
||||||
- 선택 이유: 최신 언어 모델, 의미 기반 검색
|
|
||||||
- 역할: 문서 임베딩, 의미 유사도 계산
|
|
||||||
|
|
||||||
- **scikit-learn**
|
|
||||||
- 선택 이유: 머신러닝 파이프라인, 텍스트 분류
|
|
||||||
- 역할: 문서 분류, 태그 예측, 트렌드 분석
|
|
||||||
|
|
||||||
### 비동기 처리 & 스케줄링
|
|
||||||
- **Celery**
|
|
||||||
- 선택 이유: 분산 태스크 큐, 스케줄링 지원
|
|
||||||
- 역할: RSS 수집, 논문 처리, 배치 작업
|
|
||||||
|
|
||||||
- **Redis (Broker)**
|
|
||||||
- 선택 이유: Celery 메시지 브로커, 고성능
|
|
||||||
- 역할: 태스크 큐 브로커
|
|
||||||
|
|
||||||
### 문서 처리
|
|
||||||
- **PyPDF2 / pdfplumber**
|
|
||||||
- 선택 이유: PDF 텍스트 추출, 메타데이터 파싱
|
|
||||||
- 역할: 논문 PDF 처리, 기술 문서 분석
|
|
||||||
|
|
||||||
- **BeautifulSoup**
|
|
||||||
- 선택 이유: HTML 파싱, 웹 스크래핑
|
|
||||||
- 역할: RSS 피드 처리, 웹사이트 크롤링
|
|
||||||
|
|
||||||
- **Scrapy**
|
|
||||||
- 선택 이유: 대규모 웹 크롤링, 비동기 처리
|
|
||||||
- 역할: 표준 기관 웹사이트 모니터링
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 Frontend
|
|
||||||
|
|
||||||
### 핵심 프레임워크
|
|
||||||
- **React 18**
|
|
||||||
- 선택 이유: 컴포넌트 기반 개발, 풍부한 생태계
|
|
||||||
- 역할: 사용자 인터페이스 구축
|
|
||||||
|
|
||||||
- **Next.js 13+**
|
|
||||||
- 선택 이유: SSR/SSG 지원, 성능 최적화, 파일 기반 라우팅
|
|
||||||
- 역할: React 애플리케이션 프레임워크
|
|
||||||
|
|
||||||
### UI & 스타일링
|
|
||||||
- **Tailwind CSS**
|
|
||||||
- 선택 이유: 유틸리티 우선, 빠른 개발, 일관된 디자인
|
|
||||||
- 역할: CSS 프레임워크, 반응형 디자인
|
|
||||||
|
|
||||||
- **Material-UI (MUI)**
|
|
||||||
- 선택 이유: 전문적인 UI 컴포넌트, 접근성 지원
|
|
||||||
- 역할: 복잡한 UI 컴포넌트 (테이블, 폼 등)
|
|
||||||
|
|
||||||
### 데이터 시각화
|
|
||||||
- **D3.js**
|
|
||||||
- 선택 이유: 고도로 커스터마이징 가능한 시각화
|
|
||||||
- 역할: 기술 네트워크 그래프, 복잡한 차트
|
|
||||||
|
|
||||||
- **Chart.js**
|
|
||||||
- 선택 이유: 간단한 차트 생성, React 통합
|
|
||||||
- 역할: 트렌드 차트, 통계 그래프
|
|
||||||
|
|
||||||
### 검색 & 상호작용
|
|
||||||
- **Algolia InstantSearch**
|
|
||||||
- 선택 이유: 실시간 검색, 자동완성, 필터링
|
|
||||||
- 역할: 검색 UI 컴포넌트
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 전문 분야 도구
|
|
||||||
|
|
||||||
### 학술 데이터 수집
|
|
||||||
- **arXiv API**
|
|
||||||
- 선택 이유: 물리학/공학 논문 접근
|
|
||||||
- 역할: 최신 연구 논문 수집
|
|
||||||
|
|
||||||
- **PubMed API**
|
|
||||||
- 선택 이유: 의학/보건 관련 논문
|
|
||||||
- 역할: 산업안전 의학 연구 수집
|
|
||||||
|
|
||||||
- **IEEE Xplore API**
|
|
||||||
- 선택 이유: 전기/전자/컴퓨터 공학 논문
|
|
||||||
- 역할: 기술 표준 및 연구 논문 수집
|
|
||||||
|
|
||||||
### 표준 모니터링
|
|
||||||
- **ASME 웹사이트 크롤러**
|
|
||||||
- 선택 이유: 압력용기 표준 업데이트 추적
|
|
||||||
- 역할: BPVC 등 표준 변경사항 모니터링
|
|
||||||
|
|
||||||
- **KGS 웹사이트 크롤러**
|
|
||||||
- 선택 이유: 한국 가스안전 기준 추적
|
|
||||||
- 역할: 국내 압력용기 기준 업데이트
|
|
||||||
|
|
||||||
- **API 웹사이트 크롤러**
|
|
||||||
- 선택 이유: 석유/가스 산업 표준 추적
|
|
||||||
- 역할: API 표준 업데이트 모니터링
|
|
||||||
|
|
||||||
### 전문 용어 처리
|
|
||||||
- **압력용기 전문 용어 사전**
|
|
||||||
- 선택 이유: 정확한 기술 용어 인식
|
|
||||||
- 역할: NER 모델 학습 데이터
|
|
||||||
|
|
||||||
- **플랜트 장비 분류 체계**
|
|
||||||
- 선택 이유: 체계적인 장비 분류
|
|
||||||
- 역할: 태그 정규화 및 분류
|
|
||||||
|
|
||||||
- **산업안전 용어 온톨로지**
|
|
||||||
- 선택 이유: 안전 분야 전문 용어 체계화
|
|
||||||
- 역할: 안전 관련 문서 분류
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ Infrastructure
|
|
||||||
|
|
||||||
### 컨테이너화
|
|
||||||
- **Docker**
|
|
||||||
- 선택 이유: 환경 일관성, 배포 간소화
|
|
||||||
- 역할: 애플리케이션 컨테이너화
|
|
||||||
|
|
||||||
- **Docker Compose**
|
|
||||||
- 선택 이유: 다중 서비스 오케스트레이션
|
|
||||||
- 역할: 로컬 개발 환경 구성
|
|
||||||
|
|
||||||
### 모니터링 & 로깅
|
|
||||||
- **Prometheus**
|
|
||||||
- 선택 이유: 시계열 메트릭 수집, 알림 시스템
|
|
||||||
- 역할: 시스템 메트릭 모니터링
|
|
||||||
|
|
||||||
- **Grafana**
|
|
||||||
- 선택 이유: 메트릭 시각화, 대시보드
|
|
||||||
- 역할: 모니터링 대시보드
|
|
||||||
|
|
||||||
- **ELK Stack (Elasticsearch, Logstash, Kibana)**
|
|
||||||
- 선택 이유: 중앙화된 로그 관리, 검색 가능한 로그
|
|
||||||
- 역할: 애플리케이션 로그 수집 및 분석
|
|
||||||
|
|
||||||
### CI/CD
|
|
||||||
- **GitHub Actions**
|
|
||||||
- 선택 이유: GitHub 통합, 무료 사용량
|
|
||||||
- 역할: 자동 빌드, 테스트, 배포
|
|
||||||
|
|
||||||
### 스토리지
|
|
||||||
- **MinIO (S3 호환)**
|
|
||||||
- 선택 이유: 오픈소스 객체 스토리지, S3 호환성
|
|
||||||
- 역할: 논문 PDF, 이미지 파일 저장
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🍺 macOS 개발 환경 (Homebrew 기반)
|
|
||||||
|
|
||||||
### 패키지 매니저
|
|
||||||
- **Homebrew**
|
|
||||||
- 선택 이유: macOS 표준 패키지 매니저
|
|
||||||
- 역할: 개발 도구 설치 및 관리
|
|
||||||
|
|
||||||
### 필수 개발 도구
|
|
||||||
```bash
|
|
||||||
# 언어 런타임
|
|
||||||
brew install python@3.11 # Python 런타임
|
|
||||||
brew install node@18 # Node.js 런타임
|
|
||||||
|
|
||||||
# 데이터베이스
|
|
||||||
brew install postgresql # PostgreSQL 데이터베이스
|
|
||||||
brew install redis # Redis 캐시/브로커
|
|
||||||
|
|
||||||
# 검색 엔진
|
|
||||||
brew install elasticsearch # Elasticsearch 검색 엔진
|
|
||||||
|
|
||||||
# 개발 도구
|
|
||||||
brew install git # 버전 관리
|
|
||||||
brew install htop # 시스템 모니터링
|
|
||||||
|
|
||||||
# GUI 애플리케이션
|
|
||||||
brew install --cask docker # Docker Desktop
|
|
||||||
brew install --cask visual-studio-code # IDE
|
|
||||||
```
|
|
||||||
|
|
||||||
### 서비스 관리
|
|
||||||
```bash
|
|
||||||
# 서비스 시작
|
|
||||||
brew services start postgresql
|
|
||||||
brew services start redis
|
|
||||||
brew services start elasticsearch
|
|
||||||
|
|
||||||
# 서비스 상태 확인
|
|
||||||
brew services list
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 성능 최적화 전략
|
|
||||||
|
|
||||||
### 캐싱 계층
|
|
||||||
```
|
|
||||||
L1: Redis (실시간 검색 결과, 트렌딩 태그)
|
|
||||||
L2: PostgreSQL (구조화된 메타데이터, 사용자 프로필)
|
|
||||||
L3: Elasticsearch (전문 검색, 태그 인덱스)
|
|
||||||
L4: MinIO/S3 (원본 문서, 논문 PDF)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 메모리 최적화 (Mac mini 8GB 기준)
|
|
||||||
```bash
|
|
||||||
# Elasticsearch JVM 설정
|
|
||||||
export ELASTICSEARCH_JAVA_OPTS="-Xms512m -Xmx1g"
|
|
||||||
|
|
||||||
# Redis 메모리 제한
|
|
||||||
export REDIS_MAXMEMORY="256mb"
|
|
||||||
|
|
||||||
# Python 프로세스 최적화
|
|
||||||
export PYTHONOPTIMIZE=1
|
|
||||||
```
|
|
||||||
|
|
||||||
### 검색 성능 최적화
|
|
||||||
- **사전 계산**: 자주 검색되는 조합 캐싱
|
|
||||||
- **인덱스 최적화**: 전문 용어 기반 역색인
|
|
||||||
- **벡터 검색**: BERT 기반 의미 검색
|
|
||||||
- **지역별 샤딩**: 데이터 분산 저장
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 데이터 파이프라인
|
|
||||||
|
|
||||||
### 수집 → 처리 → 저장 → 검색
|
|
||||||
```
|
|
||||||
RSS/API 수집 → NLP 태그 추출 → PostgreSQL 저장 → Elasticsearch 인덱싱 → Redis 캐싱
|
|
||||||
```
|
|
||||||
|
|
||||||
### 실시간 처리
|
|
||||||
- **RSS 모니터링**: 5분마다 새 피드 확인
|
|
||||||
- **논문 동기화**: 일일 1회 학술 DB 스캔
|
|
||||||
- **표준 업데이트**: 주간 공식 사이트 모니터링
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 확장성 고려사항
|
|
||||||
|
|
||||||
### 수평 확장
|
|
||||||
- **마이크로서비스**: 기능별 서비스 분리
|
|
||||||
- **로드 밸런싱**: 검색 서비스 다중 인스턴스
|
|
||||||
- **데이터베이스 샤딩**: 지역/분야별 데이터 분산
|
|
||||||
|
|
||||||
### 성능 모니터링
|
|
||||||
- **메트릭 수집**: 응답 시간, 처리량, 에러율
|
|
||||||
- **알림 시스템**: 임계값 초과 시 자동 알림
|
|
||||||
- **용량 계획**: 데이터 증가율 기반 리소스 계획
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
이 기술 스택은 산업 전문 정보의 특성을 고려하여 선택되었으며, macOS 환경에서의 개발 편의성과 운영 안정성을 모두 고려한 구성입니다.
|
|
||||||
Reference in New Issue
Block a user