이 글은 ios앱의 push기능을 만들고자 하는 Spring 서버를 위한 글이다-2023.08.21(수정)
APNs는 Apple Push Notification server의 약자로, 애플의 서버를 의미한다.
개별 디바이스에 직접적으로 푸시 알림을 보낼 수 있는 주체는 오직 APNs뿐이며, 파이어베이스를 사용하여도 파이어베이스가 APN인터페이스를 구현하고 있기 때문에 우리는 결국 APNS를 거쳐 푸시 알림을 보내게 된다
보낼 기기를 설정할 수 있는 deviceToken이 APNs를 통해 얻을 수 있다.
참고로 IOS는 APNs를 통해, android는 fcm토큰을 이용하는 것으로 알고 있다.
Application은 APNs에게 우리 앱에 "푸시를 보내줘"라고 요청해야하는데 이때 Provider Server가 정해진 규격에 맞게 APNs과 연결하여 요청을 보낸다.
JSON payload 를 사용하여 사용자의 기기에 notifications 를 보냅니다.
remote notifications 은 JSON payload 형태로 사용자에게 중요한 정보를 전달합니다.
payload 는 수행하려는 user interactions `alert`, `sound`, or `badge` 를 지정하고,
앱이 notification 에 응답하는데 필요한 custom data 를 포함합니다
서버에서 fcm으로 알림과 관련된 데이터를 보낼 때 우리는 json형태로 보내야 한다.
따라서 우리는 ApnsConfig, Notification 등의 클래스를 만든 다음 Message에 합치고, 이를 json형태로 바꿔 전달해야한다.
JSON > Message = MulticastMessage > Notification(>title=body) = ApnsConfig(>Aps>sound) = deviceToken
JSON dictionary 를 사용해서 remote notification 에 대한 payload 를 지정합니다. 이 dictionary 안에 Table 1 에 나열된 하나 이상의 Apple-defined keys를 포함하는 dictionary 인 aps 키를 포함합니다.
시스템에 alert 를 표시하거나 sound 를 재생하거나, 앱 아이콘에 badge 를 지정하도록 지시하는 키를 포함할 수 있습니다. 또한 notification 을 백그라운드에서 silently 처리하도록 지시를 할 수도 있습니다. 자세한 정보는 Pushing Background Updates to Your App 참조하세요.
Apple-defined keys 외에도 payload 에 custom keys 를 추가해서앱, notification service app extension, notification content app extension 에 조금의 데이터를 전달할 수 있습니다.
푸쉬알림의 Payload는 보통 위와같은 형태입니다. json타입이고 root key값은 "aps"입니다.
그럼 "aps" 딕셔너리에 담기는 주요 키 값들에 대해서 알아보겠습니다.
{ //Dictionary 형태의 aps
"aps" : {
"alert" : {
"title" : "Game Request",
"subtitle" : "Five Card Draw",
"body" : "Bob wants to play poker"
},
"category" : "GAME_INVITATION"
},
"gameID" : "12345678"
}
Key | Value type | Description |
---|---|---|
alert | Dictionary(or String) | 보통 문자열이 들어갑니다. 딕셔너리를 사용해서 문자열을 Localize할수도 있습니다. 알림에 표시되는 메시지가 alert에 해당합니다.(title과 같이 Dictionary 안에 content를 만들 수 있다) |
badge | Number | 앱아이콘 오른쪽상단에 표시되는 숫자를 나타냅니다. 0으로 설정하면 숫자가 사라집니다. |
sound | String | App의 Bundle이나 Library/Sounds Container에 있는 사운드 파일 재생합니다. default 넣으면 시스템 사운드가 나온다. 긴급 알람 울리려면 dictionary 로 넣으면 되며 커스텀 사운드의 재생시간은 30초 이하로 제한됩니다. |
thread-id | String | 알림을 그룹화하기 위한 키 값을 입력합니다. iOS14부터 제공된 기능으로, Notification Grouping을 위해 사용됩니다. 하나의 앱에 수신되는 여러 Notification이 있을 경우,이걸 지정하면 해당 알림들이 하나의 그룹으로 묶여서 사용자가 놓치지 않도록 돕는데 도움이 됩니다. |
content-available | Number | 백그라운드 앱 업데이트를 위한 silent remote notification에서 사용됩니다.이 값을 1로 설정하면 silent notification으로 설정됩니다. 이러면 기기가 알림을 수신하면 백그라운드에서 앱을 실행시키고, application(_:didReceiveRemoteNotification:fetchCompletionHandler:) 을 호출합니다.여기서 데이터 업데이트를 수행할 수 있습니다. |
category | String | Notification 카테고리를 식별하는 데 사용되는 문자열 입니다.사용자가 알림을 탭했을 때 실행할 동작과 관련있습니.UNNotificationCategory 객체를 사용해서 Notification 카테고리를 정의&등록할 수 있습니다.Notification 카테고리를 사용하면 사용자가 알림을 탭할 때 미리 정의된 동작을 수행할 수 있습니다. 아래 사진과 같은 커스텀 액션을 사용할 때 필요합니다. |
notification service
notification service 는 payload 를 가로채서 notification 에 띄우고자 하는 데이터를 재구성하는 것입니다. 이미지, 비디오 등 미디어를 다운로드하여 첨부할 수 있습니다. payload 는 4KB 로 용량이 제한되기때문에 URL 로 전달해야합니다. URL 로 다운로드하는 일을 service 에서 하게 됩니다.
중요!
- notification 의 payload 에 고객정보나 신용카드 번호와 같은 민감한 데이터를 포함하지 마십시오. 만약 민감한 데이터를 포함해야 하는 경우, 추가하기 전에 암호화 하십시오. notification service app extension 을 사용해서 데이터를 해독할 수 있습니다
- Payload는 4096바이트를 초과하면 안됩니다
Device Tocken = APNs가 기기에 푸시를 제대로 보내기 위한 고유 주소 역할
앱이 시작 -> APNs에 요청해 Device Token 획득 -> 서버에 보내 저장
Device Token은 앱이 백업될 때 새로 발급되기 때문에 절대 로컬에 캐싱하지 말 것
UIApplication.shared.registerForRemoteNotifications()
을 호출application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
함수가 불림application(_:didFailToRegisterForRemoteNotificationsWithError:)
가 사용됨 - 실패예시) 네트워크 연결 x, App의 code-signing이 잘못됨, APNs 서머 동작 xfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 여기선 launch 시에 했지만, launch가 끝나고 사용자에게 알림 허용 등의 권한 체크를 먼저 하고 수락하면 진행하는게 좀 더 깔끔합니다.
UIApplication.shared.registerForRemoteNotifications()
return true
}
// MARK: APNs
extension AppDelegate {
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNs으로 부터 받은 디바이스 토큰:" + deviceToken.description)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("APNs 등록 및 디바이스 토큰 받기 실패:" + error.localizedDescription)
}
}
토큰 기반 인증의 경우 요청을 보낼 때 Auth Token이 필요하다.
애플이 제공한 공급자 서명키로 최소 한 시간에 한 번 이상 암호화해서 업데이트 필요
사용자한테 메시지를 전달하는 3가지 방법
ios 푸시 알림 최대 발송 글자수 = 256byte(서버 푸시 기준)
참고
iOS 앱 Push 알림 이해하기
iOS) Generating a Remote Notification - APNs payload 알아보기
[iOS/APNs]Notification의 payload에는 무엇이 있을까?
[iOS] 사용자 알림(User Notifications) - (1) APNs - 1