calendar resourceChange Push Noti


왜?

이전 포스트를 통해 이제 구글 oAuth인증후 권한을 획득하여 calendarAPI를 호출 할 수 있다.

이제 우리는 캘린더의 변화를 인지하고 어떤 변화(추가,수정,삭제)가 일어났는지 확인해야한다.

그러기 위해서 google calendarAPI 중 puhNotification을 구현해야할 필요가있었다.

pushNotification이란?

push Notification이란 말그대로 캘린더의 변화가 있을때 웹서버로 ‘변화가 일어났어요’ 라는 callback 요청을 주는 것을 의미한다.

해당 구글 문서에는 아래와 같이 정의하고 있다.

The Google Calendar API provides push notifications that let you watch for changes to resources. You can use this feature to improve the performance of your application. It allows you to eliminate the extra network and compute costs involved with polling resources to determine if they have changed. Whenever a watched resource changes, the Google Calendar API notifies your application.

이제 윌웹에 pushNoti를 달아보자.

포스팅 내용들은 calendarApiPushNotifications를 참고하였다.

설정해야하는 항목들

구글 캘린더는 변화(resource changes)에대해 push notifications을 받기위해선 기본적으로 세가지 단계를 거쳐야한다.

도메인 등록하기

첫번째로 도메인을 검증해야한다. 구글은 다음과 같은 목적으로 검증과정을 거친다고한다.

This step is an abuse-prevention measure to stop anyone from using push to send messages to someone else’s domain.

즉, 남용방지이다. 정해진 서버로만 푸시를 받게함이다.

먼저 SearchConsole로 이동한다

searchConsole이동 => HTML파일업로드 => 인증완료

searchConsole에 step이 상세함으로 순서대로 따라하면된다.

필자는 python flask기반으로 위의 작업을 진행했었는데

위 인증을받기위해선 static하게 html파일을 접근하도록 설정해두어야한다.

그렇게하기위해 아래와 같은 코드를 추가하여 인증을 받았다.

pip install static

static한 폴더를 구분하여 접근할 수 있도록 하는 라이브러리다.

import static
app = flask.Flask(__name__, static_url_path='')

위와같이 코딩해두고 static폴더 하위의 모든 파일에대해 접근이 가능하다.

채널 만들기

이제 내가 원하는 캘린더에 변화를 감지할 watcher를 붙일 차례이다.

  1. 어느 캘린더에
  2. 어떤 id로(채널id)
  3. 어디로 콜백을 받을 것인가?

위 3가지에 대한 설정이 필요하다.

필자는 테스트로 yenos라는 캘린더에 대해 pushNoti를 받아보도록 한다.

먼저 api url을 설정해준다.

watch Request는 아래와 같은 form을 가진다고한다

POST: https://www.googleapis.com/apiName/apiVersion/resourcePath/watch

그렇다면

POST: https://www.googleapis.com/calendar/v3/calendars/yenos/events/watch

위의 URL로 post 형태로 전송하면 되는것이다.

다음으로 채널id와 콜백주소를 정해주면되는데 body에 추가해주면된다.(기본사항만 적어둔다)

body = {
        "id" : str(uuid.uuid4()),
        "type" : "web_hook",
        "address" : "{등록도메인}:{포트}/{콜백URL}"
    }

이제 마지막으로 어떠한 유저인지를 인증해야하는데 바로 이때 숨겨왔던(?) 유저토큰을 사용하면된다.

header를 아래와같이 추가해준다.

headers = {
    	'content-Type': 'application/json',
    	'Authorization' : 'Bearer ' + userAccessToken
    }

oAuth시 받은 유저의 accessToken을 authorization으로 사용하면된다 bearer

위 요청을 보내면 성공적일경우 response로

{
  "kind": "api#channel",
  "id": "01234567-89ab-cdef-0123456789ab"", // ID you specified for this channel.
  "resourceId": "o3hgv1538sdjfh", // ID of the watched resource.
  "resourceUri": "https://www.googleapis.com/calendar/v3/calendars/my_calendar@gmail.com/events", // Version-specific ID of the watched resource.
  "token": "target=myApp-myCalendarChannelDest", // Present only if one was provided.
  "expiration": 1426325213000, // Actual expiration time as Unix timestamp (in ms), if applicable.
}

위와같은 정보가 나온다. token과 expiration은 optional하게 설정하는 정보이다.

요청 보낸 직후,내가 정해놓은 콜백URL에 다음과 같은 정보가 찍힐것이다.

print(flask.request.headers)
>>POST https://mydomain.com/notifications // Your receiving URL.
X-Goog-Channel-ID: channel-ID-value
X-Goog-Channel-Token: channel-token-value
X-Goog-Channel-Expiration: expiration-date-and-time // In human-readable format; present only if channel expires.
X-Goog-Resource-ID: identifier-for-the-watched-resource
X-Goog-Resource-URI: version-specific-URI-of-the-watched-resource
X-Goog-Resource-State: sync
X-Goog-Message-Number: 1

채널이라고 되어있는 부분은 내가 정보 일것이다.

리소스 부분의 id는 캘린더에 종속되는 부분이라 같은 캘린더면 같은 id값이 반환된다. 이값을 실제 캘린더 리스트에 적히 id값은 아니고 별도로 push 요청때만 정해진 id값이다.

state는 어느상황에서 푸시가 왔는가 인데 현재 ‘sync’는 최초 푸시를 붙인상황에서 오게된다. 이외 exists, not_exists등의 경우가 있다.

다른부분은 구글 문서를 참고하기 바란다.

이제 내가 등록한 캘린더 yenos에서 일정을 추가 삭제 해보자.

아마 해당 콜백 adress로 변화사항이 있다고 알람이 올것이다.

그러나…

어떠한 변화가 이루어져있는지 구체적으로 알려주진않는다.

수정이라면 어떤 이벤트가 수정되었는지….

이를 체크하기위해 위의 pushNoti와 함께 eventList의 pushToken을 함께 이용해 sync를 맞춰주어야한다.

이는 다음 포스트에서 알아보도록한다.

마치며

구글은 api를 참 잘만들어 놓는다.

어떠한 프로젝트를 해도 구글 api와 함께라면 못할 일이 없을 것 같다는 생각이든다.

근데 왜 push noti에서 변환된것을 바로 알려주지 않는것인가?

아마 push noti가 sync외에도 사용될 수 있도록 범욕적 차원에서 명확히 구분해 놓은게 아닐까 싶다.