iOS용 헤드리스 모바일 SDK: 시작하기

이 문서에서는 iOS용 헤드리스 모바일 SDK를 시작하는 방법을 설명합니다.

iOS용 헤드리스 모바일 SDK를 사용하면 사전 빌드된 CCAI Platform UI를 사용하지 않고도 CCAI Platform 기반 지원을 자체 내장 iOS 환경에 직접 추가할 수 있습니다.

CCAI Platform 브랜드 위젯을 표시하는 대신 다음을 수행합니다.

  • CCAI iOS SDK를 앱에 통합합니다.

  • 자체 화면, 탐색, 시각적 디자인을 빌드합니다.

  • SDK를 사용하여 다음 작업을 할 수 있습니다.

    • 채팅 및 음성 세션을 시작하고 관리합니다.

    • 이메일, 예약된 통화, 전환 옵션을 제공합니다.

    • 스마트 작업, 첨부파일, 세션 후 흐름 (CSAT, 설문조사, 가상 에이전트) 지원

CCAI Platform은 고객센터 로직 (라우팅, 대기열, 채널, 구성, 보고)을 처리합니다. 전체 앱 환경 (UI, 흐름, 브랜딩)을 소유합니다.

자체 빌드 대신 사전 빌드된 구성 가능한 UI를 선호하는 경우 표준 모바일 SDK를 사용하세요.

요구사항

iOS용 헤드리스 모바일 SDK를 통합하기 위한 요구사항은 다음과 같습니다.

iOS 플랫폼 요구사항

  • 최소 iOS 버전: iOS 16.6 이상

  • 언어: Swift

  • IDE: 앱에서 지원하는 최신 안정적인 Xcode 버전

  • 아키텍처: 현재 Xcode 도구 모음에서 지원하는 표준 iOS 아키텍처입니다.

앱 권한

내장 앱이 스마트 액션 (사진 촬영, 동영상 녹화, 신원 확인)의 UI를 처리하므로 Apple의 필수 개인 정보 보호 권한을 선언해야 합니다.

앱에서 데이터를 사용하는 방식을 설명하는 다음 키를 Info.plist에 추가합니다.

  • NSCameraUsageDescription: 사용자가 사진/동영상을 촬영하고 전송하거나 상담사가 요청한 스마트 작업을 수행하는 데 필요합니다.

  • NSMicrophoneUsageDescription: 즉석 음성 통화 및 소리가 포함된 동영상 녹화에 필요합니다.

  • NSPhotoLibraryUsageDescription: 사용자가 카메라 롤에서 기존 사진이나 동영상을 업로드하는 데 필요합니다.

  • NSFaceIDUsageDescription: 생체 인식 인증 스마트 작업을 지원하는 경우 필수입니다.

CCAI Platform 인스턴스 요구사항

다음 세부정보를 확인하려면 CCAI Platform 인스턴스의 개발자 설정에 액세스해야 합니다.

  • 회사 키

  • 회사 비밀번호

  • 호스트 URL - CCAI 플랫폼의 호스트 이름입니다 (예: your_subdomain.ccaiplatform.com).

이러한 값은 다음 용도로 사용됩니다.

  • 회사 키 + 호스트 URL: iOS 앱에서 SDK를 초기화합니다.

  • 회사 비밀 코드: 백엔드에서 사용자를 인증하는 데 사용되는 JSON 웹 토큰 (JWT)에 서명합니다.

푸시 알림

통화 및 특정 스마트 작업의 경우 다음이 필요합니다.

  • 표준 푸시 알림을 위한 Apple 푸시 알림 서비스 (APN) 구성입니다.

  • 수신 전화 및 특정 전화 관련 알림을 지원하는 VoIP 서비스 인증서

