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 태그로 매핑 |