DOCS/troubleshooting/250825_gmail_token_null_daily_briefing_fix.md
happybell80 63f774e71f docs: skill-email 자동갱신 해결완료 반영
- skill-email이 2025-08-27 자체 갱신 구현 완료
- auth-server API 연동 없이 Google 라이브러리 직접 사용
- 관련 문서 4개 수정
  - 250827_51124_critical_issues.md: 해결완료 표시
  - 250821_gmail_token_auto_refresh.md: TODO 완료 처리
  - 250825_gmail_token_null_daily_briefing_fix.md: 해결완료 추가
  - 250825_happybell80_UI개선및개인화준비.md: 취소선 처리

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-28 01:39:31 +09:00

6.9 KiB

Gmail 토큰 NULL 및 대화 저장 실패 문제 해결 가이드

작성일: 2025-08-25

작성자: 서버 관리자

상태: 해결 진행중

영향:

  • 매일 9시 브리핑 이메일 수집 실패 (사용자 3명)
  • PostgreSQL 대화 저장 실패 (State Service DB 설정 오류)

1. 문제 상황

1.1 증상

1.2 근본 원인

-- 현재 DB 상태: 모든 사용자 token_data가 NULL
SELECT username, has_token, is_equipped 
FROM gmail_tokens;

결과:
happybell80 | f (NULL) | t (장착됨)  -- 모순 상태
0914eagle   | f (NULL) | t (장착됨)  -- 모순 상태
cdctfm      | f (NULL) | t (장착됨)  -- 모순 상태

문제: is_equipped=true이지만 실제 token_data=NULL


2. 시스템 플로우 분석

2.1 일일 브리핑 플로우

sequenceDiagram
    participant Cron as Gateway Cron<br/>(매일 9시)
    participant RB as rb8001<br/>(51124:8001)
    participant Email as skill-email<br/>(51124:8501)
    participant DB as PostgreSQL<br/>(main_db)
    participant Slack as Slack API

    Cron->>RB: POST /api/cron/daily-summary
    RB->>Email: GET /messages?user_id={slack_id}
    Email->>DB: SELECT token_data FROM gmail_tokens
    DB-->>Email: token_data: NULL ❌
    Email-->>RB: 500 Internal Server Error
    RB->>Slack: 불완전한 브리핑 전송<br/>(이메일 없이 뉴스만)

2.2 Gmail OAuth 플로우 (재인증 필요)

sequenceDiagram
    participant User as 사용자
    participant Front as 프론트엔드
    participant Auth as auth-server<br/>(51123:9000)
    participant Google as Google OAuth
    participant DB as PostgreSQL

    User->>Front: Gmail 연결 클릭
    Front->>Auth: GET /api/gmail/auth?user_id={uuid}
    Auth->>Auth: OAuth URL 생성
    Auth-->>Front: Redirect to Google
    Front->>Google: 사용자 리다이렉트
    User->>Google: 권한 승인
    Google->>Auth: Callback with code
    Auth->>Google: Exchange code for tokens
    Google-->>Auth: access_token, refresh_token
    Auth->>DB: UPDATE gmail_tokens<br/>SET token_data = {...}
    Auth-->>Front: 인증 완료

3. 해결 방안

3.1 해결책 - 관리자 대신 인증

# 1. 테스트 계정으로 OAuth 인증 URL 생성
curl -X GET "http://localhost:9000/api/gmail/auth?user_id=1e16e9d5-59f3-54da-a661-8abeabff4230"

# 2. 반환된 URL을 브라우저에서 열어 Google 로그인
# 3. 권한 승인 후 콜백 확인

# 4. 토큰 저장 확인
export PGPASSWORD=robeings
psql -h localhost -U robeings -d main_db -c \
  "SELECT user_id, token_data IS NOT NULL FROM gmail_tokens WHERE user_id = '1e16e9d5-59f3-54da-a661-8abeabff4230';"

# 5. 브리핑 수동 테스트
curl -X POST http://192.168.219.52:8001/api/cron/daily-summary \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer cron-secret-2024"

3.2 해결책 - skill-email 토큰 자동 갱신 ( 해결완료 2025-08-27)

skill-email이 Google 라이브러리를 직접 사용하여 자동 갱신 구현 완료

  • auth-server API 연동 없이 독립적 처리
  • creds.refresh(Request())로 자동 갱신
  • 갱신된 토큰 DB 자동 저장