실습할 내용은 다음과 같습니다.

  • Apple 개발자 포털에서 APNs 및 VoIP 사용자 인증 정보를 구성합니다.

  • 변환된 인증서를 CCAI 플랫폼 관리자 포털의 설정 > 개발자 설정 > 모바일 앱에 업로드합니다.

  • 앱에서 원격 알림 및 VoIP 푸시를 등록합니다.

  • 적절한 기기 토큰을 SDK에 전달합니다.

  • 타겟 > 서명 및 기능에서 다음을 사용 설정합니다.

    • 푸시 알림 기능

    • 다음 항목이 선택된 백그라운드 모드 기능:

      • VoIP - VoIP 푸시 알림 (수신 전화, PSTN을 사용하는 스마트 작업)에 필요합니다.

      • 오디오, AirPlay, PIP 모드 - 앱이 백그라운드에 있을 때 음성 통화 오디오가 계속되도록 필요합니다.

      • 원격 알림 - 표준 APNs 푸시 전송에 필요합니다.

헤드리스 iOS SDK가 앱에 적합한 이유

iOS용 헤드리스 모바일 SDK는 다음 세 가지 레이어로 볼 수 있습니다.

CCAI Platform 플랫폼 및 SDK

SDK는 CCAI Platform 플랫폼과 안전하게 상호작용하며 다음을 제공합니다.

  • JSON 웹 토큰 (JWT)을 사용한 인증

  • 대기열 및 채널 라우팅 메타데이터 (채팅, 음성, 예약된 통화, 이메일, 외부 전환 링크)

  • 실시간 세션 상태 관리

  • 스마트 작업, 파일 첨부, 화면 공유를 위한 보안 전송 파이프라인입니다.

  • 전환 로직 및 세션 후 계층 구조 평가

iOS 앱 (UI 및 로직은 개발자가 처리)

시각적 및 탐색 환경을 완전히 제어할 수 있습니다.

  • 진입점: 예를 들어 도움말 탭 또는 문의하기 버튼

  • 메뉴: 대기열이 표시되는 방식 (예: 결제, 기술 지원)

  • 세션 내 UI: 맞춤 채팅 풍선, 통화 화면, 컨트롤

  • 앱의 기능: SDK API를 호출하여 세션을 시작하고 종료하며, SDK 이벤트를 수신하고, 뷰 컨트롤러 탐색을 유도합니다.

CCAI Platform 관리자 포털 구성

CCAI Platform 관리자는 응대 규칙 (운영 시간, 사용 가능한 채널, 대기 시간 기준, 설문조사)을 구성합니다. SDK는 이 구성을 읽고 앱에 원시 데이터와 이벤트로 노출합니다. 화면에 해당 구성을 그리는 방법을 결정합니다.

회사 사용자 인증 정보 가져오기

SDK를 통합하기 전에 CCAI Platform 인스턴스에서 사용자 인증 정보를 가져옵니다.

  1. 관리자 계정으로 CCAI 플랫폼 관리자 포털에 로그인합니다.

  2. 설정 > 개발자 설정으로 이동합니다.

  3. 회사 키 및 보안 코드에서 다음을 복사합니다.

    • 회사 키

    • 회사 비밀번호

  4. 호스트 URL 기록: CCAI 플랫폼의 호스트 이름 (예: your_subdomain.ccaiplatform.com)

다음 항목을 사용합니다.

  • iOS 앱: 회사 키 + 호스트 URL

  • 백엔드 서버에서 JWT에 서명하는 데 사용할 회사 보안 코드:

    • 최종 사용자 인증

    • CCAI Platform에서 사용하는 선택적 맞춤 데이터 또는 컨텍스트입니다.

iOS 앱에 SDK 추가

헤드리스 SDK는 모듈식 아키텍처를 사용하여 빌드됩니다. 앱에 필요한 특정 기능 모듈 (예: CCAIChat 또는 CCAIScreenShare)과 함께 핵심 CCAIKit를 설치합니다.

