brunch

You can make anything
by writing

C.S.Lewis

by 웅쓰 Dec 08. 2022

iOS 앱 Push 알림 이해하기

무섭지 않아요 APNs

안녕하세요 iOS 개발하는 웅쓰입니다.

그간 이런저런 핑계로 차일피일 미루다 보니 시간이 이렇게 흘러버렸습니다,, 너무 오랜만에 인사드리네요. 앞으론 더 자주 인사드릴 수 있도록 하겠습니다 :)


이번에 브런치 앱이 새로 개편했습니다!

깜짝(?) 이벤트도 시작했는데요! 다들 앱 푸시 메시지도 잘 받으셨는지 모르겠습니다.


오늘은 이런 앱 푸시 알림이 어떤 과정을 거쳐 개개인의 iOS 앱에 도착하는지 간단하게 살펴보고자 합니다.

(안드로이드와는 다릅니다.)

앱 개발자의 관점에서 큰 흐름 위주로만 살펴봅니다.







흐름 이해하기


개별 디바이스에 직접적으로 푸시 알림을 보낼 수 있는 주체는 오직 APNs 뿐입니다.
APNs 란 Apple Push Notification server의 약자로 애플의 서버를 의미합니다.

즉 애플만이 직접적으로 디바이스에 푸시 알림을 보낼 수 있습니다.


따라서 저희(Application)는 APNs에게 우리 앱에 '푸시를 보내줘!'라고 요청해야 합니다.
이 요청이 유효한지 보고 APNs 가 푸시를 보낼지 말지를 판단합니다.

이 요청 또한 정해진 규격에 맞게 APNs와 연결한 후에 가능하고, 이를 위해 APNs에게 요청해줄 저희의 서버가 필요합니다.
문서에서 이를 Provider Server라고 칭하는데 여기선 간략하게 저희 '서버' 정도로 칭하도록 하겠습니다.

그렇다면 APNs에서는 뭘 보고 보내도 될지 판단할 수 있을까요?
당연히 사전에 앱에서 저희 서버에게 필요한 정보들을 알려줘야 합니다.

큰 흐름은 저희 서버에서 요청에 필요한 정보들을 갖고 있다가 요청하고 그 요청이 이상 없는지 확인해서 디바이스 보내는 순서입니다.


이제 요청할 때 필요한 건 뭔지, 어떻게 보내고 검증하는지를 살펴보겠습니다.



APNs에 보내려면

APNs에 요청하려면 다음 정보들이 필요합니다.

JSON payload -> 문서 & 서버

Device Token -> ?

스펙이 정의된 Request Header -> 문서 & 서버

(토큰 기반일 때만, 이하 Auth Token) Authentication Token -> ?


JSON payload, request header는 문서에 잘 나와있으니 서버에게 감사 인사를 드리며 넘어가고,,
지금은 JSON 형태의 뭔가로 요청하고 header 도 정의해야 하는구나! 정도로 넘어가면 알고 될 거 같습니다.


이제 남는 의문.

1. Device Token 이 뭐지? 어떻게 얻지?

2. 토큰 기반은 뭐지? 그럼 다른 건?

3. Auth Token 이 뭐지? 어떻게 얻지?



Device Token

Device Token은 APNs 가 기기에 푸시를 제대로 보내기 위한 고유 주소 역할을 합니다.
기기와 앱 모두 고유한 주소를 갖습니다.
당연히 두 앱이 같은 기기에 설치되어 있더라도 한 앱의 토큰은 다른 앱에서 쓸 수 없습니다.


앱이 시작되면 APNs에 요청해 Device Token을 얻을 수 있고, 이걸 우리 서버에 보내 저장하고 있도록 합니다.
참고로 이 Device Token 은 앱이 백업될 때 새로 발급되니 절대 로컬에 캐싱해두지 말라고 하네요.
(백업은 사용자가 앱을 다른 디바이스에 설치하거나, os를 재설치하는 경우와 같은 상황을 얘기하는 것 같습니다.)


물론 우리의 애플이 아무 앱에나 Device Token을 주지는 않습니다.

애플 개발자 계정을 통해 앱 번들 ID도 넣고 앱이 푸시를 사용하겠다 등등 사전 등록도 필요한데,

