--- tags: [workflow, scheduler, news, headlines, slack] type: workflow last_updated: 2026-04-06 --- # scheduled_daily_briefing 워크플로우 ## 목적 DB에 등록된 스케줄에 따라 네이버 + 동남아 스타트업 헤드라인을 수집하여 Slack 채널에 자동 게시한다. ## 아키텍처 - **스케줄러**: APScheduler (DB 기반). `db_loader.py`가 `scheduler_jobs` 테이블에서 `job_type=daily_headlines` 잡을 로드하여 등록. - **실행 래퍼**: `app/scheduler/jobs/daily_headlines.py` → `_run_headlines_with_logging(channel_id)`. - **실제 워크플로우**: `app/services/workflows/headlines_workflow.py` — LangGraph StateGraph로 구성. - **n8n 미사용**. systemd로 rb8001이 직접 실행. ## 코드 SSOT - `rb8001/app/scheduler/jobs/daily_headlines.py` — 스케줄러 잡 래퍼 - `rb8001/app/services/skills/startup_news_skill.py` — `run_headlines_job()` 진입점 - `rb8001/app/services/workflows/headlines_workflow.py` — LangGraph 워크플로우 본체 - `rb8001/app/scheduler/db_loader.py` — DB 잡 로더 (`JOB_TYPE_MAP["daily_headlines"]`) ## 흐름 ``` APScheduler cron trigger → db_loader가 등록한 guarded_job (schedule_policy 평가) → _run_headlines_with_logging(channel_id) → run_headlines_job(channel_id) → run_headlines_workflow(channel_id) [LangGraph] → fetch_naver_node (SkillCommands.fetch_naver_headlines, fmt=slack) → fetch_sea_node (SkillCommands.fetch_sea_headlines, fmt=json) → format_node (네이버 텍스트에 동남아 섹션 삽입) → send_node (Slack chat.postMessage) ``` ## 스케줄 정책 - cron 표현식은 `scheduler_jobs` DB 테이블에서 관리한다 (예: `10 9 * * 1-5`). - `schedule_policy` 필드에 `workday` 정책이 설정되어 있으면 공휴일/주말을 건너뛴다 (`evaluate_schedule_policy()`). - `channel_id`는 `config.channel_id` DB 필드에서 전달받는다. ## 주요 노드 (LangGraph) | 노드 | 함수 | 설명 | |------|------|------| | fetch_naver | `fetch_naver_node()` | `SkillCommands.fetch_naver_headlines(fmt="slack")` 호출 | | fetch_sea | `fetch_sea_node()` | `SkillCommands.fetch_sea_headlines(fmt="json")` 호출 | | format | `format_node()` | 네이버 헤드라인 텍스트 끝에 동남아 섹션 삽입 | | send | `send_node()` | Slack `chat.postMessage` 전송 | ## Slack 봇 토큰 해소 - `_get_slack_bot_token_for_channel(channel_id)` → DB에서 채널별 workspace bot_token 조회. - 실패 시 `settings.COMPANYX_SLACK_BOT_TOKEN` → `settings.SLACK_BOT_TOKEN` 순서로 폴백. ## 실패 분기 - 네이버 또는 동남아 API 호출 실패 시 `errors` 리스트에 기록하고 빈 텍스트로 진행. - 보낼 텍스트가 비어 있으면 Slack 전송을 스킵하고 `message_ts=None`으로 종료. - Slack 전송 실패 시 `errors`에 기록. ## 관련 문서 - [skill_news_briefing_request](../02_skills/skill_news_briefing_request.md)