4 Commits

Author SHA1 Message Date
9d0e9aa8aa Merge pull request 'feat/post-migration-cleanup' (#6) from feat/post-migration-cleanup into main
Reviewed-on: #6
2026-05-17 14:27:37 +09:00
d9c39a0206 docs(readme,status): CLAUDE.md 기준으로 동기화 (CODE_REVIEW F7)
README.md / STATUS.md가 blog-lab을 운영 중인 18700 포트 컨테이너로
설명하고 insta-lab/personal/packs-lab을 누락했던 문제 정리. CLAUDE.md를
source of truth로 다음을 갱신:

- 컨테이너 표 (11개로 정합화)
- 디렉토리 구조 (insta-lab/personal/packs-lab 추가)
- 빠른 시작 URL 표
- blog-lab 섹션 → insta-lab 파이프라인 설명
- agent-office 표 (InstaAgent + YouTubeResearcher 반영)
- 스케줄러 잡 목록 (09:00 Insta trends, 09:30 Insta extract, 16:30 screener 등)
- DB 표 (insta.db + personal.db + Supabase pack_files 추가)
- .env 예시 (YOUTUBE_DATA_API_KEY, ADMIN_API_KEY, INSTA_LAB_URL 등)
- STATUS 최근 작업: 2026-05-15~17 인스타 + 보안 fix 이력
2026-05-17 14:23:07 +09:00
0f73b6b07d chore(cleanup): post-migration tidying (CODE_REVIEW F8 + 정리 대상)
- stock/app/test_scraper.py 삭제 — 미존재 함수 fetch_overseas_news를
  import하는 untracked 임시 스크립트. 보존 가치 없음 (F8).
- blog-lab/ 디렉토리 잔재 (__pycache__만 남음) 완전 제거. 서비스는
  feat/insta-agent 머지에서 이미 폐기됨.
- .gitignore에 .superpowers/ (스킬 캐시·세션 메타)와 CODE_REVIEW.md
  (임시 리뷰 노트) 추가 — git status 노이즈 차단.
2026-05-17 14:19:13 +09:00
faffca0967 Merge pull request 'feat/security-hardening' (#5) from feat/security-hardening into main
Reviewed-on: #5
2026-05-17 14:00:03 +09:00
3 changed files with 107 additions and 61 deletions

8
.gitignore vendored
View File

@@ -66,3 +66,11 @@ temp/
# Git worktrees # Git worktrees
.worktrees/ .worktrees/
################################
# Local working files
################################
# Superpowers 스킬 캐시·세션 메타
.superpowers/
# 임시 코드 리뷰 노트 (작업 끝나면 폐기 또는 docs/로 이동)
CODE_REVIEW.md

112
README.md
View File

@@ -1,7 +1,7 @@
# web-backend # web-backend
Synology NAS 기반 개인 웹 플랫폼 백엔드 모노레포. Synology NAS 기반 개인 웹 플랫폼 백엔드 모노레포.
로또 분석, 주식 포트폴리오, AI 음악 생성, 블로그 마케팅, 부동산 청약, AI 에이전트 오피스, 여행 앨범 하나의 Docker Compose 스택으로 운영한다. 로또 분석, 주식 포트폴리오, AI 음악 생성, 인스타 카드 피드, 부동산 청약, AI 에이전트 오피스, 여행 앨범, 개인 서비스(포트폴리오·블로그·투두), NAS 자료 다운로드 자동화를 하나의 Docker Compose 스택으로 운영한다.
--- ---
@@ -9,18 +9,20 @@ Synology NAS 기반 개인 웹 플랫폼 백엔드 모노레포.
``` ```
┌──────────────────────────────────────────────────────────────────────┐ ┌──────────────────────────────────────────────────────────────────────┐
lotto-frontend (Nginx:8080) │ │ frontend (Nginx:8080)
│ ├── 정적 SPA 서빙 (React + Vite) │ │ ├── 정적 SPA 서빙 (React + Vite) │
│ └── API 리버스 프록시 │ │ └── API 리버스 프록시 │
│ ├── /api/ → lotto-backend:8000 (로또·블로그·투두) │ ├── /api/ → lotto:8000 (로또)
│ ├── /api/stock/, /trade/ → stock:8000 │ │ ├── /api/stock/, /trade/ → stock:8000 │
│ ├── /api/portfolio → stock:8000 │ │ ├── /api/portfolio → stock:8000 │
│ ├── /api/music/ → music-lab:8000 │ │ ├── /api/music/ → music-lab:8000 │
│ ├── /api/blog-marketing/ → blog-lab:8000 │ │ ├── /api/insta/ → insta-lab:8000 │
│ ├── /api/realestate/ → realestate-lab:8000 │ │ ├── /api/realestate/ → realestate-lab:8000 │
│ ├── /api/agent-office/ → agent-office:8000 (+ WebSocket) │ │ ├── /api/agent-office/ → agent-office:8000 (+ WebSocket) │
│ ├── /api/profile/, /todos, /blog/ → personal:8000 │
│ ├── /api/packs/ → packs-lab:8000 (HMAC + 5GB upload) │
│ ├── /api/travel/ → travel-proxy:8000 │ │ ├── /api/travel/ → travel-proxy:8000 │
│ ├── /media/music/ (nginx 직접 서빙, 생성 오디오) │ ├── /media/music/, /media/videos/ (nginx 직접 서빙, 미디어)
│ ├── /media/travel/… (nginx 직접 서빙, 사진/썸네일) │ │ ├── /media/travel/… (nginx 직접 서빙, 사진/썸네일) │
│ └── /webhook → deployer:9000 │ │ └── /webhook → deployer:9000 │
└──────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────┘
@@ -28,14 +30,16 @@ Synology NAS 기반 개인 웹 플랫폼 백엔드 모노레포.
| 컨테이너 | 포트 | 역할 | | 컨테이너 | 포트 | 역할 |
|---------|------|------| |---------|------|------|
| `lotto-backend` | 18000 | 로또 데이터 수집·분석·추천 + 블로그·투두 API | | `lotto` | 18000 | 로또 데이터 수집·분석·추천 API |
| `stock` | 18500 | 주식 뉴스·AI 요약·KIS 실계좌·포트폴리오·자산 추적 | | `stock` | 18500 | 주식 뉴스·AI 요약·KIS 실계좌·포트폴리오·자산 추적 |
| `music-lab` | 18600 | AI 음악 생성 (Suno + 로컬 MusicGen 듀얼 프로바이더) | | `music-lab` | 18600 | AI 음악 생성 (Suno + 로컬 MusicGen 듀얼 프로바이더) + YouTube 수익화 |
| `blog-lab` | 18700 | 블로그 마케팅 수익화 (키워드→글 생성→리뷰→발행) | | `insta-lab` | 18700 | 인스타 카드 피드 자동 생성 (뉴스→키워드→10페이지 카드, Playwright) |
| `realestate-lab` | 18800 | 청약 공고 자동 수집·프로필 매칭 | | `realestate-lab` | 18800 | 청약 공고 자동 수집·5티어 매칭·신규 매칭 push |
| `agent-office` | 18900 | AI 에이전트 가상 오피스 (WebSocket + 텔레그램 봇) | | `agent-office` | 18900 | AI 에이전트 가상 오피스 (WebSocket + 텔레그램 봇) |
| `personal` | 18850 | 개인 서비스 — 포트폴리오·블로그·투두 통합 |
| `packs-lab` | 18950 | NAS 자료 다운로드 자동화 (DSM 공유 링크 + 5GB 청크 업로드) |
| `travel-proxy` | 19000 | 여행 사진 API + 온디맨드 썸네일 | | `travel-proxy` | 19000 | 여행 사진 API + 온디맨드 썸네일 |
| `lotto-frontend` | 8080 | SPA 서빙 + 리버스 프록시 | | `frontend` | 8080 | SPA 서빙 + 리버스 프록시 |
| `webpage-deployer` | 19010 | Gitea Webhook → 자동 배포 | | `webpage-deployer` | 19010 | Gitea Webhook → 자동 배포 |
--- ---
@@ -44,12 +48,14 @@ Synology NAS 기반 개인 웹 플랫폼 백엔드 모노레포.
``` ```
web-backend/ web-backend/
├── backend/ # lotto-backend (로또·블로그·투두) ├── lotto/ # 로또 추천·통계·시뮬레이션
├── stock/ # 주식·포트폴리오 ├── stock/ # 주식·포트폴리오·KIS 연동
├── music-lab/ # AI 음악 생성 ├── music-lab/ # AI 음악 생성 + YouTube 수익화
├── blog-lab/ # 블로그 마케팅 파이프라인 ├── insta-lab/ # 인스타 카드 피드 자동 생성 (Playwright)
├── realestate-lab/ # 청약 자동 수집·매칭 ├── realestate-lab/ # 청약 자동 수집·5티어 매칭
├── agent-office/ # AI 에이전트 오피스 (WS + 텔레그램) ├── agent-office/ # AI 에이전트 오피스 (WS + 텔레그램)
├── personal/ # 포트폴리오·블로그·투두 통합
├── packs-lab/ # NAS 자료 다운로드 자동화 (HMAC + Supabase)
├── travel-proxy/ # 여행 사진 + 썸네일 ├── travel-proxy/ # 여행 사진 + 썸네일
├── deployer/ # Gitea Webhook 수신 → 자동 배포 ├── deployer/ # Gitea Webhook 수신 → 자동 배포
├── nginx/default.conf # 리버스 프록시 + SPA + 캐시 ├── nginx/default.conf # 리버스 프록시 + SPA + 캐시
@@ -74,12 +80,14 @@ curl http://localhost:18500/health
| 서비스 | 로컬 URL | | 서비스 | 로컬 URL |
|--------|----------| |--------|----------|
| Frontend + API | http://localhost:8080 | | Frontend + API | http://localhost:8080 |
| lotto-backend | http://localhost:18000 | | lotto | http://localhost:18000 |
| stock | http://localhost:18500 | | stock | http://localhost:18500 |
| music-lab | http://localhost:18600 | | music-lab | http://localhost:18600 |
| blog-lab | http://localhost:18700 | | insta-lab | http://localhost:18700 |
| realestate-lab | http://localhost:18800 | | realestate-lab | http://localhost:18800 |
| personal | http://localhost:18850 |
| agent-office | http://localhost:18900 | | agent-office | http://localhost:18900 |
| packs-lab | http://localhost:18950 |
| travel-proxy | http://localhost:19000 | | travel-proxy | http://localhost:19000 |
--- ---
@@ -123,20 +131,23 @@ curl http://localhost:18500/health
- **라이브러리**: 생성 파일은 `/app/data/music/`에 저장되고 Nginx가 `/media/music/`으로 직접 서빙 - **라이브러리**: 생성 파일은 `/app/data/music/`에 저장되고 Nginx가 `/media/music/`으로 직접 서빙
- **가사 도구**: 저장·편집·타임스탬프 기반 가라오케 동기 - **가사 도구**: 저장·편집·타임스탬프 기반 가라오케 동기
### 4. blog-lab (`/api/blog-marketing/`) ### 4. insta-lab (`/api/insta/`)
블로그 마케팅 수익화 4단계 파이프라인 (`draft → marketed → reviewed → published`). 인스타그램 카드 피드 자동 생성 — 뉴스 모니터링 → 키워드 추출 → 10페이지 카드 카피·PNG 렌더 → 텔레그램 푸시 → 사용자 수동 업로드.
``` ```
리서치(Naver Search + 상위 블로그 본문 크롤링) NAVER 뉴스 + YouTube 인기 (외부 트렌드)
작가(AI 초안 생성) 카테고리별 빈도 + Claude Haiku 정제 → 트렌딩 키워드
마케터(전환율 강화 + 브랜드 링크 삽입) 사용자가 키워드 선택
평가자(6기준×10점, 42/60 통과 시 published) Claude Sonnet으로 10페이지 카피 추론 (커버 1 + 본문 8 + CTA 1)
→ Jinja2 + Playwright 1080×1350 PNG 10장 렌더
→ 텔레그램 미디어 그룹 + 추천 캡션·해시태그
``` ```
- **AI 엔진**: Claude API (`claude-sonnet-4-20250514`) - **AI 엔진**: Claude Sonnet (카피) + Claude Haiku (키워드 분류)
- **키워드 분석**: 네이버 검색(블로그+쇼핑) API + 경쟁도/기회 점수 - **데이터 소스**: NAVER 뉴스 검색 + YouTube Data API v3 mostPopular(KR)
- **수익 추적**: 포스트별 월간 클릭/구매/수익 기록 - **카테고리 가중치**: 사용자가 economy/psychology/celebrity 등 카테고리별 가중치 설정 → 자동 추출 비율에 반영
- **카드 디자인**: `insta-lab/app/templates/default/card.html.j2` — 사용자가 자유 수정 (Tailwind 등)
- **프롬프트 템플릿**: DB에 저장 → 코드 배포 없이 수정 가능 - **프롬프트 템플릿**: DB에 저장 → 코드 배포 없이 수정 가능
### 5. realestate-lab (`/api/realestate/`) ### 5. realestate-lab (`/api/realestate/`)
@@ -152,7 +163,7 @@ curl http://localhost:18500/health
AI 에이전트 가상 오피스 — 2D 픽셀아트 사무실에서 4명의 에이전트가 실제 작업을 수행한다. AI 에이전트 가상 오피스 — 2D 픽셀아트 사무실에서 4명의 에이전트가 실제 작업을 수행한다.
- **아키텍처**: stock / music-lab / blog-lab / realestate-lab 기존 API를 서비스 프록시로 호출 (직접 DB 접근 없음) - **아키텍처**: stock / music-lab / insta-lab / realestate-lab 기존 API를 서비스 프록시로 호출 (직접 DB 접근 없음)
- **FSM 상태**: `idle → working → waiting(승인 대기) → reporting → break` - **FSM 상태**: `idle → working → waiting(승인 대기) → reporting → break`
- **실시간 동기화**: WebSocket `/api/agent-office/ws` (init, agent_state, task_complete, command_result) - **실시간 동기화**: WebSocket `/api/agent-office/ws` (init, agent_state, task_complete, command_result)
- **텔레그램 연동**: 양방향 알림 + 인라인 키보드 승인 - **텔레그램 연동**: 양방향 알림 + 인라인 키보드 승인
@@ -165,22 +176,28 @@ AI 에이전트 가상 오피스 — 2D 픽셀아트 사무실에서 4명의 에
|---------|--------|-----|----------| |---------|--------|-----|----------|
| 📈 **주식 트레이더** (`stock`) | 08:00 매일 | — | 뉴스 요약 (LLM) → 텔레그램 아침 브리핑, 종목 알람 등록 | | 📈 **주식 트레이더** (`stock`) | 08:00 매일 | — | 뉴스 요약 (LLM) → 텔레그램 아침 브리핑, 종목 알람 등록 |
| 🎵 **음악 프로듀서** (`music`) | 수동 트리거 | ✅ 작곡 | 프롬프트 수신 → 승인 → Suno API 작곡 → 트랙 푸시 | | 🎵 **음악 프로듀서** (`music`) | 수동 트리거 | ✅ 작곡 | 프롬프트 수신 → 승인 → Suno API 작곡 → 트랙 푸시 |
| ✍️ **블로그 마케** (`blog`) | 10:00 매일 | ✅ 발행 | 트렌드 키워드 1개 선택 → 리서치→작가→마케터→평가 자동 실행 → 점수·본문을 텔레그램 승인 요청 → 승인 시 `published` 전환, 거절 시 재생성 | | 🎴 **인스타 큐레이** (`insta`) | 09:00 / 09:30 매일 | — | 09:00 외부 트렌드(NAVER + YouTube) 수집 → 09:30 가중치 기반 키워드 추출 → 텔레그램 후보 5개씩 카테고리당 인라인 버튼 푸시 → 사용자 선택 시 카드 10장 미디어 그룹 |
| 🏢 **청약 애널리스트** (`realestate`) | 09:15 매일 | — | realestate-lab 수집 트리거 → 신규 매칭 상위 5건 + 대시보드 요약을 텔레그램 리포트 (읽음 처리 자동) | | 🏢 **청약 애널리스트** (`realestate`) | realestate-lab push trigger | — | realestate-lab이 신규 매칭 발견 시 push → 인라인 [북마크] 버튼 포함 텔레그램 알림 |
| 🎬 **YouTube 리서처** (`youtube`) | 09:00 매일 | — | 한국 YouTube 트렌딩 + Google Trends + Billboard → music-lab market_trends push |
#### 에이전트별 명령 #### 에이전트별 명령
**Stock**`fetch_news`, `list_alerts`, `add_alert`, `test_telegram` **Stock**`fetch_news`, `list_alerts`, `add_alert`, `test_telegram`
**Music**`compose` (승인 필요), `credits` **Music**`compose` (승인 필요), `credits`
**Blog**`research {keyword}`, `add_trend_keyword`, `list_trend_keywords` **Insta**`extract`, `render <keyword_id>`, `collect_trends`
**Realestate**`fetch_matches`, `dashboard` **Realestate**`fetch_matches`, `dashboard`
**YouTube**`research {countries: [...]}`
#### 스케줄러 잡 #### 스케줄러 잡
- 07:00 월요일 — Lotto: AI 큐레이터 브리핑 (5세트 + 내러티브) - 07:00 월요일 — Lotto: AI 큐레이터 브리핑 (5세트 + 내러티브)
- 07:30 — Stock: 뉴스 요약 - 07:30 — Stock: 뉴스 요약
- 09:15 — Realestate: 매칭 리포트 - 08:00 평일 — Stock: AI 뉴스 sentiment 분석
- 10:00 — Blog: 자동 파이프라인 (리서치→생성→리뷰→승인 대기) - 09:00 — YouTube: 한국 트렌딩 수집
- 09:00 — Insta: 외부 트렌드 수집 (NAVER 인기 + YouTube mostPopular)
- 09:30 — Insta: 키워드 추출 (가중치 적용) + 텔레그램 후보 푸시
- 15:40 평일 — Stock: 총 자산 스냅샷
- 16:30 평일 — Stock: 스크리너 실행
- 60초 interval — 유휴 에이전트 휴식 체크 - 60초 interval — 유휴 에이전트 휴식 체크
### 7. travel-proxy (`/api/travel/`) ### 7. travel-proxy (`/api/travel/`)
@@ -265,13 +282,15 @@ git push → Gitea → X-Gitea-Signature (HMAC SHA256)
| DB | 소유 서비스 | 주요 테이블 | | DB | 소유 서비스 | 주요 테이블 |
|----|------------|-----------| |----|------------|-----------|
| `lotto.db` | lotto-backend | draws, recommendations, simulation_runs/candidates, best_picks, purchase_history, strategy_performance/weights, weekly_reports, lotto_briefings, todos, blog_posts | | `lotto.db` | lotto | draws, recommendations, simulation_runs/candidates, best_picks, purchase_history, strategy_performance/weights, weekly_reports, lotto_briefings |
| `stock.db` | stock | articles, portfolio, broker_cash, asset_snapshots, sell_history | | `stock.db` | stock | articles, portfolio, broker_cash, asset_snapshots, sell_history |
| `music.db` | music-lab | music_tasks, music_library (provider, lyrics, image_url, suno_id, file_hash, cover_images, wav_url, video_url, stem_urls) | | `music.db` | music-lab | music_tasks, music_library (provider, lyrics, image_url, suno_id, file_hash, cover_images, wav_url, video_url, stem_urls), video_projects, revenue_records, market_trends, trend_reports |
| `blog_marketing.db` | blog-lab | keyword_analyses, blog_posts, brand_links, commissions, generation_tasks, prompt_templates | | `insta.db` | insta-lab | news_articles, trending_keywords (source 컬럼), card_slates, card_assets, generation_tasks, prompt_templates, account_preferences |
| `realestate.db` | realestate-lab | announcements, announcement_models, user_profile, match_results, collect_log | | `realestate.db` | realestate-lab | announcements, announcement_models, user_profile, match_results, collect_log |
| `agent_office.db` | agent-office | agent_config, agent_tasks, agent_logs, telegram_state, conversation_messages | | `agent_office.db` | agent-office | agent_config, agent_tasks, agent_logs, telegram_state, conversation_messages |
| `personal.db` | personal | profile, careers, projects, skills, introductions, todos, blog_posts |
| `travel.db` | travel-proxy | photos (album, filename, mtime, has_thumb), album_covers | | `travel.db` | travel-proxy | photos (album, filename, mtime, has_thumb), album_covers |
| `pack_files` (외부 Supabase) | packs-lab | filename, host_path, mime, byte_size, sha256, deleted_at |
--- ---
@@ -292,33 +311,50 @@ PGID=1000
WINDOWS_AI_SERVER_URL=http://192.168.45.59:8000 WINDOWS_AI_SERVER_URL=http://192.168.45.59:8000
WEBHOOK_SECRET=your_secret_here WEBHOOK_SECRET=your_secret_here
# LLM (stock, blog-lab, agent-office 공통) # LLM (stock, insta-lab, agent-office 공통)
ANTHROPIC_API_KEY=sk-ant-... ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-haiku-4-5-20251001 ANTHROPIC_MODEL=claude-haiku-4-5-20251001
LLM_PROVIDER=claude # claude | ollama LLM_PROVIDER=claude # claude | ollama
OLLAMA_URL=http://192.168.45.59:11435 OLLAMA_URL=http://192.168.45.59:11435
OLLAMA_MODEL=qwen3:14b OLLAMA_MODEL=qwen3:14b
# stock admin protection (CODE_REVIEW F2)
ADMIN_API_KEY=
ALLOW_UNAUTHENTICATED_ADMIN=false
# music-lab # music-lab
SUNO_API_KEY= SUNO_API_KEY=
MUSIC_AI_SERVER_URL= MUSIC_AI_SERVER_URL=
MUSIC_MEDIA_BASE=/media/music MUSIC_MEDIA_BASE=/media/music
# blog-lab # insta-lab + agent-office (NAVER 검색 + YouTube Data API 공유)
NAVER_CLIENT_ID= NAVER_CLIENT_ID=
NAVER_CLIENT_SECRET= NAVER_CLIENT_SECRET=
YOUTUBE_DATA_API_KEY=
# realestate-lab # realestate-lab
DATA_GO_KR_API_KEY= DATA_GO_KR_API_KEY=
# packs-lab (DSM + Supabase)
DSM_HOST=
DSM_USER=
DSM_PASS=
BACKEND_HMAC_SECRET=
SUPABASE_URL=
SUPABASE_SERVICE_KEY=
PACK_HOST_DIR=/docker/webpage/media/packs # shared folder 시점 (CLAUDE.md F5)
# agent-office # agent-office
TELEGRAM_BOT_TOKEN= TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID= TELEGRAM_CHAT_ID=
TELEGRAM_WEBHOOK_URL= TELEGRAM_WEBHOOK_URL=
STOCK_URL=http://stock:8000 STOCK_URL=http://stock:8000
MUSIC_LAB_URL=http://music-lab:8000 MUSIC_LAB_URL=http://music-lab:8000
BLOG_LAB_URL=http://blog-lab:8000 INSTA_LAB_URL=http://insta-lab:8000
REALESTATE_LAB_URL=http://realestate-lab:8000 REALESTATE_LAB_URL=http://realestate-lab:8000
# personal (포트폴리오 편집 인증)
PORTFOLIO_EDIT_PASSWORD=
``` ```
--- ---

View File

@@ -1,40 +1,42 @@
# web-backend — 구현 현황 & 로드맵 # web-backend — 구현 현황 & 로드맵
> 최종 갱신: 2026-05-07 > 최종 갱신: 2026-05-17
> 자세한 서비스·환경변수·DB 표는 [CLAUDE.md](./CLAUDE.md), 설계는 `docs/superpowers/specs/`, 실행 계획은 `docs/superpowers/plans/` 참조. > 자세한 서비스·환경변수·DB 표는 [CLAUDE.md](./CLAUDE.md), 설계는 `docs/superpowers/specs/`, 실행 계획은 `docs/superpowers/plans/` 참조.
--- ---
## 1. 서비스 구현 현황 ## 1. 서비스 구현 현황
### 1-1. 운영 중인 컨테이너 (10개) ### 1-1. 운영 중인 컨테이너 (11개)
| 서비스 | 포트 | 상태 | 핵심 기능 | | 서비스 | 포트 | 상태 | 핵심 기능 |
|--------|------|------|-----------| |--------|------|------|-----------|
| `lotto-backend` | 18000 | ✅ | 로또 추천·통계·리포트·구매내역 + 블로그·투두 | | `lotto` | 18000 | ✅ | 로또 추천·통계·리포트·구매내역·AI 큐레이터 |
| `stock` | 18500 | ✅ | 주식 뉴스·지수·트레이딩·포트폴리오·자산 스냅샷 | | `stock` | 18500 | ✅ | 주식 뉴스·지수·트레이딩·포트폴리오·자산 스냅샷·스크리너 |
| `music-lab` | 18600 | ✅ | Suno + MusicGen + YouTube 수익화 + 컴파일 | | `music-lab` | 18600 | ✅ | Suno + MusicGen + YouTube 수익화 + 컴파일 |
| `blog-lab` | 18700 | ✅ | 블로그 마케팅 수익화 파이프라인 | | `insta-lab` | 18700 | ✅ | 인스타 카드 피드 자동 생성 (NAVER + YouTube 트렌드 → 10페이지 카드, Playwright) |
| `realestate-lab` | 18800 | ✅ | 청약 수집·5티어 매칭·매칭 알림 | | `realestate-lab` | 18800 | ✅ | 청약 수집·5티어 매칭·매칭 알림 push |
| `agent-office` | 18900 | ✅ | AI 에이전트 (WebSocket + 텔레그램 + YouTubeResearcher) | | `personal` | 18850 | ✅ | 포트폴리오·블로그·투두 통합 (개인 서비스) |
| `packs-lab` | 18950 | ✅ | NAS 자료 다운로드 자동화 (HMAC + Supabase) — 2026-05-05 | | `agent-office` | 18900 | ✅ | AI 에이전트 (WebSocket + 텔레그램 + InstaAgent + YouTubeResearcher) |
| `packs-lab` | 18950 | ✅ | NAS 자료 다운로드 자동화 (HMAC + Supabase + 5GB chunked upload) |
| `travel-proxy` | 19000 | ✅ | 여행 사진 API + 썸네일 + 지역 관리 | | `travel-proxy` | 19000 | ✅ | 여행 사진 API + 썸네일 + 지역 관리 |
| `nginx` | 8080 | ✅ | SPA + 리버스 프록시 (5GB body limit) | | `frontend` (nginx) | 8080 | ✅ | SPA + 리버스 프록시 (5GB body limit, 인스타 라우팅 포함) |
| `webpage-deployer` | 19010 | ✅ | Gitea Webhook 자동 배포 | | `webpage-deployer` | 19010 | ✅ | Gitea Webhook 자동 배포 (BUILDKIT timeout 600s, healthcheck via docker inspect) |
### 1-2. 최근 큰 작업 (2026-04 ~ 05) ### 1-2. 최근 큰 작업 (2026-05)
| 시기 | 영역 | 핵심 | | 시기 | 영역 | 핵심 |
|------|------|------| |------|------|------|
| 2026-05-17 | 보안 / 정합성 | CODE_REVIEW F1 (packs-lab path traversal `startswith→relative_to`) + F2 (stock admin auth 503 거부) + F4 (portfolio total_buy 수량 곱산) |
| 2026-05-17 | insta-lab | Google Trends API 폐기 대응 → YouTube Data API v3로 source 교체. trend_collector 재작성 |
| 2026-05-16 | insta-lab | Trends 탭 추가 — 외부 트렌드 수집 (NAVER 인기 + YouTube) + 카테고리 가중치 (`account_preferences`) + 가중치 기반 키워드 추출 |
| 2026-05-15 | insta-lab | blog-lab 폐기 → insta-lab 신설. 뉴스 모니터링 → 키워드 추출 → 10페이지 카드 카피·PNG → 텔레그램 푸시 → 수동 인스타 업로드 파이프라인 |
| 2026-05-05 | packs-lab | sign-link / upload / list / delete + admin mint-token + 5GB nginx body limit + Supabase DDL | | 2026-05-05 | packs-lab | sign-link / upload / list / delete + admin mint-token + 5GB nginx body limit + Supabase DDL |
| 2026-05-01~06 | music-lab | YouTube 수익화 백엔드 (market_trends·trend_reports DB + 5개 API) + 다중 트랙 FFmpeg concat MP4 | | 2026-05-01~06 | music-lab | YouTube 수익화 백엔드 (market_trends·trend_reports DB + 5개 API) + 다중 트랙 FFmpeg concat MP4 |
| 2026-04-28 | realestate-lab | targeting enhancement (5티어 매칭·5축 점수·알림 대상 카운트) | | 2026-04-28 | realestate-lab | targeting enhancement (5티어 매칭·5축 점수·알림 대상 카운트, realestate-lab push → agent-office RealestateAgent) |
| 2026-04-27 | personal | personal 서비스 분리 마이그레이션 (블로그·투두·포트폴리오 인증) | | 2026-04-27 | personal | personal 서비스 분리 마이그레이션 (블로그·투두·포트폴리오 인증) |
| 2026-04-27 | agent-office | v2 — youtube_researcher (YouTube API + pytrends + Billboard) + 알림 | | 2026-04-27 | agent-office | v2 — youtube_researcher (YouTube API + pytrends + Billboard) + 알림 |
| 2026-04-24 | travel-proxy | 갤러리 리디자인 + 성능 개선 (썸네일/페이지네이션) | | 2026-04-15 | lotto | AI 큐레이터 (Claude 기반 주간 브리핑 자동 생성) |
| 2026-04-15 | lotto-backend | AI 큐레이터 (Claude 기반 주간 브리핑 자동 생성) |
| 2026-04-08 | music-lab | Suno enhancement + MusicGen 통합 |
| 2026-04-06 | blog-lab | 마케팅 파이프라인 (research → generate → market → review) |
### 1-3. 인프라 / DX ### 1-3. 인프라 / DX