iOS

✏️ 로컬 푸시 알림 보내기(Local Notification)

_yunie 2024. 6. 19. 11:42

안녕하세요!

최근 푸시 알림의 종류와 로컬 알림을 생성하고 사용자에게 전송하는 방법에 대해 배웠습니다!

수많은 앱이 푸시 알림을 사용하고 있는 만큼 개념이나 구현방법을 정리해 두면 좋을 것 같아 이렇게 글을 씁니다 :)

 

 

❓푸시 알림

푸시 알림이라는 개념이 조금 생소하실 분들을 위해 소개해드리자면 아래 이미지처럼 흔히 알림 센터에 오고 쌓이는 모든 알림 들을 푸시 알림이라고 합니다

 

🧐 푸시 알림은 왜 필요한걸까요?

앱은 기본적으로 Background 상태(현재 스크린에 보이고 있지 않은 상태)가 되면 모든 기능에 제한을 가지게 됩니다

아무래도 현재 눈앞에 있는 앱이 아닌 그 밑의 앱을 사용한다고 생각하면 말이 안 되죠?

 

여기서 예시로 은행앱을 이야기해 볼게요

만약 은행앱이 Background 상태로 가있다고 해서 계좌이체 내역을 알림으로 주지 않으면 우리는 돈이 입금됐는지 확인하기 위해서 앱을 계속해서 들락거려야 할 겁니다

그리고 은행앱을 사용하고 있는 와중에도 현재 내 계좌에 이체된 내역을 앱 위에서 즉각적으로 보여주지 않는다면 사용자인 우리들은 앱 내부의 알림 센터를 들어가 보아야 하는 번거로움이 발생합니다

 

이처럼 푸시 알림은 앱이 사용자에게 어떠한 중요한 사실을 알려줄 때 사용됩니다 

 

 

푸시 알림의 종류

 

앱을 통해 사용자에게 보내는 방식에는 Local과 Remote로 총 두 가지 방식이 있습니다 

Local 방식은 같은 시간대에 비슷한 콘텐츠가 반복적으로 전송되는 알림을 의미합니다

또한, 앱 내부에서 알림을 전달할 수 있다는 특징이 있습니다

 

반면 Remote 방식은 외부에서 앱에 푸시 알림을 보낼 수 있도록 애플에서 제공하는 APNs(Apple Push Notification service)를 이용하게 됩니다 

그리고 내용 또한 항상 유사한 것이 아닌 다양한 콘텐츠가 포함되게 됩니다

 

이것도 이미지로 쉽게 같은 앱인 뱅크샐러드로 비교해 볼게요!

좌측의 푸시 알림을 보면 유사한 형태를 띠고 있고 매일 선착순 신청이 시작되는 오전 10시, 오후 1시의 3분 전에 알림이 오는 형태를 가지고 있습니다

그리고 우측의 푸시 알림은 지출 내역에 대한 정보를 가지고 있어 저와 다르게 뱅크샐러드에 지출 내역이 기록된 분들은 다른 알림을 받으셨을 겁니다

 

이제 두 알림이 어떤 차이가 있는지 확실하게 이해되셨죠? 😉

 

Local / Remote

 

 

로컬 푸시 구현하기

우리는 서버를 이용할 수 없으니 로컬 푸시를 구현해보려고 합니다!

우선 알림을 받아오기 위해서 사용자에게 알림 허용 권한을 받아와야 합니다

대체로 알림 권한은 앱이 시작됨과 동시에 받아오기 때문에 AppDelegate에서 구현해 줍니다

여기서 사용되는 options는 UNAuthorizationOptions타입으로 알림 권한에 어떤 요소를 포함할지 결정해 줍니다

많이 사용되는 게 알림이 오면 배지를 추가해 주는 .badge, 소리를 울려주는 .sound, 알림을 표시해주는 .alert인 것 같습니다

 

그리고 만약 앱이 실행 중일 때에도 알림을 띄우고 싶다면 delegate를 이용해 줍니다!

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        // 앱 실행과 동시에 알림 허용 권한 받아오기
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { success, error in
            print(success)
        }
        // 앱 실행 중에도 알림 띄우기 위해 delegate 위임 
        UNUserNotificationCenter.current().delegate = self
        return true
    }

 

 

