PHP로 C2DM 푸시 이용하기

0.

아이폰의 푸시 서비스는 애플에서 제공하는 APNS(Apple Push Network Server)를 이용한다. 개별 아이폰 기기를 식별하는 udid 와 앱스토어의 개발자 계정만 갖고 있으면 푸시 서비스가 가능한 것. 왜 그랬는지는 도무지 모르겠지만 얼마전까지만 해도 안드로이드는 그러한 서비스를 갖고 있지 않았다. 따라서 무진장 귀찮게 커스텀 푸시 서비스를 구축하거나, 엄청난 배터리 소모와 트래픽을 요구하는 polling 방식을 사용할 수 밖에 없었던 것. 구글이 뒤늦게나마 정신 차려서 만든 것이 C2DM. 구글이 개발자에게 제공하는 푸시 네트웍 서버 되시겠다.

1.

안드로이드 내부에서 설정하는 부분은 그렇게 어렵지도 않거니와, 참고자료가 무진장 많다. 따라서 설명은 생략.
나보다 훨씬 더 잘 설명해주실 분들의 링크로 대신한다.

http://blog.naver.com/PostView.nhn?blogId=huewu&logNo=110087032264
http://eddykudo.com/91
http://code.google.com/android/c2dm/

2.

안드로이드 쪽의 개발은 전혀 문제가 없었는데, 전혀 문제 될 거라 생각하지 못했던 서버 쪽에서 문제가 발생했다.
구글이 제공하는 친절한 예제는 죄다 자바 서블릿 기반이라 PHP 로 만들어야 하는 내게는 쓸데 없는(그리고 머리 아픈) 자바 코드일 뿐이었다.
뭐 어쨌든 그 덕에 한동안 쓸 일 없었던 curl 을 징그럽게 공부했다. (그러나 늘 그렇듯 풀고보니 사소한 실수였음)

[code php]

$ch = curl_init(); 
 
curl_setopt($ch, CURLOPT_URL, "https://www.google.com/accounts/ClientLogin"); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
 
$data = array('accountType' => 'HOSTED_OR_GOOGLE', 
'Email' => '아이디', 
'Passwd' => '비번', 
'source'=>'test-1.0', 
'service'=>'ac2dm'); 
  
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_POST, true); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 

$result = curl_exec($ch);
$auth = substr(strstr($result, "Auth="), 5);
$auth = substr($auth, 0, strlen($auth)-1);

curl_setopt($ch, CURLOPT_URL, "https://android.apis.google.com/c2dm/send");

$data = "registration_id=등록아이디"."&collapse_key=1"."&data.msg=메세지";
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

$headers = array(
    "Content-Type: application/x-www-form-urlencoded",
    "Content-Length: ".strlen($data),
    "Authorization: GoogleLogin auth=$auth"
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
echo $result."\n";

curl_close($ch);

[/code]

정리 전혀 안된 명백한 테스트코드.
php 의 curl 모듈(일반적으로 기본설치)을 이용해 구글 ClientLogin 의 Authentication 을 획득하고, 그 복잡다단한 키를 헤더에 포함하여 c2dm 서버에 날리면 된다.
아아주 쉽다.

3.

사실 저 부분에서 포인트는

[code lang-php]
$auth = substr($auth, 0, strlen($auth)-1);
[/code]

달랑 요 한 줄이다.
보는 바와 같이 끝에 붙은 글자 하나 날리는 간단한 구문.
요 한 줄 때문에 한나절은 꼬박이 삽질했다.
단일 헤더 프로퍼티에는 절대, 무조건, 반드시! 개행문자가 삽입되면 안된다.
그런데 Google ClientLogin 으로 요청하면 SID, AUTH 등의 개별 키들을 개행문자로 구분해버리니 쉴 새 없이 Unauthorized 메세지가 뜬 것이다.

4.

비전공자가 보면 귀신 시나락까먹는 소리고, 이 블로그 방문객의 대다수가 비전공자이기 때문에 요런 글 웬만하면 안 쓰자-라는 주의였는데.
일하면서든, 혼자 뚜닥거리면서든 이렇게 작은 경험 올려주시는 많은 개발자 분들 덕택에 쉽게쉽게 갈 때가 많아
나름 보은의 차원에서 짧게 두드려봤다.

덧,
혹 C2DM 시도하다 해결되지 않는 문제가 있다면 댓글 남겨주시길.
해결은 못 해드려도, 같이 고민은 해드릴게요. ㅋ

6 thoughts on “PHP로 C2DM 푸시 이용하기

    1. 민상k

      엔하늘님 오랜만이시네요ㅋ APNS 를 이용하려면 개발자 계정과 보내려는 아이폰 디바이스의 고유 식별 아이디인 udid 가 필요합니다. ^^

      Reply
  1. tita

    안녕하세요. 님 자료로 cd2m 서버 연동에 많은 도움을 받았습니다.
    제가 하고있는건 별도의 php 서버를 하나두고 폰->서버->C2DM서버->폰 이렇게 구현중인데요.
    서버에서 폰으로 메세지 수신시 한글이 깨지는 문제가 있습니다..ㅠㅠ

    $data = “registration_id=$registration_id”.”&collapse_key=$collapse_key”.”&data.msg=”.urlencode($msg);

    이런식으로 PHP서버에서 보낼때 urlencode를 써보았는데도 한글이 이상한특수문자로 날아옵니다..
    영문은 정상적으로 수신되구요… 혹시 이런 현상을 보신적 있으신지요…

    메일 주소는 stendless@gmail.com 입니다.

    Reply
    1. 민상k

      답변이 늦어 죄송합니다. 블로그를 자세히 관리하는 편이 아니라서요ㅋ
      percent encoding 형태로 전송되는 경우라면 urlencode / urldecode 관련 문제를 확인해보시고 식별 불가능한 특수문자 혹은 깨진 문자로 전송되는 경우라면 각 서버의 기본 인코딩 셋을 확인해보셔야 할듯 합니다.

      참고로 C2DM 서버는 UTF-8 인코딩셋을 사용합니다.
      테스트용으로 코드 자체에 한글을 입력하셨다면 해당 파일의 인코딩셋이 EUC-KR 로 지정되어 있는지 확인하시고,
      DB 에서 쿼리를 통해 뽑는 경우 해당 테이블의 인코딩셋을 확인해보시기 바랍니다.

      도움이 되셨길 바래요.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>