diff --git a/CLAUDE.md b/CLAUDE.md index 2506aca..c616977 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -31,7 +31,7 @@ Synology NAS 기반의 개인 웹 플랫폼 백엔드 모노레포. ``` /volume1 ├── docker/webpage/ # 운영 런타임 (Docker Compose 실행 위치) -│ ├── backend/ # lotto-backend 소스 (rsync 동기화) +│ ├── lotto/ # lotto 소스 (rsync 동기화) │ ├── stock-lab/ # stock-lab 소스 (rsync 동기화) │ ├── travel-proxy/ # travel-proxy 소스 (rsync 동기화) │ ├── deployer/ # deployer 소스 (rsync 동기화) @@ -53,7 +53,7 @@ Synology NAS 기반의 개인 웹 플랫폼 백엔드 모노레포. | 컨테이너 | 포트 | 역할 | |---------|------|------| -| `lotto-backend` | 18000 | 로또 데이터 수집·분석·추천 API | +| `lotto` | 18000 | 로또 데이터 수집·분석·추천 API | | `stock-lab` | 18500 | 주식 뉴스·AI 분석·KIS API 연동 | | `music-lab` | 18600 | AI 음악 생성·라이브러리 관리 API | | `blog-lab` | 18700 | 블로그 마케팅 수익화 API | @@ -61,7 +61,7 @@ Synology NAS 기반의 개인 웹 플랫폼 백엔드 모노레포. | `agent-office` | 18900 | AI 에이전트 오피스 (실시간 WebSocket + 텔레그램 연동) | | `personal` | 18850 | 개인 서비스 (포트폴리오·블로그·투두 통합) | | `travel-proxy` | 19000 | 여행 사진 API + 썸네일 생성 | -| `lotto-frontend` (nginx) | 8080 | 정적 SPA 서빙 + API 리버스 프록시 | +| `frontend` (nginx) | 8080 | 정적 SPA 서빙 + API 리버스 프록시 | | `webpage-deployer` | 19010 | Gitea Webhook 수신 → 자동 배포 | --- @@ -70,7 +70,7 @@ Synology NAS 기반의 개인 웹 플랫폼 백엔드 모노레포. | 경로 | 프록시 대상 | 비고 | |------|------------|------| -| `/api/` | `lotto-backend:8000` | lotto API (기본) | +| `/api/` | `lotto:8000` | lotto API (기본) | | `/api/travel/` | `travel-proxy:8000` | travel API | | `/api/stock/` | `stock-lab:8000` | stock API | | `/api/trade/` | `stock-lab:8000` | KIS 실계좌 API | @@ -139,7 +139,7 @@ docker compose up -d ## 9. 서비스별 핵심 정보 -### lotto-lab (backend/) +### lotto-lab (lotto/) - DB: `/app/data/lotto.db` - 데이터 소스: `smok95.github.io/lotto/results/` - 파일 구조: `main.py`, `db.py`, `recommender.py`, `collector.py`, `checker.py`, `generator.py`, `analyzer.py`, `utils.py`, `purchase_manager.py`, `strategy_evolver.py` @@ -454,7 +454,7 @@ docker compose up -d - `CONVERSATION_MODEL`: 대화 모델 (기본 `claude-haiku-4-5-20251001`) - `CONVERSATION_HISTORY_LIMIT`: 이력 주입 수 (기본 20) - `CONVERSATION_RATE_PER_MIN`: 채팅당 분당 최대 메시지 (기본 6) -- `LOTTO_BACKEND_URL`: 기본 `http://lotto-backend:8000` +- `LOTTO_BACKEND_URL`: 기본 `http://lotto:8000` - `LOTTO_CURATOR_MODEL`: 기본 `claude-sonnet-4-5` **텔레그램 자연어 대화 (옵션 B)** diff --git a/agent-office/app/config.py b/agent-office/app/config.py index fccfbdf..2606f52 100644 --- a/agent-office/app/config.py +++ b/agent-office/app/config.py @@ -32,5 +32,5 @@ BREAK_DURATION_MIN = int(os.getenv("BREAK_DURATION_MIN", "60")) # 1 min BREAK_DURATION_MAX = int(os.getenv("BREAK_DURATION_MAX", "180")) # 3 min # Lotto Curator -LOTTO_BACKEND_URL = os.getenv("LOTTO_BACKEND_URL", "http://lotto-backend:8000") +LOTTO_BACKEND_URL = os.getenv("LOTTO_BACKEND_URL", "http://lotto:8000") LOTTO_CURATOR_MODEL = os.getenv("LOTTO_CURATOR_MODEL", "claude-sonnet-4-5") diff --git a/docker-compose.yml b/docker-compose.yml index f402203..6cfc53a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,12 @@ name: webpage services: - backend: + lotto: build: - context: ./backend + context: ./lotto args: APP_VERSION: ${APP_VERSION:-dev} - container_name: lotto-backend + container_name: lotto restart: unless-stopped ports: - "18000:8000" @@ -131,7 +131,7 @@ services: - TELEGRAM_WEBHOOK_URL=${TELEGRAM_WEBHOOK_URL:-} - TELEGRAM_WIFE_CHAT_ID=${TELEGRAM_WIFE_CHAT_ID:-} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} - - LOTTO_BACKEND_URL=${LOTTO_BACKEND_URL:-http://lotto-backend:8000} + - LOTTO_BACKEND_URL=${LOTTO_BACKEND_URL:-http://lotto:8000} - LOTTO_CURATOR_MODEL=${LOTTO_CURATOR_MODEL:-claude-sonnet-4-5} - CONVERSATION_MODEL=${CONVERSATION_MODEL:-claude-haiku-4-5-20251001} - CONVERSATION_HISTORY_LIMIT=${CONVERSATION_HISTORY_LIMIT:-20} @@ -193,7 +193,7 @@ services: frontend: image: nginx:alpine - container_name: lotto-frontend + container_name: frontend restart: unless-stopped depends_on: - music-lab diff --git a/backend/.dockerignore b/lotto/.dockerignore similarity index 100% rename from backend/.dockerignore rename to lotto/.dockerignore diff --git a/backend/Dockerfile b/lotto/Dockerfile similarity index 100% rename from backend/Dockerfile rename to lotto/Dockerfile diff --git a/backend/app/analyzer.py b/lotto/app/analyzer.py similarity index 100% rename from backend/app/analyzer.py rename to lotto/app/analyzer.py diff --git a/backend/app/checker.py b/lotto/app/checker.py similarity index 100% rename from backend/app/checker.py rename to lotto/app/checker.py diff --git a/backend/app/collector.py b/lotto/app/collector.py similarity index 100% rename from backend/app/collector.py rename to lotto/app/collector.py diff --git a/backend/app/curator_helpers.py b/lotto/app/curator_helpers.py similarity index 100% rename from backend/app/curator_helpers.py rename to lotto/app/curator_helpers.py diff --git a/backend/app/db.py b/lotto/app/db.py similarity index 95% rename from backend/app/db.py rename to lotto/app/db.py index a170662..f12b188 100644 --- a/backend/app/db.py +++ b/lotto/app/db.py @@ -143,44 +143,6 @@ def init_db() -> None: "ON best_picks(is_active, score_total DESC);" ) - # ── todos 테이블 ─────────────────────────────────────────────────────── - conn.execute( - """ - CREATE TABLE IF NOT EXISTS todos ( - id TEXT PRIMARY KEY - DEFAULT (lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2)))), - title TEXT NOT NULL, - description TEXT, - status TEXT NOT NULL DEFAULT 'todo' - CHECK(status IN ('todo','in_progress','done')), - created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), - updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')) - ); - """ - ) - conn.execute( - "CREATE INDEX IF NOT EXISTS idx_todos_created ON todos(created_at DESC);" - ) - - # ── blog_posts 테이블 ────────────────────────────────────────────────── - conn.execute( - """ - CREATE TABLE IF NOT EXISTS blog_posts ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - title TEXT NOT NULL, - body TEXT NOT NULL DEFAULT '', - excerpt TEXT NOT NULL DEFAULT '', - tags TEXT NOT NULL DEFAULT '[]', - date TEXT NOT NULL DEFAULT (date('now','localtime')), - created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), - updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')) - ); - """ - ) - conn.execute( - "CREATE INDEX IF NOT EXISTS idx_blog_date ON blog_posts(date DESC);" - ) - # ── purchase_history 테이블 ──────────────────────────────────────────── conn.execute( """ diff --git a/backend/app/generator.py b/lotto/app/generator.py similarity index 100% rename from backend/app/generator.py rename to lotto/app/generator.py diff --git a/backend/app/main.py b/lotto/app/main.py similarity index 100% rename from backend/app/main.py rename to lotto/app/main.py diff --git a/backend/app/purchase_manager.py b/lotto/app/purchase_manager.py similarity index 100% rename from backend/app/purchase_manager.py rename to lotto/app/purchase_manager.py diff --git a/backend/app/recommender.py b/lotto/app/recommender.py similarity index 100% rename from backend/app/recommender.py rename to lotto/app/recommender.py diff --git a/backend/app/requirements.txt b/lotto/app/requirements.txt similarity index 100% rename from backend/app/requirements.txt rename to lotto/app/requirements.txt diff --git a/backend/app/routers/__init__.py b/lotto/app/routers/__init__.py similarity index 100% rename from backend/app/routers/__init__.py rename to lotto/app/routers/__init__.py diff --git a/backend/app/routers/briefing.py b/lotto/app/routers/briefing.py similarity index 100% rename from backend/app/routers/briefing.py rename to lotto/app/routers/briefing.py diff --git a/backend/app/routers/curator.py b/lotto/app/routers/curator.py similarity index 100% rename from backend/app/routers/curator.py rename to lotto/app/routers/curator.py diff --git a/backend/app/strategy_evolver.py b/lotto/app/strategy_evolver.py similarity index 100% rename from backend/app/strategy_evolver.py rename to lotto/app/strategy_evolver.py diff --git a/backend/app/utils.py b/lotto/app/utils.py similarity index 100% rename from backend/app/utils.py rename to lotto/app/utils.py diff --git a/backend/tests/test_integration.py b/lotto/tests/test_integration.py similarity index 100% rename from backend/tests/test_integration.py rename to lotto/tests/test_integration.py diff --git a/backend/tests/test_purchase_manager.py b/lotto/tests/test_purchase_manager.py similarity index 100% rename from backend/tests/test_purchase_manager.py rename to lotto/tests/test_purchase_manager.py diff --git a/backend/tests/test_strategy_evolver.py b/lotto/tests/test_strategy_evolver.py similarity index 100% rename from backend/tests/test_strategy_evolver.py rename to lotto/tests/test_strategy_evolver.py diff --git a/nginx/default.conf b/nginx/default.conf index e9fe0bf..a3d428d 100644 --- a/nginx/default.conf +++ b/nginx/default.conf @@ -204,7 +204,7 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://backend:8000; + proxy_pass http://lotto:8000; } # Fear & Greed Index (CNN 공개 API) diff --git a/scripts/deploy-nas.sh b/scripts/deploy-nas.sh index f186c57..12321b4 100644 --- a/scripts/deploy-nas.sh +++ b/scripts/deploy-nas.sh @@ -2,7 +2,7 @@ set -euo pipefail # ── 서비스 목록 (한 곳에서만 관리) ── -SERVICES="backend travel-proxy deployer stock-lab music-lab blog-lab realestate-lab agent-office personal nginx scripts" +SERVICES="lotto travel-proxy deployer stock-lab music-lab blog-lab realestate-lab agent-office personal nginx scripts" # 1. 자동 감지: Docker 컨테이너 내부인가? if [ -d "/repo" ] && [ -d "/runtime" ]; then diff --git a/scripts/deploy.sh b/scripts/deploy.sh index b07a8d7..25064cc 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -7,11 +7,11 @@ flock -n 200 || { echo "Deploy already running, skipping"; exit 0; } # ── 서비스 목록 (한 곳에서만 관리) ── # docker compose 서비스명 (deployer 제외 — 자기 자신을 재빌드하면 스크립트 중단) -BUILD_TARGETS="backend travel-proxy stock-lab music-lab blog-lab realestate-lab agent-office personal frontend" +BUILD_TARGETS="lotto travel-proxy stock-lab music-lab blog-lab realestate-lab agent-office personal frontend" # 컨테이너 이름 (고아 정리용) -CONTAINER_NAMES="lotto-backend stock-lab music-lab blog-lab realestate-lab agent-office personal travel-proxy lotto-frontend" +CONTAINER_NAMES="lotto stock-lab music-lab blog-lab realestate-lab agent-office personal travel-proxy frontend" # 헬스체크 대상 -HEALTH_ENDPOINTS="backend stock-lab travel-proxy music-lab blog-lab realestate-lab agent-office personal" +HEALTH_ENDPOINTS="lotto stock-lab travel-proxy music-lab blog-lab realestate-lab agent-office personal" # data 디렉토리 DATA_DIRS="music stock blog realestate agent-office personal" @@ -89,7 +89,7 @@ done # 3) 재빌드 및 시작 docker compose up -d --build $BUILD_TARGETS -docker exec lotto-frontend nginx -s reload 2>/dev/null || true +docker exec frontend nginx -s reload 2>/dev/null || true # ── 배포 후 헬스체크 ── echo "Waiting for services to start..."