iOS앱 Push 알림 만들기

·2023년 7월 10일
0

프로젝트 공부

목록 보기
10/33


이 글은 ios앱의 push기능을 만들고자 하는 Spring 서버를 위한 글이다-2023.08.21(수정)

알림이 보내지는 대략적인 과정

  1. ios(프론트)에서 APNS를 통해 deviceToken을 가져온다.
    이때 device token이란 각 기기마다 정해지는 토큰을 말하며, 어플을 재설치할 경우 토큰은 바뀐다.
  2. 회원가입, 로그인 등을 통해 디바이스 토큰을 서버에 저장한다.
  3. Service를 구현하며 만약 알림이 울릴 특정 조건에 달성할 경우 Notification 알림을 실행한다.
  4. 이때 시간대별 알림은 @Scheduled 어노테이션을 이용해 설정할 수 있으며, 그 외에는 메소드를 불러오는 방식으로 실행할 수 있다. (API가 아님)
  5. 메소드가 불리면 알림 내용과 deviceToken 등이 HttpURLConnection을 이용해 fcm 서버에게 전송되게 된다.

APNs란?!

APNs는 Apple Push Notification server의 약자로, 애플의 서버를 의미한다.

개별 디바이스에 직접적으로 푸시 알림을 보낼 수 있는 주체는 오직 APNs뿐이며, 파이어베이스를 사용하여도 파이어베이스가 APN인터페이스를 구현하고 있기 때문에 우리는 결국 APNS를 거쳐 푸시 알림을 보내게 된다

보낼 기기를 설정할 수 있는 deviceToken이 APNs를 통해 얻을 수 있다.
참고로 IOS는 APNs를 통해, android는 fcm토큰을 이용하는 것으로 알고 있다.

Provider Server?

Application은 APNs에게 우리 앱에 "푸시를 보내줘"라고 요청해야하는데 이때 Provider Server가 정해진 규격에 맞게 APNs과 연결하여 요청을 보낸다.

APNs에 요청하기 위해 필요한 정보

  1. JSON payload
  2. Device Tocken
  3. 스펙이 정의된 Request Header

Json payload

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

💡Create the JSON Payload

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에 들어갈 것들

푸쉬알림의 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"
}
KeyValue typeDescription
alertDictionary(or String)보통 문자열이 들어갑니다. 딕셔너리를 사용해서 문자열을 Localize할수도 있습니다. 알림에 표시되는 메시지가 alert에 해당합니다.(title과 같이 Dictionary 안에 content를 만들 수 있다)
badgeNumber앱아이콘 오른쪽상단에 표시되는 숫자를 나타냅니다. 0으로 설정하면 숫자가 사라집니다.
soundStringApp의 Bundle이나 Library/Sounds Container에 있는 사운드 파일 재생합니다. default 넣으면 시스템 사운드가 나온다. 긴급 알람 울리려면 dictionary 로 넣으면 되며 커스텀 사운드의 재생시간은 30초 이하로 제한됩니다.
thread-idString알림을 그룹화하기 위한 키 값을 입력합니다. iOS14부터 제공된 기능으로, Notification Grouping을 위해 사용됩니다. 하나의 앱에 수신되는 여러 Notification이 있을 경우,이걸 지정하면 해당 알림들이 하나의 그룹으로 묶여서 사용자가 놓치지 않도록 돕는데 도움이 됩니다.
content-availableNumber백그라운드 앱 업데이트를 위한 silent remote notification에서 사용됩니다.이 값을 1로 설정하면 silent notification으로 설정됩니다. 이러면 기기가 알림을 수신하면 백그라운드에서 앱을 실행시키고, application(_:didReceiveRemoteNotification:fetchCompletionHandler:) 을 호출합니다.여기서 데이터 업데이트를 수행할 수 있습니다.
categoryStringNotification 카테고리를 식별하는 데 사용되는 문자열 입니다.사용자가 알림을 탭했을 때 실행할 동작과 관련있습니.UNNotificationCategory 객체를 사용해서 Notification 카테고리를 정의&등록할 수 있습니다.Notification 카테고리를 사용하면 사용자가 알림을 탭할 때 미리 정의된 동작을 수행할 수 있습니다. 아래 사진과 같은 커스텀 액션을 사용할 때 필요합니다.

