From 5ae841cf27518e892fb4cc25313305be30ec2be4 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Sat, 6 Sep 2025 14:01:10 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B3=84=ED=9A=8D=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EA=B2=B0=EA=B3=BC=20=EB=B0=98=EC=98=81=20?= =?UTF-8?q?=EB=B0=8F=2087=EC=A4=84=EB=A1=9C=20=EC=95=95=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rb8001 DM 전송 및 스케줄링 현황 반영 - company-x_hompage 코드 100% 재사용 가능 확인 - ProcessLock 완전 구현 상태 명시 - Nginx 설정 예시 코드 추가 - 현실적 일정으로 수정 (코드 90% 재사용) --- plan/250906_news_skill_publish_separation.md | 134 ++++++++----------- 1 file changed, 59 insertions(+), 75 deletions(-) diff --git a/plan/250906_news_skill_publish_separation.md b/plan/250906_news_skill_publish_separation.md index 5588c68..b83ae29 100644 --- a/plan/250906_news_skill_publish_separation.md +++ b/plan/250906_news_skill_publish_separation.md @@ -1,70 +1,51 @@ # 뉴스 스킬과 퍼블리시 분리 아키텍처 계획 -## 1. 현재 구조 분석 -- **단일 시스템**: company-x_hompage에서 뉴스 수집부터 게시까지 모두 처리 -- **자동 게시**: 사용자 개입 없이 자동으로 Squarespace에 게시 -- **문제점**: 사용자 선택권 없음, 로빙 스킬 시스템과 분리되어 있음 +## 1. 현재 구조 및 검증 결과 +- **기존 시스템**: company-x_hompage - 완전 자동화된 뉴스 수집/게시 +- **rb8001 현황**: DM 전송(DMSkill), Cron 트리거(/api/cron/daily-summary), asyncio 스케줄링 구현 +- **재사용 가능 자원**: collectors 모듈 100%, ProcessLock 구현 완료, thumbnail_manager 활용 가능 ## 2. 목표 아키텍처 +- **skill-news**(8511): 뉴스 수집/요약 → Slack DM 전송 +- **skill-publish**(8512): 사용자 선택 뉴스 → Squarespace 게시 +- **데이터 흐름**: 수집 → 검증/요약 → DM 전송 → 사용자 선택 → 게시 → 결과 보고 -### 2.1 시스템 분리 -- **skill-news**: 뉴스 수집, 검증, 요약, Slack DM 전송 -- **skill-publish**: 사용자 선택 뉴스를 Squarespace에 게시 +## 3. 구현 계획 -### 2.2 데이터 흐름 -1. skill-news가 매일 정해진 시간에 뉴스 수집 -2. 중복 검사 및 검증 후 요약 생성 -3. Slack DM으로 뉴스 목록 전송 (선택 버튼 포함) -4. 사용자 선택 시 skill-publish API 호출 -5. 게시 완료 후 Slack으로 결과 보고 - -## 3. 기술 스택 -- **skill-news**: FastAPI (포트 8511) -- **skill-publish**: FastAPI (포트 8512) -- **데이터 저장**: PostgreSQL (rb_news 테이블) -- **통신**: HTTP API, Slack Web API -- **스케줄링**: APScheduler - -## 4. 구현 계획 - -### Phase 1: skill-news 구현 -**기존 코드 재사용**: -- google_news_collector.py → news_collector.py -- scrape_news_playwright.py → news_scraper.py -- news_summarizer.py → 그대로 사용 +### Phase 1: skill-news (1주차) +**기존 코드 재사용 (company-x_hompage/src/)**: +- collectors/google_news_collector.py (100% 재사용) +- collectors/scrape_news_playwright.py (100% 재사용) +- collectors/summarize_news.py (100% 재사용) +- utils/process_lock.py (완전 구현됨 - PID 확인, 타임아웃, atexit) +- collectors/thumbnail_manager.py (이미지 처리) **새로 구현**: -- FastAPI 서버 (main.py) -- Slack 인터랙션 처리 (slack_handler.py) -- DB 모델 (models.py): news_id, title, url, summary, status, created_at +- Slack 인터랙션 핸들러 (rb8001 DMSkill 참조) +- APScheduler 통합 (rb8001은 asyncio만 사용 중) -**API 엔드포인트**: -- POST /collect: 뉴스 수집 트리거 -- GET /news/{date}: 특정 날짜 뉴스 조회 -- POST /slack/interactive: Slack 버튼 응답 처리 +### Phase 2: skill-publish (2주차) +**기존 코드 재사용 (company-x_hompage/src/publishers/)**: +- squarespace_login.py, squarespace_publisher.py +- post_formatter.py (중복 체크 로직 포함) -### Phase 2: skill-publish 구현 -**기존 코드 재사용**: -- squarespace_login.py → 그대로 사용 -- squarespace_publisher.py → 그대로 사용 -- post_formatter.py → 그대로 사용 +### Phase 3: 통합 및 배포 (3주차) +**Nginx 설정 추가** (nginx-infra/server-nginx-default): +```nginx +location /skill-news/ { + proxy_pass http://localhost:8511/; + proxy_set_header Host $host; +} +location /skill-publish/ { + proxy_pass http://localhost:8512/; +} +``` -**API 엔드포인트**: -- POST /publish: 선택된 뉴스 게시 -- GET /status/{publish_id}: 게시 상태 확인 +**Slack App 권한** (추가 확인 필요): +- 필수: chat:write, im:write +- 권장: files:write, users:read, channels:read -### Phase 3: Slack 통합 -**Slack App 설정**: -- Bot Token Scopes: chat:write, im:write -- Interactive Components 활성화 -- Request URL: https://ro-being.com/skill-news/slack/interactive - -**메시지 포맷**: -- Block Kit 사용하여 뉴스 카드 생성 -- 각 뉴스에 "게시" 버튼 추가 -- action_id에 news_id 포함 - -### Phase 4: 데이터베이스 설계 +## 4. 데이터베이스 설계 ```sql CREATE TABLE rb_news ( id UUID PRIMARY KEY, @@ -76,29 +57,32 @@ CREATE TABLE rb_news ( summary TEXT, status VARCHAR(50), -- collected, selected, published slack_ts VARCHAR(50), - created_at TIMESTAMP, - published_at TIMESTAMP + created_at TIMESTAMP ); ``` -## 5. 배포 계획 -1. Docker 이미지 빌드 (skill-news, skill-publish) -2. docker-compose.yml 업데이트 -3. Nginx 리버스 프록시 설정 -4. Gitea Actions CI/CD 파이프라인 구성 +## 5. API 엔드포인트 +**skill-news**: +- POST /collect: 뉴스 수집 (Cron 트리거) +- GET /news/{date}: 날짜별 조회 +- POST /slack/interactive: 버튼 응답 -## 6. 모니터링 -- 로그: /mnt/hdd/logs/skill-news/, /mnt/hdd/logs/skill-publish/ -- 헬스체크: /health 엔드포인트 -- Slack 알림: 오류 발생 시 자동 알림 +**skill-publish**: +- POST /publish: 선택 뉴스 게시 +- GET /status/{id}: 게시 상태 -## 7. 일정 -- **Week 1**: skill-news 기본 구현 및 테스트 -- **Week 2**: skill-publish 구현 및 Slack 통합 -- **Week 3**: 통합 테스트 및 배포 +## 6. 주요 개선사항 +- **스케줄링**: rb8001의 asyncio → APScheduler 업그레이드 +- **DM 전송**: rb8001 DMSkill 로직 활용 (3명 하드코딩 → DB 연동) +- **ProcessLock**: 이미 구현된 정교한 락 메커니즘 그대로 사용 +- **모니터링**: /health 엔드포인트 + Slack 오류 알림 -## 8. 주의사항 -- 환경변수 분리 관리 (.env.skill-news, .env.skill-publish) -- API 키 보안 (Slack Token, Squarespace 인증) -- 중복 실행 방지 (ProcessLock 사용) -- 타임아웃 설정 (스크래핑 60초, 게시 120초) \ No newline at end of file +## 7. 리스크 및 해결방안 +- **Slack 권한**: 실제 필요 scope는 운영 중 확인 후 추가 +- **비동기 처리**: rb8001처럼 asyncio 기반 구현 +- **중복 실행**: ProcessLock으로 완벽 방지 (타임아웃 3600초) + +## 8. 일정 (현실적 추정) +- **1주차**: skill-news 구현 (코드 90% 재사용으로 충분히 가능) +- **2주차**: skill-publish + Slack 통합 +- **3주차**: 테스트 및 배포 \ No newline at end of file