앱에 iOS SDK를 통합하려면 다음 단계를 따르세요.

  1. Package.swift 파일에 다음을 추가합니다.

    dependencies: [
       .package(url: "https://github.com/UJET/ccai-ios-sdk.git", from: "3.3.1")
    ],
    targets: [
       .target(
           name: "YourTargetName",
           dependencies: [
               .product(name: "CCAIKit", package: "CCAIKit")
           ]
       )
    ]
    
  2. AppDelegate 파일에서 CCAIKit를 가져옵니다.

    import CCAIKit
    
  3. 프로젝트가 SwiftUI인 경우 App 구조체에서 @UIApplicationDelegateAdaptor를 선언합니다.

    @main
    struct YourAppName: App {
       @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
       // ...
    }
    

헤드리스 SDK 초기화

앱 실행 중에 SDK를 초기화합니다. SDK의 모듈식 아키텍처로 인해 먼저 핵심 CCAI 시스템을 초기화한 다음 특정 서비스 모듈 (예: 채팅 또는 화면 공유)을 등록해야 합니다.

기본 초기화

SDK는 모든 필수 구성을 번들로 묶는 InitOptions 구조체를 사용합니다.

import CCAIKit
import CCAIChat       // If using Chat
import CCAIScreenShare // If using Screen Share

class AppDelegate: NSObject, UIApplicationDelegate, CCAIDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        // 1. Configure initialization options
        let options = InitOptions(
            key: "YOUR_COMPANY_KEY",
            urlHost: "your_subdomain.ccaiplatform.com",
            delegate: self,
            languageCode: "en",       // ISO 639 code (defaults to "en")
            cacheAuthToken: true       // Whether to cache the auth token (defaults to true)
        )

        // 2. Initialize the core SDK
        do {
            try CCAI.shared.initialize(options: options)
        } catch {
            print("Failed to initialize CCAI: \(error.localizedDescription)")
            return true
        }

        // 3. Initialize feature modules
        // Chat minimal (no options required)
        CCAI.shared.initializeChat()

        // Chat with optional configuration
        // let chatOptions = ChatOptions(
        //     delegate: webFormDelegate,           // Implement to intercept and render custom web forms within your own UI
        //     downloadTranscriptVisibility: .hideInPostChat, // Hide the post-chat download affordance
        //     greeting: "Hello! How can I help you?"
        // )
        // CCAI.shared.initializeChat(chatOptions)

        // Screen Share (optional)
        // let screenShareOptions = ScreenShareOptions(
        //     key: "YOUR_SCREEN_SHARE_KEY",
        //     domain: "your_domain.com"
        // )
        // CCAI.shared.initializeScreenShare(screenShareOptions)

        return true
    }

    // ... CCAIDelegate methods (Authentication) go here ...
}

InitOptions 구성 참조

public struct InitOptions {
    /// The company key used for authentication
    public let key: String

    /// The host URL for CCAI platform (for example, "my-unique-instance.uc1.ccaiplatform.com")
    public let urlHost: String

    /// The preferred language code for localization (defaults to "en")
    public var languageCode: String

    /// The delegate that receives SDK events and callbacks
    public weak var delegate: CCAIDelegate?

    /// Whether to cache the authentication token (defaults to true)
    public let cacheAuthToken: Bool
}

사용 가능한 SDK 서비스

초기화 후 CCAI.shared 싱글톤을 통해 다양한 서비스에 액세스할 수 있습니다.

let authService = CCAI.shared.authService
let companyService = CCAI.shared.companyService
let queueMenuService = CCAI.shared.queueMenuService
let optionsService = CCAI.shared.optionsService
let languageService = CCAI.shared.languageService
let pushNotificationService = CCAI.shared.pushNotificationService
let endUserService = CCAI.shared.endUserService
let chatService = CCAI.shared.chatService           // Only available after initializeChat()
let screenShareService = CCAI.shared.screenShareService // Only available after initializeScreenShare()
let rateService = CCAI.shared.rateService            // For CSAT ratings and survey submission
let smartActionService = CCAI.shared.smartActionService // Dedicated service for smart action lifecycle

