iOS 만 서비스 할때는 그냥 대충 php + cron 으로 push 를 돌렸었는데,

이게 백명 단위만 되어도 delay 문제가 생겨서... async 방식으로 언젠가 도입을 해야지.. 생각만 했었다.


이번에 안드로이드때문에 하게 되었으니.. 겸사겸사...

GCM 으로 iOS 도 사용할 수 있는 방법이 있다는건 봤지만,, 클라를 수정해야 했고..

이미 있는 앱도 같이 적용 + 클라 더 손대기가 귀찮아서 서버쪽을 잘 만들어보기로 했다.



APNS

우선 APNS 는 pyapns 라는 녀석으로 쉽게 asynchronous 한 push 를 구현가능하다.



pyapns 서버를 구축한 후 python 에서


import pyapns

pem_path = 'path_to_push_pem'

pyapns.configure({'HOST': 'http://localhost:7077/'})

pyapns.provision('com.example.appid', pem_path, 'production') #sandbox

push = {'aps': {'alert':'푸시 테스트', 'sound':'default'}}

pyapns.notify('com.example.appid', '### push token ###', push, async=True)


이렇게 사용하면 된다.



GCM

GCM 은 주로 node.js 로 했던 듯 하나... 난 시스템을 통일시키고 싶었다.

찾아보니, 위 pyapns 처럼 로컬에 서버를 열어두고 request를 보내면 되는 방식의 GoCM 이라는 라이브러리가 있었다.

Golang 으로 짜져 있음.



GCM 은 인증서가 필요없고 sandbox / production 구분이 없어서 더 간편하다.

간단히 POST request 만 구현하면 어떻게든 가능하지만, 난 requests 라이브러리 사용을 선호함.


import requests, json

GCM_SEND_ENDPOINT = 'http://localhost:5601/gcm/send'

token = '### token ###'

msg = {'title': '[title]', 'message': 'message'}

requests.post(GCM_SEND_ENDPOINT, data={'tokens': [token], 'payload': json.dumps(msg)})



Daemonize

위 방법대로 하면 이제 APNS / GCM 을 둘다 이용할 수 있게 되지만, 각각 웹서버를 하나 돌려야 해서 귀찮다.

당장은 그냥 쓴다고 해도 재부팅을 한다거나.. 프로세스 유지해주기가 귀찮으니까 데몬으로 만들어버리자.


pyapns 는 python-twistd :: daemon 으로 만들기

GoCM 은 GoCM :: daemon 으로 만들기


글을 각각 참고하면 된다.



Feedback / Report

APNS / GCM 각각 삭제되었거나 더이상 사용되지 않는 token 에 대한 feedback 을 제공해준다.


APNS

pyapns.feedback('com.example.appid') 를 호출하면 

[(timestamp, token), ] 

형태로 반환해준다.


token 으로 uninstalled 처리를 해주면 됨.


GCM

canonicals / notregistered 두가지 feedback 이 존재한다.

전자는 token 이 변경되었을 경우(인 것 같다. 사실 레퍼런스를 안봐서..), 후자는 앱이 삭제된 경우.


이건 그냥 GoCM README 를 보자.



Fin

드디어 Python 만을 사용하여(Go 는 컴파일 한번 하고 끝이니 논외), 하나의 시스템만으로 Asynchronous APNS / GCM 둘다 사용할 수 있게 되었다.


여기선 다루지 않았지만, 동일한 DB에 os 구분하여 token 을 저장하고, os 를 알아서 구분해서 메세지를 보내도록 하면 좀 더 관리가 쉽다.


분명히 두 OS를 같이 서비스하는 사람/업체가 많은데 내가 못찾는건지 다른 방법이 있는건지...

생각처럼 깔끔하고 쉬운 방법이 눈에 안보이네.. 흑

+ Recent posts