DOCS/troubleshooting/251114_gmail_calendar_scope_reconnect_guide.md

9.7 KiB

Gmail Passport Calendar Scope 재연동 가이드

작성일: 2025-11-14 작성자: Claude 목적: skill-calendar를 위한 Google Calendar API scope 추가


1. 현재 상황

문제

  • skill-calendar가 gmail_token 조회는 성공
  • Google Calendar API 호출 시 invalid_grant 에러 발생
  • 원인: 현재 Gmail Passport scope에 Calendar API 권한 없음

필요한 Scope

# 기존 (auth-server/app/providers/gmail_passport.py)
GMAIL_API_SCOPES = [
    "https://www.googleapis.com/auth/gmail.send",
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/gmail.modify",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/userinfo.profile"
]

# 추가 필요
+ "https://www.googleapis.com/auth/calendar",
+ "https://www.googleapis.com/auth/calendar.events"

2. 재연동 방법

방법 1: auth-server scope 수정 후 재인증 (권장)

Step 1: auth-server scope 수정

# 51123 서버 접속 (auth-server는 51123에서 실행)
ssh admin@192.168.219.45

# auth-server 디렉토리로 이동
cd /home/admin/auth-server

# gmail_passport.py 수정
vi app/providers/gmail_passport.py

수정 내용:

# Line 찾아서 수정 (대략 30-40줄)
GMAIL_API_SCOPES = [
    "https://www.googleapis.com/auth/gmail.send",
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/gmail.modify",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/userinfo.profile",
    "https://www.googleapis.com/auth/calendar",  # 추가
    "https://www.googleapis.com/auth/calendar.events"  # 추가
]

Step 2: auth-server 재배포

# Git 커밋
git add app/providers/gmail_passport.py
git commit -m "feat: Gmail Passport에 Calendar scope 추가"
git push origin main

# Gitea Actions가 자동 배포 (30초 소요)
# 또는 수동 배포:
docker compose restart

Step 3: 사용자별 재인증

웹 브라우저에서:

  1. https://ro-being.com 로그인 (김종태 계정)
  2. 설정 > 아이템 > Gmail
  3. "재인증" 버튼 클릭
  4. Google 권한 동의 화면에서 Calendar 권한 확인
  5. "허용" 클릭
  6. 자동으로 인벤토리 페이지로 리다이렉트
  7. gmail_token 테이블에 새로운 scope 저장됨

확인:

# 51124 서버에서
cd /home/admin/ivada_project/skill-calendar
python3 tests/test_google_calendar_integration.py

방법 2: DB 직접 수정 (비권장, 임시)

주의

  • OAuth 토큰은 발급 시 scope가 고정됨
  • DB만 수정해도 Google API는 scope 부족으로 거부
  • 반드시 재인증 필요

확인용 쿼리

-- 현재 scope 확인
SELECT user_id, scopes FROM gmail_token 
WHERE user_id = '53529291-5050-4daa-89fb-008b546feb63';

-- scope 추가 (효과 없음, 재인증 필요)
UPDATE gmail_token 
SET scopes = scopes || '["https://www.googleapis.com/auth/calendar"]'::jsonb
WHERE user_id = '53529291-5050-4daa-89fb-008b546feb63';

3. Google Cloud Console 설정 확인

OAuth 동의 화면 - Calendar Scope 추가 (중요!)

현재 상태: Gmail scope만 있음 (gmail.modify, userinfo.email 등)

추가 절차:

  1. https://console.cloud.google.com/apis/credentials/consent
  2. 화면 하단 "범위 추가 또는 삭제" 버튼 클릭
  3. 필터에서 "calendar" 검색
  4. 다음 2개 체크:
    • .../auth/calendar - 캘린더 보기, 수정, 공유, 영구 삭제
    • .../auth/calendar.events - 캘린더 일정 보기 및 수정
  5. "업데이트" 버튼 클릭
  6. "저장 후 계속" 클릭
  7. 완료 확인: "민감한 범위" 또는 "제한된 범위"에 Calendar 표시됨

API 활성화

  1. "API 및 서비스" > "라이브러리"
  2. "Google Calendar API" 검색
  3. "사용 설정" 클릭 (이미 활성화되어 있을 수 있음)

4. 테스트 시나리오

E2E 테스트

1. auth-server scope 수정 완료
2. 김종태 계정 Gmail 재인증
3. ro-being.com 로그인
4. 로빙에게 메시지: "11월 24일 검진 07:40~12시 인천 연수구 갯벌로156"
5. 로빙 응답: "일정을 구글 캘린더에 등록해드릴까요?"
6. 사용자 응답: "그래"
7. 로빙 응답: "✅ 구글 캘린더에 일정을 등록했습니다!"
8. Google Calendar 웹에서 확인: 2025-11-24 07:40~12:00 일정 존재

5. 트러블슈팅

invalid_grant 계속 발생

  • Gmail Passport 재인증 확인
  • gmail_token.scopes 필드에 calendar 포함 확인
  • access_token 갱신 시도 (refresh_token 사용)

Calendar API 403 Forbidden

  • Google Cloud Console에서 Calendar API 활성화 확인
  • OAuth 동의 화면에 Calendar scope 추가 확인

일정 등록 성공했지만 Calendar에 없음

  • 다른 Google 계정으로 로그인했을 가능성
  • primary calendar 대신 다른 캘린더 ID 사용 여부 확인

6. 참고 문서



7. 테스트 결과 (2025-11-14)

