DOCS/300_architecture/sequences/daily_briefing_sequences.md
happybell80 8c02b80359 Fix incorrect table names in documentation
- gmail_tokens → gmail_token (33 files)
- companies → company (17 files)
- conversation_logs → conversation_log (27 files)
- workspace_members → workspace_member (28 files)

All table names now match the actual PostgreSQL schema
2025-09-26 00:49:47 +09:00

7.2 KiB

일일 브리핑 시스템 시퀀스 다이어그램

작성일: 2025-08-25

작성자: 서버 관리자 with Claude

상태: 구현 완료 (Gmail 토큰 문제로 부분 작동)


목차

  1. 시스템 개요
  2. 정상 작동 시퀀스
  3. 현재 실패 시퀀스
  4. 구현 상태 요약

1. 시스템 개요

1.1 아키텍처

  • 크론 서버: 51123 (Gateway)
  • 실행 서버: 51124 (rb8001, skill-email, skill-news)
  • 실행 시간: 매일 오전 9시 (KST)
  • 대상 사용자: 슬랙 워크스페이스 멤버 3명

1.2 서비스 구성

서비스 포트 역할 상태
robeing-gateway 8100 크론 실행
rb8001 8001 브리핑 생성
skill-email 8501 이메일 수집 ⚠️
skill-news 8505 뉴스 수집

2. 정상 작동 시퀀스

sequenceDiagram
    participant Cron as Gateway Cron<br/>(51123:8100)
    participant RB as rb8001<br/>(51124:8001)
    participant DM as dm_skill<br/>(rb8001 내부)
    participant Email as skill-email<br/>(51124:8501)
    participant News as skill-news<br/>(51124:8505)
    participant DB as PostgreSQL<br/>(51123:5432)
    participant Auth as auth-server<br/>(51123:9000)
    participant LLM as Gemini Service<br/>(rb8001 내부)
    participant Slack as Slack API
    participant User as 사용자 DM

    %% 크론 트리거
    Note over Cron: 매일 09:00:00 KST
    Cron->>RB: POST /api/cron/daily-summary<br/>Authorization: Bearer cron-secret-2024
    
    %% 인증 및 초기화
    RB->>RB: 토큰 검증<br/>(main.py:229)
    RB->>DM: send_daily_summary_dm()<br/>(dm_skill.py:384)
    
    %% 사용자 목록
    Note over DM: 하드코딩된 사용자:<br/>U091UNVE41M (전희재)<br/>U0925SXQFDK (김종태)<br/>U092F7FQ55L (HanYong)
    
    %% 병렬 데이터 수집
    par 이메일 수집
        loop 각 사용자별
            DM->>Email: GET /messages<br/>?user_id={slack_id}<br/>&limit=5<br/>&query=category:primary
            
            %% 토큰 체크 및 갱신
            Email->>DB: SELECT * FROM gmail_token<br/>WHERE user_id = ?
            DB-->>Email: token_data, refresh_token
            
            alt 토큰 만료
                Email->>Auth: POST /api/gmail/refresh<br/>Body: {user_id, refresh_token}
                Auth->>Auth: Google OAuth 토큰 갱신
                Auth->>DB: UPDATE gmail_token
                Auth-->>Email: 새 access_token
            end
            
            Email->>Email: Gmail API 호출<br/>Primary 탭 이메일 조회
            Email-->>DM: 이메일 목록 (최대 5개)
        end
    and 뉴스 수집
        DM->>News: POST /api/news/search<br/>Body: {<br/>  keywords: ["AI", "스타트업",<br/>  "기술", "혁신", "투자"]<br/>}
        News->>News: Google News API 호출
        News->>News: 결과 필터링 및 정렬
        News-->>DM: 최신 뉴스 5개
    end
    
    %% LLM 요약 생성
    DM->>DM: 데이터 통합<br/>- 이메일: 사용자별 5개<br/>- 뉴스: 공통 5개
    
    DM->>LLM: 요약 생성 요청
    Note over LLM: 프롬프트:<br/>"한국어로 오늘의 브리핑 작성<br/>1. 중요 이메일 요약<br/>2. 주요 뉴스 요약<br/>3. 액션 아이템 추출"
    LLM-->>DM: 구조화된 브리핑 텍스트
    
    %% Slack 전송
    loop 각 사용자별
        DM->>DM: 개인화 메시지 생성
        DM->>Slack: POST /api/chat.postMessage<br/>Body: {<br/>  channel: {user_dm_id},<br/>  text: "🌅 모닝 브리핑",<br/>  blocks: [...]<br/>}
        Slack-->>DM: 전송 성공
        Slack->>User: 📨 개인 DM 수신
    end
    
    %% 완료
    DM-->>RB: 브리핑 전송 완료
    RB-->>Cron: 200 OK<br/>Body: {status: "success"}