4. 실행 단계별 가이드

Step 1: 현재 상태 확인 (5분)

# 1. 토큰 상태 확인
export PGPASSWORD=robeings
psql -h localhost -U robeings -d main_db -c \
  "SELECT u.username, gt.token_data IS NOT NULL as has_token, 
          gt.is_equipped, gt.metadata->>'email' as email 
   FROM users u 
   LEFT JOIN gmail_tokens gt ON u.id = gt.user_id 
   WHERE u.username IN ('happybell80', '0914eagle', 'cdctfm');"

Step 2: 테스트 계정 인증 (15분)

# 1. OAuth URL 생성 (happybell80 계정)
curl -s "http://localhost:9000/api/gmail/auth?user_id=1e16e9d5-59f3-54da-a661-8abeabff4230" | jq -r '.auth_url'

# 2. 브라우저에서 URL 열고 Google 계정으로 로그인
# 3. 권한 승인 (이메일 읽기, 쓰기, 수정)

# 4. 인증 성공 확인
psql -h localhost -U robeings -d main_db -c \
  "SELECT token_data->'access_token' IS NOT NULL as success 
   FROM gmail_tokens 
   WHERE user_id = '1e16e9d5-59f3-54da-a661-8abeabff4230';"

Step 3: 브리핑 테스트 (10분)

# 1. 수동 브리핑 실행
curl -X POST http://192.168.219.52:8001/api/cron/daily-summary \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer cron-secret-2024"

# 2. 실시간 로그 모니터링
docker logs robeing-gateway -f 2>&1 | grep -E "daily|gmail|email"

# 3. Slack DM 확인
# happybell80 사용자의 Slack DM에 브리핑이 도착했는지 확인

Step 4: 다른 사용자 처리 (20분)

# 0914eagle 계정 인증
curl -s "http://localhost:9000/api/gmail/auth?user_id=b6ea2ee0-a15a-5cf4-93a9-a9ca20d4c4a0" | jq -r '.auth_url'

# cdctfm 계정 인증
curl -s "http://localhost:9000/api/gmail/auth?user_id=69ae4ea9-a15f-5110-9f5d-6568e380fcfb" | jq -r '.auth_url'

5. 검증 체크리스트

  • 모든 사용자의 token_data NOT NULL 확인
  • 수동 브리핑 실행 시 이메일 포함 확인
  • Slack DM으로 완전한 브리핑 수신 확인

6. 관련 파일

  • auth-server: /home/admin/auth-server/app/api/gmail_refresh.py
  • skill-email: skill-email/main.py (51124 서버)
  • State Service: /home/heejae/robeing-state-service/ (사용 안 함)

7. 대화 저장 문제 (추가 발견)

7.1 문제 상황

  • 증상: Slack DM 대화가 PostgreSQL에 저장 안됨
  • ChromaDB: 정상 저장
  • PostgreSQL: 저장 실패 (conversation_logs 테이블 0 rows)

7.2 대화 저장 플로우 (현재: State Service 사용 안 함)

sequenceDiagram
    participant User as Slack User
    participant RB as rb8001<br/>(51124:8001)
    participant Chroma as ChromaDB<br/>(51124:8000)
    participant PG as PostgreSQL<br/>(51123:5432)

    User->>RB: "하이"
    RB->>RB: 메시지 처리
    RB-->>User: "안녕하세요, 김종태님!"
    
    RB->>Chroma: store_memory()
    Chroma-->>RB: ✅ 저장 성공<br/>ID: 2a776b26...
    
    RB->>PG: 직접 INSERT INTO conversation_logs
    PG-->>RB: ✅ 저장 성공
    
    Note over RB: State Service 없이<br/>직접 DB 연결

7.3 근본 원인 (현재: 해결됨)

State Service 환경변수 오류State Service 사용 중단:

  • State Service는 더 이상 사용하지 않음
  • rb8001이 직접 PostgreSQL에 연결

7.4 현재 구조

# rb8001이 직접 DB 연결 (51124 서버)
DATABASE_URL=postgresql://robeings:robeings@192.168.219.45:5432/main_db
# State Service 없이 직접 연결

예상 소요 시간: 1시간 30분

  • Gmail 토큰 문제: 1시간
  • State Service DB 설정: 필요 없음 (직접 DB 연결)