DOCS/journey/troubleshooting/251114_gmail_calendar_scope_reconnect_guide.md
Claude-51124 22557e7132 docs: 오래된 트러블슈팅 아카이브 및 구조 정리
- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동
- book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서)
- 빈 폴더 제거 (journey/assets/*)
2025-11-17 14:06:05 +09:00

7.3 KiB

Gmail Calendar Scope 및 Timezone 트러블슈팅

작성일: 2025-11-14 ~ 2025-11-16 작성자: Claude


1. Calendar Scope 추가 (2025-11-14)

문제

  • skill-calendar가 Google Calendar API 호출 시 invalid_grant 에러
  • 원인: Gmail Passport scope에 Calendar API 권한 없음

해결 절차

Step 1: auth-server scope 수정

# 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"        # 추가
]
cd /home/admin/auth-server
git add app/providers/gmail_passport.py
git commit -m "feat: Calendar scope 추가"
git push origin main

Step 2: Google Cloud Console 설정 (필수!)

OAuth 동의 화면에서 Calendar Scope 수동 추가:

  1. https://console.cloud.google.com/apis/credentials/consent
  2. "범위 추가 또는 삭제" 클릭
  3. "calendar" 검색
  4. 체크:
    • .../auth/calendar (캘린더 보기, 수정, 공유, 영구 삭제)
    • .../auth/calendar.events (캘린더 일정 보기 및 수정)
  5. "업데이트" → "저장 후 계속"

API 활성화:

  • "API 및 서비스" > "라이브러리" > "Google Calendar API" > "사용 설정"

Step 3: 사용자별 재인증 (필수!)

웹 브라우저:

  1. https://ro-being.com 로그인
  2. 설정 > 아이템 > Gmail > "재인증"
  3. Google 권한 동의 화면에서 Calendar 권한 확인
  4. "허용" 클릭

중요: OAuth 토큰은 발급 시 scope가 고정됨. DB 직접 수정으로는 해결 안 됨.


2. PostgreSQL 시퀀스 문제 (2025-11-14)

문제

  • conversation_log_pk 중복 키 에러
  • 대화 저장 실패 → approval 로직 작동 불가 ("네" 응답 인식 못함)

원인

  • conversation_log 테이블 id 시퀀스가 out-of-sync
  • 이미 존재하는 id를 insert 시도

해결

-- 51123 서버에서
SELECT MAX(id) FROM conversation_log;
SELECT nextval('conversation_log_id_seq');

-- 시퀀스 재정렬
SELECT setval('conversation_log_id_seq', (SELECT MAX(id) FROM conversation_log) + 1);

3. Calendar CRUD Timezone 이슈 (2025-11-16)

문제

  • CREATE: 성공
  • READ: 방금 등록한 일정 조회 실패
  • DELETE: 성공하지만 잘못된 날짜 표시

원인

naive datetime (timezone 없음) 사용:

# 문제
start_iso = f"{date}T{start_hour}:{start_min}:00"  # "2025-11-17T15:00:00"

# Google Calendar API는 timezone 없으면 해석 불확실
# rb8001 → skill-calendar 전송 시 timezone 불일치

해결

rb8001/app/router/calendar_handler.py 수정:

parse_time_range() (Line 397):

from datetime import datetime
from zoneinfo import ZoneInfo

year, month, day = map(int, date.split('-'))
tz = ZoneInfo("Asia/Seoul")

start_dt = datetime(year, month, day, int(start_hour), int(start_min), 0, tzinfo=tz)
end_dt = datetime(year, month, day, int(end_hour), int(end_min), 0, tzinfo=tz)

return start_dt.isoformat(), end_dt.isoformat()
# "2025-11-17T15:00:00+09:00"

handle_calendar_query() (Line 228):

today = datetime.now(ZoneInfo("Asia/Seoul"))
target_date = datetime(year, month, day, tzinfo=ZoneInfo("Asia/Seoul"))

테스트 결과

Before (67%):

  • CREATE
  • READ (조회 실패)
  • DELETE

After (100%):

  • CREATE
  • READ (조회 성공)
  • DELETE (정확한 날짜 표시)

4. 트러블슈팅

invalid_grant 계속 발생

  • Gmail Passport 재인증 확인 (Step 3)
  • gmail_token.scopes 필드에 calendar 포함 확인
  • Google Cloud Console OAuth 동의 화면에 Calendar scope 추가 확인 (Step 2)

Calendar API 403 Forbidden

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

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

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

"네" 승인 응답 인식 못함

  • PostgreSQL conversation_log 시퀀스 확인 (섹션 2)
  • conversation_log에 대화 저장되는지 확인

5. E2E 테스트 시나리오

1. auth-server scope 수정 + Google Cloud Console 설정 완료
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 일정 존재

6. 교훈

Datetime 규칙

  • 절대 금지: naive datetime (timezone 없음)
  • 필수: datetime.now(ZoneInfo("Asia/Seoul"))
  • 전송: ISO 8601 with timezone (2025-11-17T15:00:00+09:00)

Microservice 간 통신

  • 모든 datetime은 timezone offset 포함
  • UTC 통일 또는 명시적 timezone 사용
  • 컨테이너 시스템 timezone 확인: docker exec [컨테이너] date

OAuth 토큰 관리

  • 코드만 수정해도 소용없음 - Google Cloud Console 설정 필수
  • 토큰은 발급 시 scope 고정 - 재인증 필수
  • DB 직접 수정으로는 해결 안 됨

7. 관련 커밋

  • 4cd0990: fix: Add timezone awareness to calendar operations
  • fd7ec1c: Revert README.md documentation changes

8. 추가 관찰 (2025-11-17)

해결된 이슈

  • calendar_approval 이후 Frontend 응답에서 항상 "죄송합니다. 응답을 생성할 수 없습니다."가 노출되던 문제
  • 원인: rb8001/main.py/api/message 핸들러가 results[0].content만 보고, calendar_handler가 내려준 message 필드는 무시함
  • 조치: results[0]에서 content가 없으면 message를 대신 사용하도록 분기 수정 → 캘린더 등록 성공 메시지가 정상 노출됨
  • 다중 날짜(예: "2025-11-07, 2025-11-14, 2025-11-21...")가 포함된 LLM 응답에서 date 필드 전체를 split('-') 하면서 time_range 파싱이 실패하던 문제 → parse_time_range()에서 첫 번째 YYYY-MM-DD만 정규식으로 추출해 사용하도록 수정
  • LLM이 날짜: 2025-11-07, 2025-11-14, 2025-11-21, 2025-11-28처럼 여러 날짜를 내려줄 때, calendar_handler.handle_calendar_create()가 모든 ISO 날짜를 리스트로 추출해 각각 create_event를 호출하도록 개선 → 7/14/21/28 네 건이 개별 일정으로 생성됨
  • 생성 단계에서 같은 날짜·시각에 이미 등록된 로컬 로그가 있으면 새 이벤트를 만들지 않고 "이미 같은 시간대에 등록된 일정이 있습니다"라고 안내하도록 중복 방지 레이어 추가

남은 문제

  • 동일한 일정 문구를 반복 입력하면 매번 새로운 이벤트가 생성됨 → 일정 중복 체크 로직 필요
  • 문서화 미완료: Slack/Frontend 사용자 가이드에서 승인 흐름과 실패 메시지 예시를 아직 설명하지 않음

후속 TODO

  1. 일정 중복 감지(최근 N분 내 같은 날짜/시간이면 안내만) 기능 추가
  2. 사용자용 가이드 문서(DOCS/guide)에 승인 흐름 및 실패 메시지 내용을 반영