From 192851220a0d91181f4714091777d8fc3af8494c Mon Sep 17 00:00:00 2001 From: happybell80 Date: Thu, 4 Dec 2025 22:05:07 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EB=89=B4=EC=8A=A4=20plan=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EA=B0=84=EA=B2=B0=ED=99=94=20-=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EC=99=84=EB=A3=8C=20=EC=84=B9=EC=85=98=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0,=20troubleshooting=20=EB=A7=81=ED=81=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../250906_news_skill_publish_separation.md | 122 ++++------ .../plans/250906_news_system_integration.md | 211 +++++------------- 2 files changed, 100 insertions(+), 233 deletions(-) diff --git a/journey/plans/250906_news_skill_publish_separation.md b/journey/plans/250906_news_skill_publish_separation.md index e52f8f8..7e1311c 100644 --- a/journey/plans/250906_news_skill_publish_separation.md +++ b/journey/plans/250906_news_skill_publish_separation.md @@ -1,93 +1,65 @@ # 뉴스 스킬과 퍼블리시 분리 아키텍처 계획 -## 1. 현재 구조 (검증 완료) -- **기존 시스템**: company-x_hompage - 완전 자동화된 뉴스 수집/게시 -- **rb8001 실행 중**: Docker 상태 "Up 11 hours (healthy)" 확인 -- **DM 기능**: /api/cron/daily-summary 구현, dm_skill.py (577라인) -- **재사용 가능**: collectors 모듈 100%, ProcessLock(타임아웃 3600초), thumbnail_manager +**작성일**: 2025-09-06 +**목적**: skill-news, skill-publish 마이크로서비스 분리 -## 2. 목표 아키텍처 -- **skill-news**: 포트 8505 (51124 서버 **정상 운영** 확인) -- **skill-publish**: 포트 8511 (**구현 완료** - [트러블슈팅](../troubleshooting/250906_skill_publish_implementation.md)) -- **데이터 흐름**: 수집 → 검증/요약 → DM 전송 → 사용자 선택 → 게시 → 결과 보고 +--- -## 3. 구현 계획 +## 1. 목표 아키텍처 -### Phase 1: skill-news (⚠️ 불완전 구현 발견) -**2025-09-07 개선사항**: -- ✅ rb8001 → skill-news POST 파라미터 전달 -- ✅ 중복 체크 collector 내부로 이동 (엔드포인트 제거) -- ✅ Company-X 전용 봇 토큰 분리 (COMPANY_X_SLACK_BOT_TOKEN) -- ✅ 뉴스 없을 때 메시지 비활성화 -- [상세: troubleshooting/250907_company_x_news_zero_articles.md] +``` +skill-news (8505) + - 뉴스 수집 (Google News API) + - 스크래핑 (본문 추출) + - Gemini 요약 -**착각했던 문제점**: -- ❌ skill-news는 검색만 함 (스크래핑/요약 없음) -- ❌ 본문(content)과 요약(summary) 없이 제목/URL만 전달 -- ❌ skill-publish가 빈 콘텐츠로 홈페이지 게시 시도 -- ❌ company-x_hompage는 완전한 파이프라인 보유 +skill-publish (8511) + - Squarespace CMS 게시 + - 게시 상태 관리 +``` -**필수 변수 (Squarespace 게시용)**: -- id, company_name, title, **summary**(280-320자) -- date, publisher, url, thumbnail_url -- formatted_content (제목+요약+날짜+언론사) +--- -### Phase 2: skill-publish (✅ 완료) -**구현 상세**: [트러블슈팅 문서](../troubleshooting/250906_skill_publish_implementation.md) 참조 +## 2. 구현 상태 -### Phase 3: 통합 및 배포 (3주차) -**통신 방식**: -- 내부: Docker 네트워크 (rb8001 ↔ skill-*) -- skill-news: 포트 8505 (운영 중) -- skill-publish: 포트 8511 (구현 예정) -- Nginx 프록시: 외부 노출 불필요 (내부 통신만) +### ✅ 완료 +- skill-news: 포트 8505 운영 중 +- skill-publish: 포트 8511 구현 완료 -**Slack App 권한**: -- 확인됨: chat:write (mrkdwn, Block Kit 지원) -- 추가 필요 여부: files:write, users:read [확인 필요] +**상세**: `troubleshooting/250906_skill_publish_implementation.md` -## 4. 데이터베이스 (확인됨) -**PostgreSQL (51123 서버)**: -- main_db 사용 (구 auth_db) -- users, gmail_token, robeing_stats 테이블 존재 -- ~~rb_news 테이블~~: DB 작업 후 구현 예정 +### ⏳ 미구현 -**ChromaDB (51124 서버)**: -- 경로: /home/admin/ivada_project/rb8001/chroma_db (확인됨) -- 16개 사용자별 UUID 컬렉션 존재 +**Phase 3: skill-news 스크래핑/요약 기능 강화** +- 현재: 제목/URL만 제공 +- 필요: 본문(content) + 요약(summary) 280-320자 +- 작업: companyx_news_collector.py 확장 -**데이터 저장 방식**: -- 단기: JSON 파일 기반 (`/app/data/news_state.json`) -- Slack 메시지 ID에 뉴스 ID 임베드 -- ChromaDB로 중복 체크 -- 향후: PostgreSQL rb_news 테이블로 마이그레이션 계획 +**Phase 4: 통합 테스트** +- E2E 시나리오: 수집 → Slack 전송 → 버튼 클릭 → 게시 → 알림 +- 실제 Squarespace 게시 검증 -## 5. API 엔드포인트 -**skill-news**: -- POST /collect: 뉴스 수집 (Cron 트리거) -- GET /news/{date}: 날짜별 조회 -- POST /slack/interactive: 버튼 응답 +--- -**skill-publish**: -- POST /publish: 선택 뉴스 게시 -- GET /status/{id}: 게시 상태 +## 3. 필수 변수 (Squarespace 게시용) -## 6. 확인된 구현 사항 -- **브리핑 시스템**: ✅ rb8001/app/skills/dm_skill.py 구현됨 -- **APScheduler**: ✅ rb8001에 이미 구현 (평일 09:00 스케줄링) -- **사용자 목록**: Slack ID .env 미설정 (DB 연동 필요) -- **Gmail 토큰 갱신**: ✅ 2024-08-27 해결 완료 -- **ProcessLock**: ✅ 완전 구현 (PID 확인, 타임아웃 3600초, atexit) -- **서버 분리**: ✅ 51123(메인), 51124(로빙/스킬) 물리적 분리 -- **Gemini 모델**: ✅ 환경변수 GEMINI_MODEL로 통일 (gemini-2.5-flash-lite) -- **skill-publish**: ✅ 포트 8511 구현 완료 ([상세](../troubleshooting/250906_skill_publish_implementation.md)) +```json +{ + "id": "article_123", + "company_name": "컴퍼니엑스", + "title": "...", + "summary": "280-320자 요약", + "date": "2025-09-06", + "publisher": "강원일보", + "url": "https://...", + "thumbnail_url": "https://...", + "formatted_content": "HTML" +} +``` -## 7. 즉시 필요 작업 -- **데이터 저장**: ✅ JSON 파일 기반 구현 완료 -- **Slack 사용자 ID**: .env 설정 필요 (51124) -- **내부 통신**: ✅ 포트 8511 HTTP API 준비 완료 +--- -## 8. 일정 (완료 상태) -- **1주차**: ✅ skill-news 운영 중 (포트 8505) -- **2주차**: ✅ skill-publish 구현 완료 (포트 8511) -- **3주차**: Slack 통합 및 rb8001 연동 예정 +## 4. 참고 + +- `troubleshooting/250906_skill_publish_implementation.md` +- `troubleshooting/250908_skill_news_companyx_data_integration.md` diff --git a/journey/plans/250906_news_system_integration.md b/journey/plans/250906_news_system_integration.md index 1b48b99..4f877d7 100644 --- a/journey/plans/250906_news_system_integration.md +++ b/journey/plans/250906_news_system_integration.md @@ -1,183 +1,78 @@ # 뉴스 시스템 통합 계획 -## 작성일: 2025-09-06 -## 작성자: happybell80 -## 목적: skill-news, rb8001, skill-publish 통합 연동 +**작성일**: 2025-09-06 +**목적**: skill-news, rb8001, skill-publish 통합 연동 -## 1. 현재 구현 상태 +--- -### 대상 채널 -- **컴퍼니엑스 전체 채널**: C09C98KK2TT -- **로빙팀 채널**: C09CP4MDX71 (테스트용) -- **팀 ID**: T09C98KB933 -- **용도**: 컴퍼니엑스 뉴스 선택 후 게시 +## 1. 아키텍처 -### 구현 완료 (확인됨) -- **skill-news** (포트 8505): 뉴스 수집, 스크래핑, 요약 API 운영 중 -- **skill-publish** (포트 8511): Squarespace 게시 서비스 준비 완료 -- **APScheduler**: rb8001/main.py:207 평일 09:00 자동 실행 -- **DM 전송**: rb8001/app/skills/dm_skill.py:384 텍스트 메시지 전송 -- **Gemini 요약**: gemini-2.5-flash-lite 모델 사용 중 -- **JSON 상태 관리**: /app/data/news_state.json 파일 기반 - -### 코드 수정 완료 (테스트 대기) -- **Slack 인터랙티브 버튼**: Block Kit 구현 완료 -- **Button Callback 처리**: /api/slack/interactive 엔드포인트 추가 -- **rb8001↔skill-publish 연동**: HTTP 통신 코드 구현 -- **게시 결과 알림**: response_url 통한 알림 구현 -- **DB 저장**: rb_news 테이블 없음 (Phase 3 대기) - -## 2. 통합 플로우 - -### 2.1 뉴스 수집 및 채널 전송 +### 서비스 구조 ``` -APScheduler → skill-news:8505/api/news/google/companyx-search - → rb8001/app/skills/news_posting_skill.py - → Slack 채널 전송 -``` -**구현**: companyx_news_collector.py (OR 연산자, 제외 키워드 적용) - -### 2.2 사용자 인터랙션 (목표) -``` -사용자 버튼 클릭 → rb8001/slack/interactive - → 검증 및 처리 - → skill-publish 호출 +APScheduler → skill-news:8505 → rb8001 → Slack 채널 + ↓ + 사용자 버튼 클릭 + ↓ + skill-publish:8511 → Squarespace ``` -### 2.3 게시 프로세스 (목표) -``` -rb8001 → POST skill-publish:8511/publish - → Squarespace 자동 게시 - → 결과 반환 - → Slack DM 알림 -``` +### 데이터 흐름 +- 수집: skill-news (Google News API) +- 요약: Gemini LLM +- 전송: skill-slack (Block Kit) +- 게시: skill-publish (Squarespace CMS) -## 3. 필요 구현 사항 +--- -### 3.0 컴퍼니엑스 전용 검색 (skill-news) ✅ -**파일**: app/services/companyx_news_collector.py (생성됨) -**엔드포인트**: /api/news/google/companyx-search (news_endpoints.py:64) -**검색식**: `"컴퍼니 엑스" OR "컴퍼니엑스" -광고 -채용 -구인` -**환경변수**: COMPANY_X_NEWS_KEYWORDS (기본값 내장) +## 2. 구현 상태 -### 3.1 Slack Block Kit 메시지 (rb8001 생성, skill-slack 전송) ✅ -**위치**: app/skills/news_posting_skill.py (생성됨) -**함수**: -- `send_news_for_posting()`: Block Kit 생성 후 skill-slack에 전송 요청 -- `create_news_blocks()`: Block Kit 메시지 생성 -- `process_news_batch()`: APScheduler에서 호출 -```python -blocks = [ - { - "type": "section", - "text": {"type": "mrkdwn", "text": f"*{title}*\n{summary}"}, - "accessory": { - "type": "button", - "text": {"type": "plain_text", "text": "게시"}, - "action_id": f"publish_news_{news_id}", - "value": news_id - } - } -] -``` -**참고**: naver_startup_news_service.py, dm_skill.py:384 (DM 전송 로직) +### ✅ 완료 +- skill-news 운영 중 (포트 8505) +- skill-publish 구현 완료 (포트 8511) +- APScheduler 평일 10:00 자동 실행 +- Slack Block Kit 버튼 전송 -### 3.2 Interactive Endpoint (rb8001) ✅ -**위치**: main.py:249 (구현됨) -```python -@app.post("/api/slack/interactive") -async def slack_interactive(request: Request): - return await handle_interactive(request) # slack_handler.py -``` -**핸들러**: slack_handler.py:274 handle_interactive() 구현됨 -**구현 방식**: 기존 handle() 패턴 따라 payload 파싱, action_id 확인 -**URL 설정**: Slack App에 https://ro-being.com/api/slack/interactive 등록 +**상세**: `troubleshooting/250907_company_x_news_zero_articles.md` 외 다수 -### 3.3 skill-publish 연동 (rb8001) ✅ -**위치**: news_posting_skill.py:186 publish_to_squarespace() 구현됨 -```python -async def publish_to_squarespace(news_data): - async with httpx.AsyncClient() as client: - response = await client.post( - "http://localhost:8511/publish", - json=news_data - ) -``` -**호출 위치**: slack_handler.handle_interactive() → publish_to_squarespace() -**결정**: localhost 사용 (rb8001이 모든 스킬을 localhost로 호출 중) +### ⏳ 미구현 +- **PostgreSQL rb_news 테이블**: 현재 JSON 파일 기반 +- **실시간 게시 상태 추적**: skill-publish API 확장 필요 +- **게시 이력 조회**: 프론트엔드 UI 미구현 -### 3.4 데이터 저장 전략 -**현재**: JSON 파일 (/app/data/news_state.json) -**향후**: PostgreSQL rb_news 테이블 -**결정**: JSON 유지 (DB 작업 완료 후 마이그레이션) +--- -## 4. 환경변수 설정 +## 3. 미구현 Phase 3: DB 영구 저장 + +### 현재 제약 +- JSON 파일 (`/app/data/news_state.json`) 사용 +- 컨테이너 재시작 시 이력 손실 가능 +- 통계/분석 어려움 + +### 필요 작업 +1. `rb_news` 테이블 생성 (user_id, article_id, published_at, status) +2. news_posting_skill.py에 DB 저장 로직 추가 +3. 게시 이력 조회 API (`GET /api/news/history`) + +--- + +## 4. 환경 설정 ### rb8001 (.env) ```bash COMPANY_X_NEWS_CHANNEL_ID=C09CP4MDX71 -COMPANY_X_NEWS_KEYWORDS=컴퍼니엑스,컴퍼니 엑스,Company X -COMPANY_X_NEWS_SCHEDULE=0 10 * * 1-5 # cron -SKILL_PUBLISH_URL=http://localhost:8511 SKILL_NEWS_URL=http://localhost:8505 +SKILL_PUBLISH_URL=http://localhost:8511 ``` -### skill-publish (.env) -```bash -# 이미 설정됨 (포트 8511) -``` +### Slack App +- Interactivity URL: https://ro-being.com/api/slack/interactive +- Scopes: chat:write, chat:write.public -## 5. Slack App 설정 -**필요 작업**: -- Interactivity & Shortcuts 활성화 (HTTP Mode) -- Request URL 설정: https://ro-being.com/api/slack/interactive -- OAuth Scopes 확인됨: chat:write, chat:write.public (문서 확인) -- 확인 필요: im:history 권한 +--- -## 6. 구현 우선순위 +## 5. 참고 문서 -### Phase 1 (즉시) -1. Slack Block Kit 메시지 구현 -2. Interactive endpoint 추가 -3. 테스트 (버튼 클릭 → 로그 확인) - -### Phase 2 (다음 주) -1. skill-publish 연동 코드 -2. 게시 결과 Slack 알림 -3. 상태 추적 (JSON 기반) - -### Phase 3 (DB 준비 후) -1. rb_news 테이블 생성 -2. JSON → DB 마이그레이션 -3. 이력 조회 API - -## 7. 테스트 시나리오 -1. 환경변수 설정: COMPANY_X_NEWS_TEST_NOW=true (30초 후 실행) -2. 버튼 표시 확인 -3. 클릭 이벤트 수신 확인 -4. skill-publish 호출 확인 -5. 게시 완료 확인 - -## 8. 리스크 및 대안 -- **Slack 권한 부족**: App 재설치 필요할 수 있음 -- **통신 실패**: 모든 서비스 localhost 사용으로 해결 -- **DB 지연**: JSON 파일로 충분히 운영 가능 - -## 9. 모니터링 -```bash -# Interactive 이벤트 확인 -docker logs rb8001 | grep interactive - -# 게시 요청 확인 -docker logs skill-publish | grep publish - -# Slack 전송 확인 -docker logs rb8001 | grep postMessage -``` - -## 10. 완료 기준 -- [x] 코드 구현: 모든 Phase 1, 2 기능 구현 완료 -- [ ] 테스트: 실제 작동 확인 필요 -- [ ] Slack App 설정: Interactive URL 등록 필요 -- [ ] 환경변수 설정: .env 파일 업데이트 필요 -- [ ] 배포: Docker 재시작 후 검증 필요 +- `troubleshooting/250907_company_x_news_zero_articles.md` +- `troubleshooting/250908_skill_news_companyx_data_integration.md` +- `troubleshooting/250908_slack_interactive_gateway_proxy.md` +- `troubleshooting/250920_news_db_persistence_implementation.md`