Sending Notification Requests to APNs

Panther·2021년 8월 17일
0

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns

"Transmit your remote notification payload and device token information to Apple Push Notification service (APNs)."

애플 푸시 노티피케이션 서비스(APNs)에 원격 노티피케이션 페이로드 및 기기 토큰 정보를 전송합니다.

Overview

사용자에게 보낼 노티피케이션을 갖고 있는 경우 제공자는 포스트 요청을 구성하고 이 요청을 애플 푸시 노티피케이션 서비스(APNs)에 전송해야 합니다. 요청은 아래 정보를 포함하고 있어야 합니다.

  • 보내길 원하는 JSON 페이로드입니다.
  • 사용자의 기기에 대한 기기 토큰입니다.
  • 노티피케이션을 어떻게 전달할지 구체화하고 있는 요청 헤더 필드입니다.
  • 토큰 기반 인증의 경우 제공자 서버의 현재 인증 토큰입니다.

서버의 포스트 요청을 받으면 APNs는 제공된 인증 토큰 혹은 서버의 인증서를 사용해서 요청을 검증합니다. 검증이 성공적이면 APNs는 사용자의 기기를 식별하기 위해 제공받은 기기 토큰을 사용합니다. 이후 해당 기기에 JSON 페이로드를 전송하기 위한 시도를 합니다.

Establish a Connection to APNs

제공자 서버와 아래 중 한 가지 서버에 연결을 설정하기 위해 HTTP/2와 TLS 1.2 혹은 이후 버전을 사용하시기 바랍니다.

  • 개발자 서버: api.sandbox.push.apple.com:443
  • 생산 서버: api.push.apple.com:443

Tip
어떠한 서버든 APNs와 커뮤니케이션하고자 할 때 포트 2197(포트 443 대신)을 사용할 수도 있습니다. APNs 트래픽이 방화벽을 통할 수 있도록 하면서도 다른 HTTPS 트래픽은 차단할 수 있습니다.

전달하는 앱은 생선 서버를, 테스트를 위해서는 개발 서버를 사용하시기 바랍니다. 많은 원격 노티피케이션을 보내는 경우 성능 향상을 위해 이러한 서버에 다중 연결을 설정할 수 있습니다. 예를 들어 여러 제공자 서버를 갖는 경우 각각은 각자의 연결을 설정할 수 있습니다.

APNs는 각 연결에 대해 다중 동시성 스트림을 지원하지만 스트림의 구체적인 수는 가정하지 않습니다. 정확한 숫자는 서버 로드에 따라 달라지고, 제공자 인증서를 사용하는지, 인증 토큰을 사용하는지에 따라 달라집니다. 예를 들어 인증 토큰을 사용하는 경우 APNs는 유효한 인증 토큰을 갖는 요청을 포스트할 때까지 오직 하나의 스트림만을 허용합니다. APNs는 HTTP/2 PRIORITY 프레임을 무시합니다. 그렇기 때문에 스트림에 이를 보내지 않아야 합니다.

제공자 인증서가 취소된 경우 혹은 인증 토큰을 취소시킨 경우에는 APNs 연결을 모두 닫고 문제를 수정해야 하며 새 연결을 열어야 합니다. APNs는 GOAWAY 프레임을 보내서 연결을 종료시킬 것입니다. GOAWAY 프레임의 페이로드 원인 키를 갖는 JSON 데이터를 포함하며, 원인 키는 연결 종료의 이유를 나타냅니다.

애플 공식 문서에서 원인 키에 대한 값의 리스트를 보려면 링크를 참고하라고 하지만 링크가 주어져 있지 않습니다. 정확하지 않지만 아래 링크의 Table 4가 이를 나타내고 있을 수 있어서 링크를 남기겠습니다.

Handling Notification Responses from APNs
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/handling_notification_responses_from_apns
https://velog.io/@panther222128/Handling-Notification-Responses-from-APNs

Create and Send a POST Request to APNs

사용자의 기기에 노티피케이션을 보내려면 포스트 노티피케이션을 구성하고 APNs에 보내야 합니다. HTTP/2와 TLS를 사용해 생성된 연결을 거쳐 이 요청을 전송하시기 바랍니다. 포스트 노티피케이션을 구성하려면 아래 정보를 미리 갖추고 있어야 합니다.

  • 노티피케이션을 받기 위한 사용자 기기를 식별할 수 있는 기기 토큰입니다. Registering Your App with APNs를 보시기 바랍니다.
  • 현재 인증 토큰입니다.(토큰 기반 인증 사용 시에만 해당합니다.) Establishing a Token-Based Connection to APNs를 보시기 바랍니다.
  • JSON 데이터로 구체화된 노티피케이션의 페이로드입니다. Generating a Remote Notification을 보시기 바랍니다.