회사 구성 가져오기

초기화 후 companyService를 사용하여 회사 수준 구성을 가져옵니다. 이는 언어 선택기를 채우거나, 회사 이름을 표시하거나, 사용자가 대기열에 들어가기 전에 지원 연락처 세부정보를 읽는 데 유용합니다.

do {
    let company = try await CCAI.shared.companyService?.get()
    print("Company: \(company?.displayName ?? "Unknown")")
} catch {
    print("Failed to get company info: \(error)")
}

최종 사용자 인증

헤드리스 모바일 SDK는 JSON 웹 토큰 (JWT)을 사용하여 사용자를 인증하고 컨텍스트 정보를 상담사의 CRM에 안전하게 전달합니다.

작동 방식

SDK는 간소화된 2단계 비동기 인증 흐름을 사용합니다.

  1. SDK에서 사용자를 인증해야 한다고 판단합니다.

  2. 비동기 함수인 CCAIDelegate 메서드(ccaiShouldAuthenticate())를 호출합니다.

  3. 앱은 회사 보안 코드를 사용하여 백엔드 서버에서 원격으로 JWT에 서명합니다.

  4. 그러면 앱이 서명된 JWT를 CCAI.shared.authService?.authenticate(jwt)에 전달하여 인증 토큰으로 교환합니다.

  5. 인증 토큰이 SDK에 반환되어 연결이 완료됩니다.

인증을 위해 CCAIDelegate 구현

앱은 CCAIDelegate 프로토콜을 구현해야 합니다. 인증이 필요한 경우 SDK는 단일 비동기 위임 메서드를 호출합니다.

CCAIDelegate 프로토콜

public protocol CCAIDelegate: AnyObject {
    /// Authenticates the end user and returns an auth token
    func ccaiShouldAuthenticate() async -> String?
}

구현 예 (Swift)

class AppDelegate: CCAIDelegate {
    func ccaiShouldAuthenticate() async -> String? {
        // 1. Sign JWT remotely on your backend server
        guard let jwt = await signJWTRemotely() else { return nil }

        // 2. Authenticate JWT using authService to get an auth token
        return try? await CCAI.shared.authService?.authenticate(jwt)
    }
}

참조 및 테스트를 위한 JWT 서명이 포함된 전체 예시

class AuthController: CCAIDelegate {
    func ccaiShouldAuthenticate() async -> String? {
        var jwt = JWT(claims: claims)

        // First, sign JWT with company secret (do this on your backend in production)
        guard let secret = self.companySecret,
              let key = secret.data(using: .utf8) else { return nil }
        let signer = JWTSigner.hs384(key: key)
        guard let encodedJWT = try? jwt.sign(using: signer) else { return nil }

        // Then authenticate JWT using authService to get an auth token
        return try? await CCAI.shared.authService?.authenticate(encodedJWT)
    }
}

CRM에 맞춤 데이터 전달

컨텍스트 데이터를 에이전트에게 전달하려면 (예: 사용자의 현재 기기 OS, 위치 또는 계정 등급) 백엔드에서 서명하기 전에 JWT 페이로드에 custom_data 객체를 삽입해야 합니다.

각 맞춤 데이터는 label (에이전트에게 표시되는 내용), value, type이 포함된 JSON 객체로 형식이 지정되어야 합니다.

지원되는 데이터 유형

  • string: 표준 텍스트 (예: 'iPhone 14 Pro')

  • number: 정수 또는 부동 소수점 (예: 1234 또는 99.99)

  • date: 밀리초를 포함하는 13자리 UTC Unix 타임스탬프입니다 (예: 1537399655992).

  • url: 표준 HTTP/HTTPS URL 형식입니다.

  • boolean: 표준 true 또는 false 값입니다.

