Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- uiscrollview
- map
- combine
- Observable
- swift documentation
- collectionview
- UITextView
- Refactoring
- HIG
- 리펙터링
- 리펙토링
- MVVM
- 애니메이션
- Clean Code
- Xcode
- Human interface guide
- RxCocoa
- rxswift
- swiftUI
- 리팩토링
- ribs
- 클린 코드
- tableView
- clean architecture
- ios
- SWIFT
- 스위프트
- Protocol
- UICollectionView
- uitableview
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] iOS remote push notification (서버 푸시) - Braze Appboy SDK 연동을 통한 이해 본문
iOS 응용 (swift)
[iOS - swift] iOS remote push notification (서버 푸시) - Braze Appboy SDK 연동을 통한 이해
jake-kim 2021. 8. 3. 23:37iOS 푸시 원리
- 앱 > 애플 서버에 토큰 요청 > 앱에서 토큰 수신 > push 서버에 토큰 등록 > push서버에서 가공된 내용 + token 앱에서 수신 > 애플서버에 다시 전송 > 애플서버에서 앱으로 최종 푸시 전송
-
- 앱에서 push를 “p8 or .p12 certificate 파일” 인증서와 함께 애플서버에 HTTP로 토큰 달라고 요청
- 애플 서버는 인증서, 프로파일을 받고 인증 후 토큰 응답
- 받은 토큰값과 메시지를 앱에서 push 서버로 POST방식으로 요청
- push서버에서 POST요청을 받아 내용을 가공 > 애플 서버에 요청 (push서버에서는 APNs키가 등록되어 있어야함)
- 애플 서버는 토큰을 확인하고 토큰의 주인에 해당하는 아이폰 기기에 push 전송
앱 가동
- APNs(Apple Push Notification service)에 사용자 기기를 등록 요청
let center = UNUserNotificationCenter.current()
center.delegate = self
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
center.requestAuthorization(options: options) { granted, _ in
/// 사용자가 푸시 권한에 관해 선택한 결과를 Braze에 전달
Appboy.sharedInstance()?.pushAuthorization(fromUserNotificationCenter: granted)
guard granted else { return }
DispatchQueue.main.async {
/// APNs에서 push를 받기위해 등록 요청
UIApplication.shared.registerForRemoteNotifications()
}
}
- APNs로부터 token 수신 (주의: simulator에서는 해당 메소드 실행되지 않는것을 주의)
/// APNs에 해당 디바이스가 등록이 완료된 경우, Braze에 토큰 등록
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Appboy.sharedInstance()?.registerDeviceToken(deviceToken)
}
애플로부터 최종 Push 알림을 받은 경우
- push 서버에 로깅을 위해 전송
/// push 알림을 받았을때 Braze에 전달하여 push 분석과 로깅하는데 사용
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
Appboy.sharedInstance()?.register(application,
didReceiveRemoteNotification: userInfo,
fetchCompletionHandler: completionHandler)
}
Push가 온 경우 처리
- UNUserNotificationCenterDelegate 사용
extension AppDelegate: UNUserNotificationCenterDelegate {
/// foreground에 있는 동안의 push 표출 옵션
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
/// push를 탭한 경우 처리
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
// TODO: Deeplink 처리
/// 사용자가 push에 관해 상호작용한 후 알림 응답을 braze로 전달
Appboy.sharedInstance()?.userNotificationCenter(center,
didReceive: response,
withCompletionHandler: completionHandler)
}
}
* 전체 AppDelegate 코드
import UIKit
import AppboyKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
/// Braze 웹사이트에서 등록한 key값을 이용하여 Braze SDK 연동
Appboy.start(withApiKey: ServiceConfiguration.appboyAPIKey,
in: application,
withLaunchOptions: launchOptions,
withAppboyOptions: [ABKSessionTimeoutKey: 60])
// TODO: 해당 코드는 테스트 용도이므로 user id를 AccessToken으로 교체가 되면 해당 코드 삭제
/// Braze user id 등록
let uuid: String
if let storedUUID = UserDefaultsManager.AppConfiguration.uuid {
uuid = storedUUID
} else {
uuid = UUID().uuidString
UserDefaultsManager.AppConfiguration.uuid = uuid
}
Log.debug("UUID = \(uuid)")
Appboy.sharedInstance()?.changeUser(uuid)
registerRemoteNotification()
return true
}
// MARK: - Notification
/// 사용자의 기기를 APNs(Apple Push Notification service)에 등록
private func registerRemoteNotification() {
let center = UNUserNotificationCenter.current()
center.delegate = self
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
center.requestAuthorization(options: options) { granted, _ in
/// 사용자가 푸시 권한에 관해 선택한 결과를 Braze에 전달
Appboy.sharedInstance()?.pushAuthorization(fromUserNotificationCenter: granted)
guard granted else { return }
DispatchQueue.main.async {
/// APNs에서 push를 받기위해 등록 요청
UIApplication.shared.registerForRemoteNotifications()
}
}
}
/// APNs에 해당 디바이스가 등록이 완료된 경우, Braze에 토큰 등록
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Appboy.sharedInstance()?.registerDeviceToken(deviceToken)
}
/// push 알림을 받았을때 Braze에 전달하여 push 분석과 로깅하는데 사용
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
Appboy.sharedInstance()?.register(application,
didReceiveRemoteNotification: userInfo,
fetchCompletionHandler: completionHandler)
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
/// foreground에 있는 동안의 push 표출 옵션
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
/// push를 탭한 경우 처리
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
/// 사용자가 push에 관해 상호작용한 후 알림 응답을 braze로 전달
Appboy.sharedInstance()?.userNotificationCenter(center,
didReceive: response,
withCompletionHandler: completionHandler)
}
}
cf) deeplink를 처리할 때 url을 수신하는 델리게이트
- SceneDelegate.swit 파일이 존재하면 scene(_:opeenURLContexts:)에서 url 수신
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
urlHandler?.handle(url)
}
- SceneDelegate.swift파일이 없고 AppDelegate.swift파일만 존재한다면, application(_:open:options:) -> Bool 메소드 이용
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
urlHandler?.handle(url)
return true
}
'iOS 응용 (swift)' 카테고리의 다른 글
[iOS - swift] UILabel에서 특정 문자열의 font, 색상 변경 방법 (attributedText) (2) | 2021.08.05 |
---|---|
[iOS - swift] shadow 그림자 효과 top, left, right, bottom 방향 주는 방법 (layer.shadow) (1) | 2021.08.04 |
[iOS - swift] 주석 처리, 퀵 헬프 주석, //, /// (0) | 2021.08.01 |
[iOS - swift] 내부 content size에 따라 superview 크기도 변하는 동적 뷰 (0) | 2021.07.30 |
[iOS - swift] intinsicContentSize, sizeToFit, sizeThatFits (UILabel 크기를 텍스트에 맞추는 방법) (0) | 2021.07.30 |
Comments