Registering Your App with APNs
https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns
https://velog.io/@panther222128/Registering-Your-App-with-APNs

Establishing a Token-Based Connection to APNs
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns
https://velog.io/@panther222128/Establishing-a-Token-Based-Connection-to-APNs

Generating a Remote Notification
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
https://velog.io/@panther222128/Generating-a-Remote-Notification

Note
인증서 기반 인증을 사용하고 있는 경우 TLS 연결 설정 시 APNs에 제공자 인증서를 전송해야 합니다. 더 많은 정보는 Establishing a Certificate-Based Connection to APNs를 보시기 바랍니다.

Establishing a Certificate-Based Connection to APNs
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_certificate-based_connection_to_apns
https://velog.io/@panther222128/Establishing-a-Certificate-Based-Connection-to-APNs

선행하는 데이터와 더불어 Table 1에 있는 헤더를 요청에 추가해야 합니다. 몇 가지 헤더 필드는 노티피케이션 전달이 요구됩니다. 다른 헤더는 선택적이거나 토큰 기반 인증을 사용하는지, 인증서 기반 인증을 사용하는지에 따라 달라집니다.

Table 1 Header fields for a POST request

Header fieldDescription
:method(필수사항) 값 포스트입니다.
:path(필수사항) 기기 토큰으로의 경로입니다. 이 헤더의 값은 <device_token>이 사용자의 기기를 식별하는 16진수 바이트인 곳인 /3/device/<device_token>입니다. 앱은 원격 노티피케이션 등록 시 이 기기 토큰에 대한 바이트를 받습니다. Registering Your App with APNs를 보시기 바랍니다.
authorization(토큰 기반 인증의 경우에 필수사항) 이 헤더의 값은 <provider_token>이 특정 주제에 노티피케이션을 보내는 권한을 갖는 암호화된 토큰이 있는 곳인 베어러 <provider_token>입니다. 인증서 토큰 기반 인증을 사용하는 경우 이 헤더는 APNs가 무시합니다. 더 많은 정보는 Establishing a Token-Based Connection to APNs를 보시기 바랍니다.
apns-push-type(watchOS 6 및 이후 버전에서 필수사항이며, macOS, iOS, tvOS, iPadOS에서 권정됩니다.) 이 헤더의 값은 정확히 노티피케이션 페이로드의 컨텐츠를 반영합니다. 불일치하는 경우 혹은 헤더가 필요한 시스템을 놓치고 있는 경우 APNs는 에러를 반환하고, 노티피케이션의 전달을 지연시키거나 버립니다.
apns-id노티피케이션에 대한 고유 ID인 정식 UUID입니다. 노티피케이션 전송 시 에러가 발생하면 APNs는 서버에 에러를 보고할 때 이 값을 포함합니다. 정식 UUID는 32 소문자 16진수이며, 형태 8-4-4-4-12에서 하이픈으로 구분되는 다섯 개 그룹으로 표시됩니다. 예시는 123e4567-e89b-12d3-a456-4266554400a0입니다. 이 헤더를 생략하면 APNs는 UUID를 생성하고 이것의 응답에서 반환합니다.
apns-expiration노티피케이션이 더 이상 유효하지 않은 시점인 날짜입니다. 이 값은 초로 나타나는 유닉스 에포크(UTC)입니다. 이 값이 0이 아니면 APNs는 노티피케이션을 저장하고 구체화된 날짜까지 필요한 경우 시도를 반복하면서 적어도 한 번은 전달을 시도합니다. 값이 0인 경우 APNs는 노티피케이션 전달을 한 번만 시도하고 저장하지 않습니다.
apns-priority노티피케이션의 우선순위입니다. 이 헤더를 생략하면 APNs는 노티피케이션 우선순위를 10으로 설정합니다. 노티피케이션을 즉시 보내려면 10으로 구체화해야 합니다. 사용자 기기의 전원에 따라 노티피케이션을 보내려면 5를 구체화해야 합니다.
apns-topic노티피케이션에 대한 주제입니다. 일반적으로 주제는 앱의 번들 ID/앱 ID입니다. 푸시 노티피케이션의 타입에 따라 접미사를 가질 수 있습니다. PushKit VoIP 혹은 watchOS complication 노티피케이션을 지원하는 인증서를 사용하고 있다면, 앱의 번들 아이디와 함게 이 헤더를 포함시켜야 하고 해당하는 경우에 적합한 접미사를 포함시켜야 합니다. APNs에 토큰 기반 인증을 사용하고 있는 경우 정확한 번들 ID 및 접미사 조합을 갖는 이 헤더를 포함시켜야 합니다. 앱 ID에 대한 더 많은 정보는 Register an App ID를 보시기 바랍니다.
apns-collapse-id사용자를 위해 다중 여러 노티피케이션을 하나의 노티피케이션으로 통합시키는 데 사용하는 아이덴티파이어입니다. 각 노티피케이션 요청은 사용자의 기기에서 표시되기 위한 새 노티피케이션을 발생시킨비다. 두 번 이상 같은 노티피케이션을 전송할 때 요청을 통합시키기 위해 이 헤더에서 같은 값을 사용하시기 바랍니다. 이 키의 값은 64 바이트를 초과하지 않아야 합니다.

