DOCS/troubleshooting/250825_gmail_token_slack_id_migration.md
Claude-51124 45da54962b docs: skill-email UUID 불일치 문제 문서화 및 기존 문서 업데이트
- 새 문서: 250831_skill-email_UUID_inconsistency_URGENT.md
- rb8001이 UUID 전달, skill-email이 Slack ID 기대하는 문제
- 기존 문서들에 경고 메시지 추가
- UUID Primary Key 통일 방안 제시
2025-08-31 21:49:17 +09:00

6.0 KiB

Gmail Token 시스템 Slack ID 직접 사용 마이그레이션

개요

2025년 8월 25일, Gmail 토큰 조회 시스템을 UUID 변환 방식에서 Slack ID 직접 사용 방식으로 마이그레이션했습니다.

⚠️ 2025-08-31 업데이트: rb8001이 여전히 UUID를 전달하는 문제 발견. 250831_skill-email_UUID_inconsistency_URGENT.md 참조

문제 상황

기존 시스템의 문제점

  1. UUID 불일치 문제

    • auth-server: uuid.uuid4() (랜덤 UUID) 사용
    • skill-email/rb8001: uuid.uuid5(namespace, slack_id) (네임스페이스 기반 UUID) 사용
    • 결과: 동일한 사용자에 대해 서로 다른 UUID가 생성되어 토큰 조회 실패
  2. 데이터베이스 스키마 변경

    • 기존: token_data JSON 컬럼에 모든 토큰 정보 저장
    • 변경: 개별 컬럼으로 분리 (access_token, refresh_token, oauth_config, scopes, expiry)
    • 새 컬럼 추가: slack_id (Slack 사용자 ID 직접 저장)

해결 방안

1. Slack ID 직접 사용

UUID 변환을 완전히 제거하고 Slack ID를 직접 사용하도록 변경

2. 변경된 파일

/home/heejae/skill-email/services/db_credentials_provider.py

제거된 코드:

import uuid

def __init__(self, connection_string: str):
    # ...
    self.uuid_namespace = uuid.NAMESPACE_DNS  # 제거됨
    
def _convert_to_uuid(self, user_id: str) -> str:  # 메서드 전체 제거
    """Slack user_id를 UUID로 변환"""
    # ...

변경된 쿼리:

# 이전
user_uuid = self._convert_to_uuid(user_id)
cur.execute("""
    SELECT ... FROM gmail_tokens
    WHERE user_id = %s AND is_equipped = true
""", (user_uuid,))

# 현재
cur.execute("""
    SELECT ... FROM gmail_tokens
    WHERE slack_id = %s AND is_equipped = true
""", (user_id,))  # slack_id 직접 사용

/home/heejae/skill-email/services/gmail_service.py

추가된 자동 토큰 갱신:

def _get_gmail_service(self, user_id: str):
    # ...
    # 토큰이 만료되었거나 곧 만료될 경우 자동 refresh
    if creds and creds.expired and creds.refresh_token:
        logger.info(f"Refreshing expired token for user: {user_id}")
        from google.auth.transport.requests import Request
        creds.refresh(Request())
        
        # 갱신된 토큰 저장
        if hasattr(self.creds_provider, 'save_credentials'):
            self.creds_provider.save_credentials(user_id, creds)
            logger.info(f"Refreshed token saved for user: {user_id}")

401 에러 시 재시도 로직:

except HttpError as e:
    if e.resp.status == 401:
        logger.info(f"Got 401 error, refreshing token for user: {user_id}")
        # 캐시 삭제 후 재시도
        if user_id in self._service_cache:
            del self._service_cache[user_id]
        # 토큰 refresh 포함하여 다시 시도

3. 데이터베이스 스키마

gmail_tokens 테이블 구조:

CREATE TABLE gmail_tokens (
    id UUID PRIMARY KEY,
    slack_id VARCHAR(20) NOT NULL,  -- Slack 사용자 ID 직접 저장
    email VARCHAR(255),
    access_token TEXT,
    refresh_token TEXT,
    oauth_config JSONB,
    scopes JSONB,
    expiry TIMESTAMP,
    is_equipped BOOLEAN DEFAULT false,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 인덱스
CREATE INDEX idx_gmail_tokens_slack_id ON gmail_tokens(slack_id);
CREATE INDEX idx_gmail_tokens_equipped ON gmail_tokens(slack_id, is_equipped);

영향 받는 서비스

  1. skill-email (포트 8501)

    • db_credentials_provider.py 수정
    • gmail_service.py 자동 refresh 로직 추가
  2. rb8001 (포트 8001)

    • dm_skill.py의 일일 요약 기능
    • Gmail 이메일 조회 시 skill-email API 사용
  3. auth-server (포트 8088)

    • 변경 없음 (이미 slack_id 저장 중)
  4. robeing-monitor (포트 9024)

    • 이미 수정 완료 (새 컬럼 구조 읽기)

테스트 및 검증

1. 이메일 조회 테스트

# 개별 사용자 이메일 조회
curl -X GET "http://localhost:8501/messages?user_id=U091UNVE41M&limit=5&query=category:primary"

2. 일일 요약 DM 테스트

# Cron API 호출로 전체 사용자에게 DM 전송
curl -X POST "http://localhost:8001/api/cron/daily-summary" \
  -H "Authorization: Bearer cron-secret-2024" \
  -H "Content-Type: application/json"

3. 토큰 자동 갱신 확인

# skill-email 로그에서 자동 refresh 확인
docker logs skill-email | grep "Refreshing"

주요 개선 사항

  1. UUID 불일치 문제 해결

    • 모든 서비스가 동일한 식별자(slack_id) 사용
    • UUID 변환 과정 제거로 오류 가능성 감소
  2. 자동 토큰 갱신

    • 만료된 토큰 자동 감지 및 갱신
    • 401 에러 시 자동 재시도
    • 갱신된 토큰 DB 자동 저장
  3. 코드 단순화

    • UUID 변환 로직 제거
    • 직관적인 slack_id 사용
    • 디버깅 용이성 향상

배포 절차

# 1. skill-email 재빌드 및 재시작
cd /home/heejae/skill-email
docker compose down && docker compose up -d --build

# 2. 로그 확인
docker logs skill-email --tail 50

# 3. 헬스체크
curl http://localhost:8501/health

트러블슈팅

SSL SYSCALL error: EOF detected

  • 원인: PostgreSQL 연결 풀 타임아웃
  • 해결: 재시도 시 정상 작동 (연결 풀 자동 재생성)

토큰 조회 실패

  • 확인사항:
    1. slack_id 컬럼에 올바른 Slack 사용자 ID 저장 여부
    2. is_equipped = true 설정 여부
    3. SSH 터널 연결 상태 (포트 5433)

자동 갱신 실패

  • 확인사항:
    1. refresh_token 존재 여부
    2. Google OAuth 클라이언트 ID/Secret 설정
    3. 네트워크 연결 상태

참고 사항

  • SSH 터널: localhost:5433 → 124.55.18.179:5432
  • 데이터베이스: main_db
  • 환경 변수: /home/heejae/skill-email/.env
  • Docker 네트워크: network_mode: host