예약된 CRM 키

CCAI Platform은 사용자를 VIP로 표시하거나 악의적인 행위자에 관해 상담사에게 경고하는 등 플랫폼의 내장 동작을 트리거하는 특정 예약 키를 지원합니다. 불리언 유형으로 형식이 지정되어야 하며, 보안 JWT 메서드를 사용하여 페이로드에 서명한 경우에만 허용됩니다.

  • reserved_verified_customer: 고객이 내부 시스템에 의해 인증되었는지 여부를 나타냅니다.

  • reserved_bad_actor: 사용자를 에이전트에게 스팸 또는 사기 계정으로 표시합니다.

  • reserved_repeat_customer: 이 고객이 최근에 지원팀에 자주 문의했는지 여부를 나타냅니다.

예약된 키가 있는 페이로드 예시

{
  "iat": 1537399656,
  "exp": 1537400256,
  "custom_data": {
    "reserved_verified_customer": {
      "label": "Verified Customer",
      "value": true,
      "type": "boolean"
    },
    "reserved_bad_actor": {
      "label": "Bad Actor",
      "value": false,
      "type": "boolean"
    },
    "reserved_repeat_customer": {
      "label": "Repeat Customer",
      "value": false,
      "type": "boolean"
    }
  }
}

인증 토큰 관리

SDK는 캐시된 인증 토큰을 수동으로 업데이트하거나 지우는 메서드도 제공합니다.

// Set a new auth token
CCAI.shared.authService?.updateAuthToken("new_auth_token")

// Clear the current token (for example, on user logout)
CCAI.shared.authService?.updateAuthToken(nil)

맞춤 데이터 JWT 페이로드 스키마

백엔드에서 회사 비밀 코드로 서명할 최종 페이로드를 구성할 때는 이 스키마를 엄격하게 따라야 합니다. 필수 iat(발급 시간) 및 exp (만료) 타임스탬프에 유의하세요.

{
  "iat": 1537399656,
  "exp": 1537400256,
  "custom_data": {
    "os_version": {
      "label": "OS Version",
      "value": "16.4",
      "type": "string"
    },
    "membership_tier": {
      "label": "Membership Tier",
      "value": "Platinum",
      "type": "string"
    },
    "ssn_last_four": {
      "label": "SSN",
      "value": "1234",
      "type": "string",
      "invisible_to_agent": true
    },
    "reserved_verified_customer": {
      "label": "Verified Customer",
      "value": true,
      "type": "boolean"
    }
  }
}

푸시 알림 사용 설정

SDK는 다음과 같은 용도로 푸시 알림을 사용합니다.

  • 수신 전화

  • 특정 스마트 작업 및 통화 관련 이벤트

  • 앱이 백그라운드에 있을 때 상태를 유지합니다.

인증서 구성

CCAI Platform에서는 CCAI Platform 관리자 포털에 저장할 두 가지 유형의 Apple 푸시 인증서가 필요합니다.

  • Apple 푸시 알림 서비스 (APNs) SSL 인증서 - 표준 원격 푸시 알림에 사용됩니다.

  • VoIP 서비스 인증서 - 수신 전화 알림 및 특정 통화 관련 스마트 작업에 사용됩니다.

두 인증서는 모두 Apple Developer 포털에서 생성되고 PEM 형식으로 변환된 후 CCAI 플랫폼 관리자 포털에 업로드됩니다.

APNs SSL 인증서 만들기