Registering Your App with APNs
https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns
https://velog.io/@panther222128/Registering-Your-App-with-APNs

Establishing a Token-Based Connection to APNs
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns
https://velog.io/@panther222128/Establishing-a-Token-Based-Connection-to-APNs

Register an App ID
https://help.apple.com/developer-account/#/dev1b35d6f83

apns-push-type 헤더 필드는 여섯 개의 유효한 값을 갖습니다. 아래 설명은 언제 그리고 어떻게 이 값을 사용하는지 설명하고 있습니다.

alert
사용자 상호작용을 트리거하는 노티피케이션에 대한 알림 푸시 타입을 사용하시기 바랍니다(예를 들어 알림, badge, 소리). 푸시 타입으로 설정하면 apns-topic 헤더 필드는 주제로 앱의 번들 ID를 사용해야 합니다. 더 많은 정보는 Generating a Remote Notification을 보시기 바랍니다.

노티피케이션이 사용자로부터 즉각적인 액션을 요구하는 경우 노티피케이션 우선순위를 10으로 설정해야 합니다. 그렇지 않은 경우는 5를 사용합니다.

알림 푸시 타입은 watchOS 6 및 이후 버전을 요구합니다. 이 타입은 macOS, iOS, tvOS, iPadOS에서 권장됩니다.

Generating a Remote Notification
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
https://velog.io/@panther222128/Generating-a-Remote-Notification

background
백그라운드에서 컨텐트를 전달하면서 사용자 상호작용을 트리거하지 않는 노티피케이션인 백그라운드 푸시 타입을 사용할 수 있습니다. 이 푸시 타입을 설정하면 apns-topic 헤더 필드는 주제로 앱의 번들 ID를 사용해야 합니다. 우선순위를 항상 5로 설정해야 합니다. 10으로 사용하면 에러가 발생합니다. 더 많은 정보는 Pushing Background Updates to Your App를 보시기 바랍니다.

백그라운드 푸시 타입은 watchOS 6 및 이후 버전을 요구합니다. 이 타입은 macOS, iOS, tvOS, iPadOS에서 권장됩니다.

Pushing Background Updates to Your App
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app
https://velog.io/@panther222128/Pushing-Background-Updates-to-Your-App

voip
들어오는 Voice-over-IP(VoIP) 호출에 대한 정보를 제공하는 voip 푸시 타입 노티피케이션을 사용할 수 있습니다. 더 많은 정보는 Responding to VoIP Notifications from PushKit을 보시기 바랍니다.

이 푸시 타입을 설정하면 apns-topic 헤더 필드는 끝에 .voip가 붙는 앱의 번들 ID를 사용해야 합니다. 인증서 기븐 인증을 사용하고 있는 경우 VoIP 서비스에 인증서를 등록해야 합니다. 주제는 1.2.840.113635.100.6.3.4 혹은 1.2.840.113635.100.6.3.6 확장의 부분입니다.

voip 푸시 타입은 watchOS에서 사용이 불가능합니다. macOS, iOS, tvOS, iPadOS에서 권장됩니다.

Responding to VoIP Notifications from PushKit
https://developer.apple.com/documentation/pushkit/responding_to_voip_notifications_from_pushkit
https://velog.io/@panther222128/Responding-to-VoIP-Notifications-from-PushKit

complication
watchOS 앱의 complication에 대한 업데이트 정보를 포함하는 complication 푸시 타입 노티피케이션을 사용할 수 있습니다. 더 많은 정보는 Keeping Your Complications Up to Date를 보시기 바랍니다.

이 푸시 타입을 설정하면 apns-topic 헤더 필드는 끝에 .complication이 붙는 것을 갖는 앱 번들 ID를 사용해야 합니다. 인증서 기반 인증을 사용하는 경우 WatchKit 서비스에 인증서를 등록해야 합니다. 주제는 1.2.840.113635.100.6.3.6 확장의 부분입니다.

complication 푸시 타입은 watchOS 및 iOS에서 권장됩니다. macOS, tvOS, iPadOS에서 사용은 불가능합니다.

Keeping Your Complications Up to Date
https://developer.apple.com/documentation/clockkit/keeping_your_complications_up_to_date

fileprovider
파잎 제공자 확장에 대한 변경사항 신호를 보내기 위해 fileprovider 푸시 타입을 사용할 수 있습니다. 이 푸시 타입을 설정하면 apns-topic 헤더 필드는 끝에 .pushkit.fileprovider가 붙는 앱 번들 ID를 사용해야 합니다. 더 많은 정보는 Using Push Notifications to Signal Changes를 보시기 바랍니다.

fileprovider 푸시 타입은 watchOS에서 사용이 불가능합니다. macOS, iOS, tvOS, iPadOS에서 권장됩니다.

Using Push Notifications to Signal Changes
https://developer.apple.com/documentation/fileprovider/content_and_change_tracking/tracking_your_file_provider_s_changes/using_push_notifications_to_signal_changes
https://velog.io/@panther222128/Using-Push-Notifications-to-Signal-Changes

mdm
관리되는 기기에게 MDM 서버로 접근할 것을 알려주는 mdm 푸시 타입 노티피케이션을 사용할 수 있습니다. 이 푸시 타입을 설정하면 MDM 푸시 인증서의 제목에 있는 UID 특성의 주제를 사용해야 합니다. 더 많은 정보는 Device Management를 보시기 바랍니다.

mdm 푸시 타입은 watchOS에서 사용이 불가능합니다. macOS, iOS, tvOS, iPadOS가 권장됩니다.

Device Management
https://developer.apple.com/documentation/devicemanagement

APNs는 반복적으로 헤더 키 및 값을 저장하는 방지하는 HPAC(header compression for HTTP/2)의 사용을 요구합니다. APNs는 HPACK을 위한 작은 동적 테이블을 유지합니다. 해당 테이블이 채워지는 것을 피하려면 아래 방법을 통해서 헤더를 인코딩해야 합니다. 특히 여러 스트림을 사용하는 경우 그렇습니다.

  • :path 및 권한 값을 인덱싱 없는 리터럴 헤드 필드로 인코딩해야 합니다.
  • apns-id, apns-expiration, apns-collapse-id 값을 초기인지 혹은 후속적인 요청인지에 따라 다르게 인코딩합니다.
    • 처음 이 헤더를 보낼 때 동적 테이블에 헤더 필드를 추가하기 위해서 증가하는 인덱싱을 갖는 것으로 인코딩해야 합니다.
    • 후속 요청의 경우 인덱싱 없는 리터럴 헤더 필드로 이 헤더를 인코딩해야 합니다.
  • 다른 모든 필드를 인덱싱을 가는 헤더 필드로 인코딩해야 합니다.

노티피케이션의 컨텐트를 갖는 JSON 페이로드를 요청의 바디에 넣어야 합니다. JSON 페이로드는 압축되지 않아야 하고 최대 크기는 4 킬로바이트(4096 바이트)로 제한됩니다. Voice over Internet Protocol(VoIP) 노티피케이션의 경우 최대 크기는 5 킬로바이트(5120 바이트)입니다.

Listing 1은 인증 토큰을 갖는 구성된 요청의 샘플을 보여줍니다.

Listing 1 A POST request with an authentication token

Listing 1 A POST request with an authentication token
HEADERS
  - END_STREAM
  + END_HEADERS
  :method = POST
  :scheme = https
  :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
  host = api.sandbox.push.apple.com
  authorization = bearer eyAia2lkIjogIjhZTDNHM1JSWDciIH0.eyAiaXNzIjogIkM4Nk5WOUpYM0QiLCAiaWF0I
		 jogIjE0NTkxNDM1ODA2NTAiIH0.MEYCIQDzqyahmH1rz1s-LFNkylXEa2lZ_aOCX4daxxTZkVEGzwIhALvkClnx5m5eAT6
		 Lxw7LZtEQcH6JENhJTMArwLf3sXwi
  apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
  apns-push-type = alert
  apns-expiration = 0
  apns-priority = 10
  apns-topic = com.example.MyApp
DATA
  + END_STREAM
  { "aps" : { "alert" : "Hello" } }

Listing 2는 인증서와 함께 사용을 위해 구성된 샘플 요청을 보여줍니다. APNs는 기본값 주제로 앱의 번들 ID를 사용합니다.