Calendar Scope 추가 성공

  • auth-server에 calendar scope 추가 완료
  • 김종태 계정 Gmail 재인증 완료
  • Google Cloud Console Calendar API 활성화 완료
  • skill-calendar → Google Calendar API 이벤트 생성 성공

Calendar 통합 테스트 결과 ⚠️

성공 케이스 (4/10)

  • "11월 30일 오후 2시 서울역에서 클라이언트 미팅" → calendar_event 감지됨
  • "11월 18일 오전 11시 사무실에서 회의" → calendar_event 감지됨
  • skill-calendar API 직접 호출 시 정상 작동
  • Google Calendar에 실제 이벤트 생성 확인

실패 케이스 (6/10)

  • "11월 20일 오후 3시에 팀 미팅" → intent 감지 실패 (LLM으로 우회)
  • "11월 23일 오후 3시 카페" → intent 감지 실패 ("카페"는 패턴에 없음)
  • "11월 18일 14시 개발팀 스프린트" → intent 감지 실패 ("스프린트"는 패턴에 없음)
  • 승인 응답 ("네", "좋아", "ㅇㅇ") → approval로 변환 안됨 (컨텍스트 비어있음)

근본 원인 분석

1. Intent 패턴 부족

# decision_engine.py의 calendar_event 패턴
IntentType.CALENDAR_EVENT: [
    r"\d+월\s*\d+일.*(검진|미팅|회의|회식|약속|일정)",  # 현재
    # 부족: 카페, 스프린트, 약속, 미팅, 회의, 점심, 저녁, 피팅 등
]

문제: 일정 키워드가 제한적이라 다양한 표현 감지 못함
해결: 패턴 확장 + LLM fallback 활용

2. Recent Conversations 로딩 실패

[DecisionEngine] 의도 분석 시작: '네'
Loaded 0 recent conversations for user ...
[Approval] 직전 intent 없음 → UNKNOWN

문제:

  • PostgreSQL conversation_log_pk 중복 키 에러 발생 중
  • 따라서 conversation_log에 저장이 안 되고, 조회도 빈 배열
  • approval 로직은 recent_conversations에 의존하므로 작동 불가

근본 원인:

  • conversation_log 테이블의 id 시퀀스가 out-of-sync
  • 이미 존재하는 id (1149, 1151, 1153 등)를 insert하려고 시도

해결 방안:

-- 51123 서버에서
SELECT MAX(id) FROM conversation_log;  -- 현재 최대값 확인
SELECT nextval('conversation_log_id_seq');  -- 시퀀스 현재값 확인
-- 시퀀스를 MAX(id) + 1로 재설정
SELECT setval('conversation_log_id_seq', (SELECT MAX(id) FROM conversation_log) + 1);

개선 사항

우선순위 1: DB 시퀀스 수정 (필수)

  • 없이는 approval 로직 완전 불능
  • PostgreSQL 시퀀스 재정렬 필요

우선순위 2: Intent 패턴 확장

IntentType.CALENDAR_EVENT: [
    # 기존
    r"\d+월\s*\d+일.*(검진|미팅|회의|회식|약속|일정)",
    # 추가
    r"\d+월\s*\d+일.*\d{1,2}시",  # 시간만 있으면 일정으로 간주
    r"(내일|모레|다음주).*(시|점심|저녁|미팅|회의|약속)",
    r"\d+월\s*\d+일",  # 날짜만 있어도 일정 가능성 고려
]

우선순위 3: LLM Fallback 강화

  • calendar_confirm이 이미 LLM 기반으로 파싱 수행
  • Intent 감지 실패 시 LLM에게 "일정인가?" 질문 후 calendar_confirm 호출

작업 완료: Gmail Calendar 재인증 성공, skill-calendar API 작동 확인
다음 단계:

  1. PostgreSQL conversation_log 시퀀스 수정 (필수)
  2. calendar_event 패턴 확장 (선택)
  3. 전체 E2E 재테스트

8. 추가 관찰 (2025-11-14 19:00)

신규 개선 사항

  • conversation_log 조회 시 intent 값 포함 → approval 로직이 다시 작동하여 calendar_approval → create_event 흐름이 복구됨
  • calendar_handlercalendar_confirm 대화 기록을 직접 찾고, Markdown 필드가 없어도 날짜/시간/장소를 추출하도록 보완함
  • Slack/Frontend에서 들어온 승인 메시지(네/좋아/ㅇㅋ 등)는 즉시 캘린더 이벤트 생성으로 이어지고 Google Calendar에도 등록 확인

남은 문제

  • 승인 직후에도 LLM fallback이 한 번 더 호출되어 “응답을 생성할 수 없습니다.” 메시지가 덧붙음 → approval 분기에서 LLM 재호출을 막아야 함
  • 동일한 일정 문구를 반복 입력하면 매번 새로운 이벤트가 생성됨 → 일정 중복 체크 로직 필요
  • 문서화 미완료: 위 보완 사항을 정리했으나, Slack/Frontend 사용자 가이드는 아직 업데이트되지 않음 (향후 DOCS/guide 추가 필요)

후속 TODO

  1. approval 완료 후에는 LLM을 재호출하지 않고 “등록 완료” 응답을 직접 반환
  2. 일정 중복 감지(최근 N분 내 같은 날짜/시간이면 안내만) 기능 추가
  3. 사용자용 가이드 문서(DOCS/guide)에 승인 흐름 및 실패 메시지 내용을 반영