Apple의 공식 APN에 인증서 기반 연결 설정 가이드에 따라 다음 단계에 따라 APN SSL 인증서를 만드세요.

  1. developer.apple.com에 로그인하고 Certificates, Identifiers & Profiles(인증서, 식별자, 프로필)로 이동합니다.

  2. + 버튼을 선택하여 새 인증서를 만듭니다.

  3. 서비스에서 Apple 푸시 알림 서비스 SSL (샌드박스 및 프로덕션)을 선택합니다.

  4. 애플리케이션의 번들 식별자와 일치하는 앱 ID를 선택한 다음 계속을 선택합니다.

  5. Mac의 키체인 접근에서 생성된 인증서 서명 요청 (CSR)을 업로드합니다.

    • 키체인 접근 > 인증서 지원 > 인증 기관에서 인증서 요청…을 엽니다.

    • 이메일 주소를 입력하고 CA 이메일 주소는 비워 둔 다음 디스크에 저장됨을 선택하고 계속을 선택합니다.

  6. 계속을 선택한 다음 생성된 .cer 파일을 다운로드합니다.

  7. .cer 파일을 더블클릭하여 키체인에 설치합니다.

  8. Keychain Access에서 설치된 인증서를 찾아 마우스 오른쪽 버튼으로 클릭하고 내보내기…를 선택하여 .p12 파일로 저장합니다. 내보내기 비밀번호를 설정하라는 메시지가 표시됩니다.

  9. openssl을 사용하여 .p12 파일을 PEM 형식으로 변환합니다.

    # Extract the certificate
    openssl pkcs12 -in apns_certificate.p12 -out apns_cert.pem -clcerts -nokeys
    
    # Extract the private key
    openssl pkcs12 -in apns_certificate.p12 -out apns_key.pem -nocerts -nodes
    
    # (Optional) Combine into a single PEM file
    cat apns_cert.pem apns_key.pem > apns_combined.pem
    

VoIP 서비스 인증서 만들기

VoIP 서비스 인증서를 사용하면 앱이 Apple의 PushKit 프레임워크를 통해 높은 우선순위의 푸시 알림을 수신할 수 있으며, 이를 통해 앱이 종료된 상태에서 깨어나 수신 전화를 처리할 수 있습니다. 최신 공식 단계는 Apple 개발자 문서의 VoIP 서비스 인증서 만들기를 참고하세요.

  1. developer.apple.com에 로그인하고 Certificates, Identifiers & Profiles(인증서, 식별자, 프로필)로 이동합니다.

  2. + 버튼을 선택하여 새 인증서를 만듭니다.

  3. 서비스에서 VoIP 서비스 인증서를 선택합니다.

  4. 애플리케이션의 번들 식별자와 일치하는 앱 ID를 선택한 다음 계속을 선택합니다.

  5. APNs SSL 인증서에 대해 생성한 것과 동일한 인증서 서명 요청(CSR)을 업로드하거나 새 CSR을 만듭니다.

  6. 계속을 선택한 다음 생성된 .cer 파일을 다운로드합니다.

  7. .cer 파일을 더블클릭하여 키체인에 설치합니다.

  8. 키체인 접근에서 설치된 VoIP 서비스 인증서를 찾아 마우스 오른쪽 버튼으로 클릭하고 내보내기…를 선택하여 .p12 파일로 저장합니다.

  9. openssl을 사용하여 .p12 파일을 PEM 형식으로 변환합니다.

    # Extract the certificate
    openssl pkcs12 -in voip_certificate.p12 -out voip_cert.pem -clcerts -nokeys
    
    # Extract the private key
    openssl pkcs12 -in voip_certificate.p12 -out voip_key.pem -nocerts -nodes
    
    # (Optional) Combine into a single PEM file
    cat voip_cert.pem voip_key.pem > voip_combined.pem
    

CCAI Platform 관리자 포털에 인증서 업로드

  1. CCAI Platform 관리자 포털에 로그인합니다.

  2. 설정 > 개발자 설정 > 모바일 앱으로 이동합니다.

  3. APNs PEM 인증서를 업로드합니다.

  4. VoIP PEM 인증서를 업로드합니다.

푸시 알림 권한 요청

SDK는 푸시 알림 승인을 요청하는 편의 메서드를 제공합니다(iOS만 해당).

