PushKit은 표준 APNs를 우회하여 지연 시간이 짧은 VoIP 알림을 전달하는 iOS 프레임워크입니다. Apple Developer Documentation (2025)에 따르면, PushKit은 백그라운드에서도 5초 이내에 통화 전달을 보장합니다. VoIP 알림은 사용자에게 배너를 표시할 필요 없이 직접 처리되므로, 이 프레임워크는 iOS에서 메신저 및 화상 통화 앱을 위한 기본 도구가 됩니다.
핵심 요점
PushKit은 iOS 8에서 도입된 Apple의 프레임워크로, VoIP 애플리케이션을 위해 지연 시간이 짧은 푸시 알림을 제공합니다. 표준 APNs(Apple Push Notification service)와 달리, PushKit은 수신 전화가 올 때 앱이 백그라운드에서 깨어날 수 있도록 하여 사용자에게 알림을 표시하지 않습니다. 이는 음성 및 영상 통화 앱에 매우 중요합니다 — 앱이 종료된 상태에서도 사용자는 즉시 전화를 받을 수 있습니다. Apple WWDC 2024에 따르면, PushKit은 전 세계적으로 매일 20억 개 이상의 VoIP 알림을 처리합니다.
이 메커니즘은 기기와 Apple 푸시 서버 간의 직접 연결을 기반으로 하여 표준 알림 채널을 우회합니다. 앱 서버가 VoIP 알림을 보내면 전용 PushKit 서버를 통과하여 최대 우선순위로 기기에 전달됩니다. 시스템은 백그라운드에서 앱을 깨우고 델리게이트 메서드 pushRegistry:didReceiveIncomingPushWithPayload:forType:을 호출합니다. 앱은 페이로드를 수신하고, 통화를 처리하며, 확인을 위해 완료 핸들러를 호출합니다. Apple 사양에 따르면 전송부터 처리까지의 전체 주기는 5초를 넘지 않습니다.
PushKit과 APNs의 주요 차이점은 전달 메커니즘과 처리 방식에 있습니다. APNs는 배너, 소리, 배지를 표시하는 표준 알림 채널을 사용하는 반면, PushKit은 시각적 알림 없이 앱에 직접 데이터를 전달합니다. 아래는 주요 특성의 비교표입니다.
| 특성 | PushKit | APNs |
|---|---|---|
| 전달 우선순위 | 높음 (즉시 전달) | 중간 (지연 가능) |
| 앱 깨우기 | 예, 백그라운드에서 | 알림을 탭할 때만 |
| 배너 표시 | 아니요 | 예 (선택 사항) |
| 용도 | VoIP, 통화, 영상 통화 | 모든 유형의 알림 |
| 페이로드 | JSON만, 미디어 없음 | JSON + 첨부 파일 |
PushKit은 또한 리치 미디어 첨부 파일을 지원하지 않으며 일반 마케팅 알림에 사용할 수 없습니다. Apple은 PushKit 사용을 엄격히 통제합니다 — 앱에 명시적인 VoIP 기능이 있어야 하며, 그렇지 않으면 검토에서 거부됩니다. APNs는 다른 모든 시나리오에서 보편적인 솔루션으로 남아 있습니다.
PushKit을 사용하려면 앱이 PKPushRegistry를 통해 pushType .voIP로 등록해야 합니다. 등록은 첫 실행 시 한 번 수행되며, 그 후 시스템이 고유한 푸시 토큰을 생성하여 델리게이트를 통해 전달합니다. 이 토큰은 이후 VoIP 알림 전송을 위해 앱 서버로 전송됩니다. 아래는 Swift에서 PushKit 등록 및 토큰 획득의 예입니다.
import PushKit
let registry = PKPushRegistry(queue: DispatchQueue.main)
registry.delegate = self
registry.desiredPushTypes = [.voIP]
// MARK: - PKPushRegistryDelegate
func pushRegistry(
_ registry: PKPushRegistry,
didUpdate pushCredentials: PKPushCredentials,
for type: PKPushType
) {
let deviceToken = pushCredentials.token
.map { String.format("%02x", $0) }
.joined()
sendVoIPTokenToServer(deviceToken)
}
PKPushType.voIP로 desiredPushTypes를 호출한 후, 시스템이 자동으로 VoIP 알림 수신 권한을 요청합니다. pushRegistry:didUpdatePushCredentials:forType: 메서드에서 앱은 기기 토큰을 Data로 수신하며, 이를 16진수 문자열로 변환하여 서버에 전송합니다. 토큰은 각 기기마다 고유하며 앱 재설치 시 변경됩니다 — 서버는 토큰 업데이트를 처리해야 합니다.
func pushRegistry(
_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: @escaping VoidBlock
) {
guard let caller = payload.dictionaryPayload["caller"] as? String else {
completion()
return
}
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .generic, value: caller)
provider.reportNewIncomingCall(
with: UUID(),
update: update,
completion: { error in
if let error = error {
print("Call error: \(error)")
}
completion()
}
)
}
didReceiveIncomingPushWith 메서드에서 앱은 통화 데이터와 함께 페이로드를 수신합니다. 발신자 정보를 추출한 후, CallKit 프레임워크의 CXCallUpdate를 생성하여 수신 전화 화면을 표시합니다. 처리 후 완료 핸들러를 호출하는 것이 중요합니다 — 그렇지 않으면 시스템이 타임아웃으로 인해 앱 프로세스를 강제 종료할 수 있습니다. 최대 처리 시간은 30초이며, 이후 iOS는 알림을 미처리된 것으로 간주합니다.
PushKit은 CallKit과 긴밀하게 통합되어 있습니다 — iOS에서 시스템 통화 인터페이스를 표시하기 위한 프레임워크입니다. 앱이 PushKit을 통해 VoIP 알림을 수신하면, 통화를 관리하기 위해 CXProvider와 CXCallController를 생성해야 합니다. CallKit은 앱이 최소화된 상태에서도 잠금 화면에 수신 전화 화면을 자동으로 표시합니다. 아래는 CallKit 제공자 설정 예시입니다.
let config = CXProviderConfiguration(localizedName: "MyApp")
config.supportsVideo = true
config.maximumCallGroups = 1
config.maximumCallsPerCallGroup = 1
config.supportedHandleTypes = [.phoneNumber, .generic]
let provider = CXProvider(configuration: config)
provider.setDelegate(self, queue: nil)
CXProviderConfiguration은 통화 화면의 모양과 동작을 정의합니다 — 앱 이름, 비디오 지원, 동시 통화 수. VoIP 앱의 경우 PushKit과 CallKit의 통합이 필수입니다: 이것이 없으면 시스템이 수신 전화 화면을 표시하지 않으며, 사용자는 통화를 놓치게 됩니다. Apple은 PushKit을 사용하는 모든 앱에 CallKit 사용을 요구합니다.
PushKit 사용에는 Apple이 설정한 여러 엄격한 제한이 따릅니다. 프레임워크는 VoIP 기능에만 사용할 수 있습니다 — PushKit을 통해 마케팅 알림을 보내려는 모든 시도는 앱 차단으로 이어집니다. 페이로드 크기는 4KB를 초과할 수 없으며, 첨부 파일 없이 JSON 데이터만 포함할 수 있습니다. iOS 13부터 Apple은 VoIP 알림 전송 빈도에 제한을 도입했습니다 — 기기당 분당 하나의 알림으로 제한됩니다. 서버는 이 제한을 준수해야 하며, 그렇지 않으면 알림이 시스템에 의해 거부됩니다. PushKit은 iOS 시뮬레이터에서도 작동하지 않습니다 — 테스트는 실제 기기에서만 가능합니다.
VoIP 알림 페이로드는 사용자 지정 통화 데이터가 포함된 JSON 사전입니다. APNs와 달리 PushKit은 표준 alert, badge, sound 필드를 지원하지 않습니다 — 모든 데이터는 개발자가 정의합니다. 일반적인 구조에는 발신자 식별자(caller), 통화 유형(음성 또는 영상), 방 또는 세션 식별자 및 타임스탬프가 포함됩니다. 4KB 제한 내에서 공간을 절약하기 위해 각 필드의 크기는 최소화해야 합니다. Apple은 잠금 화면에 수신 전화 화면을 표시하는 데 필요한 데이터만 페이로드에 포함하고, 나머지 정보(아바타, 메시지 기록)는 사용자가 응답한 후 별도의 네트워크 요청을 통해 로드할 것을 권장합니다. 최소 페이로드 예: { "caller": "안나", "caller_id": "+79161234567", "type": "audio", "room": "uuid-room-1234", "ts": 1718534400 }. 페이로드의 모든 키는 짧고 명확해야 하며, 앱 버전 간 호환성을 위해 서버 측에서 문서화되어야 합니다.
PushKit으로 작업할 때는 전달 실패 및 연결 끊김을 처리해야 합니다. 기기가 오프라인 상태이거나 네트워크에서 연결이 끊어진 경우, VoIP 알림이 전달되지 않습니다 — PushKit은 저장 및 재전송을 지원하지 않으며, APNs는 최대 24시간 동안 알림을 저장하여 재시도합니다. 서버는 전달되지 않은 알림을 독립적으로 추적하고 연결이 복원될 때 재시도해야 합니다. 이를 위해 push kit feedback service 메커니즘이 사용됩니다 — 실패 이유와 함께 전달되지 않은 알림 목록을 반환합니다. 서버 분석을 통해 VoIP 알림 전달 성공 모니터링을 설정하고 성공 전달률이 95% 아래로 떨어지면 개발자에게 알리는 것이 좋습니다. PushKit 시스템은 기기에 활성 인터넷 연결이 있는 경우에만 전달을 보장합니다 — 연결이 없으면 알림이 영구적으로 손실되며, 이는 보장된 전달로 안정적인 VoIP 통화 시스템을 설계할 때 고려하는 것이 중요합니다.
자주 묻는 질문
PushKit은 배너를 표시하지 않고 수신 전화 시 앱이 백그라운드에서 깨어날 수 있도록 하는 지연 시간이 짧은 VoIP 알림 전달을 위한 Apple 프레임워크입니다. 메신저 및 화상 통화 앱에서 사용됩니다.
PushKit은 전달 우선순위가 더 높으며 사용자에게 알림을 표시하지 않고 백그라운드에서 앱을 깨웁니다. APNs는 배너와 함께 알림을 전달하며 사용자 상호 작용 없이 통화 처리를 위해 앱을 깨울 수 없습니다.
예, Apple은 시스템 수신 전화 화면을 표시하기 위해 PushKit을 CallKit과 통합하도록 요구합니다. CallKit이 없으면 앱이 잠금 화면에 수신 전화를 표시할 수 없어 VoIP 기능이 무용지물이 됩니다.
.voIP 유형으로 PKPushRegistry를 생성하고 pushRegistry:didUpdatePushCredentials:forType: 델리게이트 메서드를 구현한 후 토큰을 얻을 수 있습니다. 토큰은 Data로 전달되며 서버로 전송하기 위해 16진수 문자열로 변환해야 합니다.
PushKit의 최대 페이로드 크기는 4KB입니다. 데이터는 JSON 형식이어야 합니다. 미디어 첨부 파일은 지원되지 않습니다. iOS 13부터 기기당 분당 하나의 VoIP 알림으로 제한됩니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.