이건 기회가 되면 따로 다뤄보겠습니다. 아무튼 앱 정보를 미리 넣고 유료 개발자 계정이 필요합니다. ㅠ


두 가지 인증방법

앞선 필수 정보 중 payload, request header, device token 등이 푸시를 어떻게 보낼지에 대한 정보에 가까웠다면,
이제는 어떻게 검증할지에 대해 알아봐야 할 차례입니다.

토큰 기반(Token-based)과 증명서 기반(Certificate-Based) 두 가지 방식으로 인증이 가능합니다.


Certificate-Based Connection

증명서 기반의 연결은 서버가 APNs와 연결할 때 증명서를 통해 보안 연결하는 방식입니다.
서버 레벨에서 인증되기 때문에 알림 요청에서 별도의 인증 토큰은 필요하지 않습니다.
인증 토큰이 없기 때문에 개별 요청의 크기도 토큰 기반에 비해 약간 작습니다.


하지만 다수의 앱에 알림을 보내기 위해서 각각의 앱마다 개별 증명서가 필요하고,
앱 별로 개별 보안 연결 관리가 필요합니다. 증명서가 만료되거나 하면 각각을 또 다 바꿔줘야겠죠,,
결과적으로 토큰 기반이 더 관리가 쉽다고 하네요.


Token-Based Connection

토큰 기반 인증의 경우 요청을 보낼 때 Auth Token 이 필요합니다.
보낼 때 토큰을 함께 보내니 stateless 하게 APNs와 통신할 수 있는데요, APNs 가 증명서를 찾을 필요도 없고 서버의 다른 정보도 필요 없으니 보다 빠르게 통신할 수 있습니다.
개별 요청에 인증 토큰이 포함되니 증명서 인증 방식보다는 요청의 크기가 약간 큽니다.


토큰 방식은 여러 서버에서 같은 토큰을 사용할 수 있고,
하나의 토큰으로 사내 여러 앱에 사용할 수 있어 증명서 방식보다 관리가 쉽습니다.

대신 애플이 제공한 공급자 서명키로 최소 한 시간에 한 번 이상 암호화해서 업데이트가 필요합니다.


*공급자 서명키를 만들면
10 글자의 Key ID와 텍스트 파일로 된 p8 확장자 키를 받습니다.
Key ID는 JSON Payload에 포함되어야 합니다.

따라서 사전에 서버에는 Key ID와 p8 키가 모두 등록되어있어야 하겠죠?
키는 한 번 발급받으면 다시 재발급받을 수 없으니 잘 관리해야 합니다 :)
잃어버리면 revoke 하고 새로 발급받아야 함.



이렇게 저희 서버가 보낼 환경이 다 갖춰졌다면 APNs에게 요청해 사용자에게 푸시 알림을 보낼 수 있습니다.

JSON payload

Device Token

Request Header

Authentication Token  or 연결 단계에서 Certifiacate를 통한 인증








얼마 전 개발 phase에서 푸시 알림이 안 오는 이슈가 있었어서 왜 이럴까를 놓고 한참을 고민한 적이 있었습니다.

저희는 앱에서 개발 phase 가 나눠져 있고, (번들 ID 다름)

서버의 phase 도 나눠져 있습니다. (API 다름)

본문에서 다루진 않았지만 APNs도 production과 development 2가지 서버를 제공합니다.


토큰 방식을 사용하고 있으므로 서명키 key, 그에 등록된 앱, 서버에서 정확히 어느 APNs 서버로 보내는지 등에 대한 걸 알아야 했는데 이에 대한 이해가 부족하니 정확히 어디를 수정해야 하는지, 어디를 확인해야 하는지도 파악이 잘 안 돼서 헤맸던 것 같습니다.


항상 머릿속에 그림이 잘 안 그려지고 두리뭉실하게만 알고 있었는데, 이번에 정리하면서 많은 의문이 해소되었습니다. 다른 분들에게도 도움이 되었으면 좋겠습니다.

읽어주셔서 감사합니다.




.

.

.




새로워진 브런치에서 만나요 :)

https://brunch.co.kr/@brunch/319




참고

Sending Notification Requests to APNs

Establishing a Certificate-Based Connection to APNs

Establishing a Token-Based Connection to APNs

Registering Your App with APNs





    




브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari