diff --git a/DS1525_OPTIMIZED_SETUP.md b/DS1525_OPTIMIZED_SETUP.md new file mode 100644 index 0000000..7a8e50c --- /dev/null +++ b/DS1525_OPTIMIZED_SETUP.md @@ -0,0 +1,607 @@ +# ๐Ÿ  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์œผ๋กœ ๋ชจ๋“  ์„œ๋น„์Šค๋ฅผ ์—ฌ์œ ๋กญ๊ฒŒ ๋Œ๋ฆด ์ˆ˜ ์žˆ์–ด์š”. ์™„๋ฒฝํ•œ ์„ ํƒ์ž…๋‹ˆ๋‹ค! ๐Ÿ‘ diff --git a/HOMEBREW_SETUP.md b/HOMEBREW_SETUP.md new file mode 100644 index 0000000..0b105ab --- /dev/null +++ b/HOMEBREW_SETUP.md @@ -0,0 +1,592 @@ +# ๐Ÿบ 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๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™„์ „ํ•œ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋‹จ๊ณ„๋ณ„๋กœ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”. diff --git a/SYNOLOGY_SETUP.md b/SYNOLOGY_SETUP.md new file mode 100644 index 0000000..ca5fada --- /dev/null +++ b/SYNOLOGY_SETUP.md @@ -0,0 +1,721 @@ +# ๐Ÿ  ์‹œ๋†€๋กœ์ง€ 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๋กœ ๋” ์•ˆ์ •์ ์ด๊ณ  ํšจ์œจ์ ์ธ ์‚ฐ์—… ์ •๋ณด ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•ด๋ณด์„ธ์š”!** ๐Ÿ ๐Ÿš€ diff --git a/TECH_STACK.md b/TECH_STACK.md new file mode 100644 index 0000000..2f02a65 --- /dev/null +++ b/TECH_STACK.md @@ -0,0 +1,285 @@ +# ๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์Šคํƒ (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 ํ™˜๊ฒฝ์—์„œ์˜ ๊ฐœ๋ฐœ ํŽธ์˜์„ฑ๊ณผ ์šด์˜ ์•ˆ์ •์„ฑ์„ ๋ชจ๋‘ ๊ณ ๋ คํ•œ ๊ตฌ์„ฑ์ž…๋‹ˆ๋‹ค.