3. 현재 실패 시퀀스

sequenceDiagram
    participant Cron as Gateway Cron<br/>(51123)
    participant RB as rb8001<br/>(51124)
    participant DM as dm_skill
    participant Email as skill-email
    participant News as skill-news
    participant DB as PostgreSQL
    participant Slack as Slack API
    participant User as 사용자

    Note over Cron: 09:00:00 트리거 ✅
    Cron->>RB: POST /api/cron/daily-summary ✅
    RB->>DM: send_daily_summary_dm() ✅
    
    %% 이메일 수집 실패
    rect rgb(255, 230, 230)
        Note over DM,Email: 이메일 수집 실패
        DM->>Email: GET /messages
        Email->>DB: SELECT gmail_token
        DB-->>Email: token_data: NULL ❌
        Email-->>DM: 500 Internal Server Error
        Note over DM: 이메일 데이터 = []
    end
    
    %% 뉴스는 정상
    rect rgb(230, 255, 230)
        Note over DM,News: 뉴스 수집 성공
        DM->>News: POST /api/news/search ✅
        News-->>DM: 뉴스 5개 반환 ✅
    end
    
    %% 불완전한 브리핑
    DM->>DM: 부분 데이터로 요약 생성
    Note over DM: 이메일 섹션 비어있음
    
    loop 각 사용자
        DM->>Slack: 불완전한 브리핑 전송
        Slack->>User: 📨 뉴스만 있는 브리핑
        Note over User: "이메일 요약: 없음<br/>뉴스 요약: 5개 항목"
    end


4. 구현 상태 요약

4.1 완료된 구현

  • 크론 설정: Gateway에서 매일 9시 실행
  • API 엔드포인트: /api/cron/daily-summary (main.py:229)
  • DM 스킬: send_daily_summary_dm() (dm_skill.py:384)
  • 뉴스 서비스: skill-news 독립 서비스 (포트 8505)
  • Slack 전송: 정상 작동

4.2 현재 상태

항목 상태
Gmail 토큰 사용자별 저장
토큰 갱신 auth-server API 구현됨
사용자 조회 하드코딩

4.3 관련 파일

51123 서버:
├── /home/admin/robeing-gateway/app/crontab.py (크론 설정)
├── /home/admin/auth-server/app/api/gmail_refresh.py (토큰 갱신 API)
└── /home/admin/DOCS/troubleshooting/250824_*.md (트러블슈팅)

51124 서버:
├── /home/admin/ivada_project/rb8001/
│   ├── main.py:229 (크론 엔드포인트)
│   └── app/skills/dm_skill.py:384 (브리핑 생성)
├── /home/admin/ivada_project/skill-email/ (이메일 서비스)
└── /home/admin/ivada_project/skill-news/ (뉴스 서비스)

5.4 모니터링 포인트

# 크론 실행 확인
docker exec robeing-gateway crontab -l | grep briefing

# 서비스 상태 확인
docker ps | grep -E "rb8001|skill-email|skill-news"

# 로그 확인
docker logs rb8001 --tail 100 | grep daily-summary
docker logs skill-email --tail 50 | grep ERROR

# DB 토큰 상태
psql -U robeings -d main_db -c "SELECT user_id, token_data IS NOT NULL as has_token FROM gmail_token;"

개선 제안

단기 (즉시 적용 가능)

  1. skill-email에 토큰 만료 체크 로직 추가
  2. 에러 발생 시에도 뉴스만이라도 전송하도록 graceful degradation

중기 (1-2주)

  1. 사용자 목록 DB 연동
  2. Gmail refresh_token 자동 갱신 구현
  3. 브리핑 커스터마이징 (사용자별 선호도)

장기 (1개월+)

  1. 웹 UI에서 브리핑 설정 관리
  2. 브리핑 시간 개인화
  3. 다양한 데이터 소스 추가 (캘린더, 태스크 등)