notification service
notification service 는 payload 를 가로채서 notification 에 띄우고자 하는 데이터를 재구성하는 것입니다. 이미지, 비디오 등 미디어를 다운로드하여 첨부할 수 있습니다. payload 는 4KB 로 용량이 제한되기때문에 URL 로 전달해야합니다. URL 로 다운로드하는 일을 service 에서 하게 됩니다.

중요!

  • notification 의 payload 에 고객정보나 신용카드 번호와 같은 민감한 데이터를 포함하지 마십시오. 만약 민감한 데이터를 포함해야 하는 경우, 추가하기 전에 암호화 하십시오. notification service app extension 을 사용해서 데이터를 해독할 수 있습니다
  • Payload는 4096바이트를 초과하면 안됩니다

Device Token

Device Tocken = APNs가 기기에 푸시를 제대로 보내기 위한 고유 주소 역할

  • 기기와 앱은 모두 고유한 주소를 가지며, 두 앱이 같은 기기에 설치되었더라도 한 앱의 토큰은 다른 앱에서 쓸 수 없다.

앱이 시작 -> APNs에 요청해 Device Token 획득 -> 서버에 보내 저장

Device Token은 앱이 백업될 때 새로 발급되기 때문에 절대 로컬에 캐싱하지 말 것

Device Token 검색

  1. iOS에서 device token을 요청하기 위해 UIApplication.shared.registerForRemoteNotifications()을 호출
  2. 등록에 성공해 토큰을 받으면 AppDelegate의 application(_:didRegisterForRemoteNotificationsWithDeviceToken:) 함수가 불림
  3. 실패할 경우 application(_:didFailToRegisterForRemoteNotificationsWithError:)가 사용됨 - 실패예시) 네트워크 연결 x, App의 code-signing이 잘못됨, APNs 서머 동작 x
func 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)
    }
}

Token-Based Connection

토큰 기반 인증의 경우 요청을 보낼 때 Auth Token이 필요하다.

  • 보낼 때 토큰을 함께 보내기 때문에 stateless
  • APNs가 증명서를 찾을 필요 없기 때문에 증명서 기반의 연결과 달리 속도 빠름.
  • 증명서 기반의 연결과 달리 요청의 크기가 약간 큼.

    애플이 제공한 공급자 서명키로 최소 한 시간에 한 번 이상 암호화해서 업데이트 필요


iOS push의 종류

사용자한테 메시지를 전달하는 3가지 방법

  • 메시지(알림창) - alert
  • 로컬 알림 - UserNotification
  • 서버 알림(푸시 알림) - APNs
  1. 로컬 푸시(Local Notification) : 앱 자체로부터 push를 앱에 띄우는 것
  2. 서버 푸시(Server Notification) : 서버로부터 앱에 띄우는 것

iOS push 알림 최대 글자수

ios 푸시 알림 최대 발송 글자수 = 256byte(서버 푸시 기준)

  • 한글은 한 글자당 6byte
  • 영문, 특수문자, 띄어쓰기는 한 글자당 1byte
  • 하지만 전송 시 JSON 내의 모든 문자열 수가 255byte 이하여야 해서 실제 보내지는 메세지 내용은 가변적으로 200byte정도다.

참고
iOS 앱 Push 알림 이해하기
iOS) Generating a Remote Notification - APNs payload 알아보기
[iOS/APNs]Notification의 payload에는 무엇이 있을까?
[iOS] 사용자 알림(User Notifications) - (1) APNs - 1

profile
개발자가 되고싶은 낭랑 24세

0개의 댓글

관련 채용 정보