Listing 2 A POST request relying on a certificate

HEADERS
  - END_STREAM
  + END_HEADERS
  :method = POST
  :scheme = https
  :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
  host = api.sandbox.push.apple.com
  apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
  apns-push-type = alert
  apns-expiration = 0
  apns-priority = 10
DATA
  + END_STREAM
  { "aps" : { "alert" : "Hello" } }

Service Guarantees

APNs는 많은 노력을 기울이는 서비스입니다.

  • 같은 기기 토큰에 전송된 노티피케이션은 재정렬될 것입니다.
  • 오프라인 기기로의 노티피케이션은 APNs 오프라인 저장소 정책을 적용합니다. APNs는 각각의 번들 ID에 기기 토큰 하나당 하나의 푸시만을 저장합니다.
  • 우선순위 5를 갖는 노티피케이션은 그룹화될 것이며, 사용자의 기기에 버스트로 전달될 것입니다. 또한, 조절될 수 있고, 오프라인 저장소에 저장될 수 있으며, 어떤 경우에는 전달되지 않을 수 있습니다. 정확한 동작은 사용자가 애플리케이션과 상호작용하는 방식에 따라 결정되고 기기의 전원 상태에 따라 결정될 것입니다.

Best Practices While Connecting to APNs

아래는 고려해볼 수 있는 APNs 모범사례입니다.

  • APNs는 2021년 3월 13일 부로 레거시 바이너리 프로토콜을 지원하지 않습니다. 가능한 빠르게 HTTP/2 기반 API로 업데이트할 것을 권장합니다.
  • 각각의 연결 전에 APNs 서버 이름을 확인하기 위해 캐시되지 않은 DNS 쿼리를 만들어야 합니다. 이는 모든 제공자로부터 푸시 트래픽이 모든 APNs 서버에 걸쳐서 잘 배포될 것을 보장해줄 것입니다.
  • 처리량 및 요청 응답 처리 시간에 따라 새 연결을 열어야 합니다.
  • 선택적인 연결에 대한 푸시 버스트르 피해야 합니다. 많은 연결에 대해 푸시 트래픽을 다양화하는 것은 모든 APNs 서버에 걸쳐 애플리케이션에 푸시 트래픽을 배분합니다.
  • 가능하다면 연결을 재사용해야 합니다. 대부분의 경우에 연결은 몇 시간에서 며칠 동안 재사용될 수 있습니다. 연결이 대부분 유휴상태라면 비활성화의 한 시간 후 HTTP PING 프레임을 전송할 것입니다. 연결을 재사용하는 것은 적은 대역폭 및 적은 CPU 소비를 자주 나타낼 것입니다.
  • apns-id 헤더에 대해 고유한 값을 사용해야 합니다. 이는 APNs 서버에 대한 디버깅을 도울 것입니다.
  • 각각의 푸시와 함께 apns-push-type 헤더를 전송해야 합니다. 푸시 타입은 사용자가 노티피케이션에 대한 최선의 경험을 가질 수 있도록 설계됩니다. 헤더를 놓치는 경우 최근의 기능 및 향후의 기능이 작동하지 않을 수 있습니다. 이 헤더가 요구되거나 선택적이라면 확인을 위해 Table 1과 기능 문서를 참고하시기 바랍니다. 각각의 푸시에 대한 APNs의 반환된 상태에 주의를 기울여야 하고, 애플이케이션을 위해 적합한 액션을 취해야 합니다. 더 많은 정보는 Handling Notification Responses from APNs를 보시기 바랍니다.
  • APNs 연결을 위해 인증서를 사용하고 있으면 새 인증서를 가져오는 것과 현재 인증서의 만료 전에 서비스를 배포해야 함을 기억해야 합니다.
  • 기기 토큰 크기에 대한 가정을 하지 않아야 합니다.

Handling Notification Responses from APNs
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/handling_notification_responses_from_apns
https://velog.io/@panther222128/Handling-Notification-Responses-from-APNs

See Also


Server Tasks

Generating a Remote Notification

JSON 페이로드로 사용자의 기기에 노티피케이션을 전송합니다.

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
https://velog.io/@panther222128/Generating-a-Remote-Notification

Handling Notification Responses from APNs

APNs 서버가 반환한 상태 코드에 응답합니다.

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/handling_notification_responses_from_apns
https://velog.io/@panther222128/Handling-Notification-Responses-from-APNs

Pushing Background Updates to Your App

앱을 깨우고 백그라운드에서 업데이트하는 노티피케이션을 전달합니다.

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app
https://velog.io/@panther222128/Pushing-Background-Updates-to-Your-App


0개의 댓글