그리고 extension을 통해 AppDelegate에 UNUserNotificationCenterDelegate를 채택해 줄게요!

앱이 실행 중일 때도 알림을 보여줌과 동시에 사용자가 알림 센터에서 알림을 터치했다면 특정한 화면으로 이동해 주는 메서드도 사용해 줄 수 있습니다 (저는 따로 코드를 작성해주지는 않았어요 :D )

 

extension AppDelegate: UNUserNotificationCenterDelegate {
    // Foreground에서 알람을 받고 싶을 때
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        // iOS14부터 alert이 banner랑 list로 나뉘어짐
        // list와 banner 모두 사용하면 기본적인 알림 형태 
        completionHandler([.banner, .badge, .list, .sound])
    }
    
    // 화면이동 ex) 카카오톡 채팅방 화면 띄워줄 때
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        print("클릭됨")
    }
}

 

AppDelegate에서 해줄 일은 끝났습니다

이제는 어떤 알림을 띄울지 구성해 볼까요?

 

알림을 만들 때는 3가지 단계를 거치게 됩니다

  1. Content구성
  2. Trigger 생성
  3. Request 생성 및 등록 

🔥 우선, Content는 알림에 어떤 내용을 포함할지 설정해 주는 영역입니다

예시 코드처럼 title, body, badge 이외에도 다양한 콘텐츠를 설정해 줄 수 있습니다

 

🔥 Trigger는 알림 시간과 반복에 대해 설정해 주는 영역입니다

timeInterval을 5로 지정해 주면 5초 뒤에 알림이 오게 됩니다

그리고 만약 반복을 의미하는 repeats를 true로 설정해 주면 설정한 초가 지날 때마다 알림이 오게 됩니다

이때, 반복을 주기 위해서는 60초 이상의 값이 timeInterval로 들어가야 합니다!

 

🔥 Request는 방금 생성한 Content와 Trigger를 identifer와 함께 구성해 주는 역할을 합니다

identifier는 알림의 알림 취소 등에 사용되는 식별자로 같은 식별자의 알림은 뱅크샐러드 알림처럼 여러 개가 쌓이게 됩니다

 

그리고 이렇게 구성한 알림을 NotificationCenter에 등록해 줍니다

import UIKit

class LocalNotification {
    private init() {}
    static let noti = LocalNotification()

    func sendNotification() {
        // 1. 콘텐츠
        // - title, body 외에도 badge, sound 등 설정 가능
        let content = UNMutableNotificationContent()
        content.title = "알림 테스트! 볼드체에요"
        content.subtitle = "여기는 볼드체가 아니에요"
        content.badge = 30
        
        // 2. 언제 알림을 띄울 것인가
        // - 캘린더 기반
        // - 위치 기반
        // - 시간 간격: 초 단위 / 반복
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        
        // 3. iOS 알림 센터 시스템에 등록
        // - identifier 기준으로 쌓임
        // - identifier는 64개까지만 가능
        let request = UNNotificationRequest(identifier: "\(Date())", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)
    }
}

 

이후 사용하고자 하는 곳에서 sendNotification 메서드를 호출해 준 후, 앱 실행 후 5초가 지나면 이렇게 알림이 도착한 것을 확인할 수 있습니다!

 

Foreground / Background

 

 

또 만약 주기적으로 알림을 띄워주고 싶다면 아래처럼 DateComponents()를 이용해 구현해 줄 수 있습니다!

예시는 19시(오후 7시)마다 알림이 뜨도록 설정해 줬어요

 

class LocalNotification {
    private init() {}
    static let noti = LocalNotification()
    
    func sendNotification() {
        let content = UNMutableNotificationContent()
        content.title = "여기는 title!"
        content.body = "여기는 body!"
        
        var dateComponent = DateComponents()
        dateComponent.hour = 19
     
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: true)
        
        let request = UNNotificationRequest(identifier: "\(Date())", content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request)
    }
}

 

 

📚 참고

https://dokit.tistory.com/50

https://jrepository.tistory.com/126