research

Google Calendar Event Schema

Google Calendar Event Schema

API v3 기준. 출처: Google Calendar API v3 reference.


Event Resource 핵심 필드

{
  "kind": "calendar#event",
  "id": "string",
  "iCalUID": "string",
  "status": "confirmed|tentative|cancelled",
  "summary": "string",
  "description": "string",
  "location": "string",
  "colorId": "string",
  "eventType": "default|birthday|focusTime|outOfOffice|workingLocation|fromGmail",

  "start": { "date": "2024-03-22", "dateTime": "RFC3339", "timeZone": "Asia/Seoul" },
  "end":   { "date": "...",        "dateTime": "...",     "timeZone": "..." },
  "endTimeUnspecified": false,

  "recurrence": ["RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR"],
  "recurringEventId": "string",
  "originalStartTime": { "date": "...", "dateTime": "...", "timeZone": "..." },

  "attendees": [{
    "email": "string",
    "displayName": "string",
    "responseStatus": "needsAction|declined|tentative|accepted",
    "organizer": false,
    "optional": false
  }],

  "reminders": {
    "useDefault": true,
    "overrides": [{ "method": "email|popup|sms", "minutes": 30 }]
  },

  "transparency": "opaque|transparent",
  "visibility": "default|public|private|confidential",

  "created": "RFC3339",
  "updated": "RFC3339",
  "creator": { "email": "...", "self": true },
  "organizer": { "email": "..." }
}

핵심 개념

all-day vs timed

  • start.date만 있으면 all-day (시간 없음)
  • start.dateTime이 있으면 timed (timeZone 필수)

반복 이벤트 처리

  • 마스터 이벤트: recurrence 필드에 RRULE 배열
  • 인스턴스: recurringEventId로 마스터 참조, originalStartTime 보존
  • 로컬에서 반복 이벤트를 "전개(expand)"하려면 자체 RRULE 파서 필요 (rrule.js 등)

eventType 활용

  • focusTime — Google Calendar의 집중 시간 블록
  • outOfOffice — 부재 표시
  • workingLocation — 재택/사무실 구분
  • Naran에서 이 타입을 활용하면 컨텍스트 기반 스케줄링 가능

syncToken 패턴 (incremental sync)

1. 최초: events.list() 전체 조회 → nextSyncToken 저장
2. 이후: events.list(syncToken=saved) → 변경분만 수신
3. 410 GONE → syncToken 만료, 전체 재조회

Naran 설계 시사점

| GCal 필드 | Naran에서 할 것 | |-----------|----------------| | id + iCalUID | 외부 sync key로 저장 | | start.date vs start.dateTime | event_type: 'allday' | 'timed' 구분 | | recurrence | 로컬에서는 RRULE 원문 저장 + 전개 여부 플래그 | | recurringEventId | 인스턴스 추적 (삭제/수정 전파 처리) | | status: cancelled | soft delete 처리 | | eventType | 커스텀 context 태그로 매핑 |