let options: UNAuthorizationOptions = [.alert, .sound]
try await CCAI.shared.pushNotificationService?.registerForPushNotifications(
    options: options
) { granted in
    if granted {
        print("Push notifications granted")
    } else {
        print("Push notifications denied")
    }
}

원격 알림 등록

AppDelegate에서 푸시 알림 대리자를 구현합니다. SDK는 토큰 전달을 위해 pushNotificationService를 제공합니다.

import CCAIKit

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    ) {
        CCAI.shared.pushNotificationService?.updatePushToken(
            data: deviceToken,
            type: .apns
        )
    }

    func application(
        _ application: UIApplication,
        didFailToRegisterForRemoteNotificationsWithError error: Error
    ) {
        CCAI.shared.pushNotificationService?.updatePushToken(
            data: nil,
            type: .apns
        )
    }
}

Xcode의 Target(타겟) > Signing & capabilities(서명 및 기능) 탭에서 원격 알림에 대해 Capabilities(기능) > Push notifications(푸시 알림) 및 Background modes(백그라운드 모드)도 사용 설정해야 합니다.

수신 푸시 알림 처리

푸시 페이로드를 수신하면 처리를 위해 SDK로 전달합니다.

func application(
    _ application: UIApplication,
    didReceiveRemoteNotification userInfo: [AnyHashable: Any],
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
    // Let the SDK determine if this push relates to an incoming call,
    // session update, or another internal event
    CCAI.shared.pushNotificationService?.handlePushNotification(userInfo)
    completionHandler(.newData)
}

SDK는 푸시가 수신 전화, 세션 업데이트 또는 기타 내부 이벤트와 관련이 있는지 확인하고 그에 따라 처리합니다.

VoIP 푸시 알림 등록

수신 전화 및 특정 PSTN 기반 스마트 액션의 경우 SDK에는 표준 APNs 토큰 외에 VoIP 푸시 토큰이 필요합니다. VoIP 푸시는 우선순위가 높게 전송되며 종료된 상태에서 앱을 깨울 수 있습니다.

PushKit를 가져오고 AppDelegate의 didFinishLaunchingWithOptions에 PKPushRegistry 만들기

import PushKit

class AppDelegate: NSObject, UIApplicationDelegate, PKPushRegistryDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        // ... SDK initialization ...

        // Register for VoIP push notifications
        let voipRegistry = PKPushRegistry(queue: DispatchQueue.main)
        voipRegistry.delegate = self
        voipRegistry.desiredPushTypes = [.voIP]

        return true
    }
}

PKPushRegistryDelegate 메서드를 구현하여 VoIP 토큰과 페이로드를 SDK에 전달

// MARK: - PKPushRegistryDelegate

func pushRegistry(
    _ registry: PKPushRegistry,
    didUpdate credentials: PKPushCredentials,
    for type: PKPushType
) {
    // Forward the VoIP token to the SDK
    CCAI.shared.pushNotificationService?.updatePushToken(
        data: credentials.token,
        type: .voip
    )
}

func pushRegistry(
    _ registry: PKPushRegistry,
    didInvalidatePushTokenFor type: PKPushType
) {
    // Clear the VoIP token
    CCAI.shared.pushNotificationService?.updatePushToken(
        data: nil,
        type: .voip
    )
}

func pushRegistry(
    _ registry: PKPushRegistry,
    didReceiveIncomingPushWith payload: PKPushPayload,
    for type: PKPushType,
    completion: @escaping () -> Void
) {
    guard type == .voIP else {
        completion()
        return
    }

    // Forward the VoIP payload to the SDK using the `handleVoIPPush`
    // extension on `CCAI` (defined in the `CCAICall` module). The SDK
    // takes ownership of the call lifecycle; invoke PushKit's completion
    // handler in the trailing closure after the SDK has accepted the
    // payload.
    CCAI.shared.handleVoIPPush(payload: payload.dictionaryPayload) { completion() }
}