# 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 ```python # 기존 (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 수정 ```bash # 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 ``` **수정 내용**: ```python # 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 재배포 ```bash # 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 저장됨 **확인**: ```bash # 51124 서버에서 cd /home/admin/ivada_project/skill-calendar python3 tests/test_google_calendar_integration.py ``` ### 방법 2: DB 직접 수정 (비권장, 임시) #### 주의 - OAuth 토큰은 발급 시 scope가 고정됨 - DB만 수정해도 Google API는 scope 부족으로 거부 - 반드시 재인증 필요 #### 확인용 쿼리 ```sql -- 현재 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. 참고 문서 - DOCS/troubleshooting/250820_happybell80_Gmail패스포트시스템완성.md - DOCS/plans/251114_skill_calendar_multiplatform_integration.md - Google Calendar API: https://developers.google.com/calendar/api/guides/overview --- --- ## 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 패턴 부족 ```python # 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하려고 시도 **해결 방안**: ```sql -- 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 패턴 확장 ```python 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 재테스트