본문 바로가기

iOS

[iOS] 로컬 푸쉬 알림 구현 방법 (Local Notification)

Swift로 로컬에서 푸쉬 알림을 어떻게 띄우게 구현하는지 알아보도록 하겠습니다.

기본 구조

Local Notification은 크게 3가지 파트로 나뉩니다. content, trigger, request 입니다. 이 세가지를 통하여 Local Notification을 쉽게 구현할 수 있습니다.

Content

content는 사용자에게 어떤 내용을 보여줄지에 대한 정보를 담고 있습니다. title, body, badge number, userInfo, attachments 등이 있습니다. userInfo는 예상하다시피 원하는 정보를 모두 담을 수 있는 Dictionary 입니다. 알림을 사용자가 눌렀을 때, userInfo에 들어있는 정보를 접근하여 활용할 수 있습니다.

Trigger

trigger에는 3가지 타입이 있습니다. time, calendar, location 입니다. 이름과 같은 역할을 한다고 보면 쉽습니다. 일정 시간이 지난 후에 작동되길 원한다면 time, 특정한 날짜에 작동하기 원한다면 calendar, 특정 위치에 진입할 경우 혹은 나갈 경우에 작동하기 원한다면 location을 활용할 수 있습니다.

Request

requestcontenttrigger를 가지고 로컬 푸쉬를 등록하기 위해 생성해야 합니다. 또한 identifier를 꼭 지정해야 합니다. 나중에 해당 알림을 취소하거나 핸들링할 때 쓰이게 됩니다.

구현 방법

이제 구현을 시작해보도록 하겠습니다.

 

import UserNotifications

 

Local Notification을 구현하기 위해서 UserNotifications을 사용합니다.

 

let userNotificationCenter = UNUserNotificationCenter.current()

override func viewDidLoad() {
    super.viewDidLoad()

    requestNotificationAuthorization()
    sendNotification(seconds: 10)
}

func requestNotificationAuthorization() {

}

func sendNotification(seconds: Double) {

}

 

사용자에게 알림 권한을 요청할 requestNotificationAuthoriztion과 알림을 보낼 sendNotification 함수를 구현할 것입니다.

 

func requestNotificationAuthorization() {
    let authOptions = UNAuthorizationOptions(arrayLiteral: .alert, .badge, .sound)

    userNotificationCenter.requestAuthorization(options: authOptions) { success, error in
        if let error = error {
            print("Error: \(error)")
        }
    }
}

 

이 함수를 호출하게 되면 사용자에게 알림 권한에 대한 허용 여부를 묻는 팝업이 나오게 됩니다. 🙆‍♂️

 

func sendNotification(seconds: Double) {
    let notificationContent = UNMutableNotificationContent()

    notificationContent.title = "알림 테스트"
    notificationContent.body = "이것은 알림을 테스트 하는 것이다"

    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: seconds, repeats: false)
    let request = UNNotificationRequest(identifier: "testNotification",
                                        content: notificationContent,
                                        trigger: trigger)

    userNotificationCenter.add(request) { error in
        if let error = error {
            print("Notification Error: ", error)
        }
    }
}

 

contenttitlebody를 담았습니다. 이외에도 attachments에 이미지 등의 rich content를 담을 수 있습니다. 어떤 데이터 타입을 담을 수 있는지는 UNNotificationAttachment를 참고하시면 됩니다. trigger에는 단순하게 전달받은 시간 이후에 알림이 전달되도록 구현하였습니다.

 

이제 알림을 받고난 후의 이벤트를 핸들링해야겠죠? UNUserNotificationCenterDelegate를 conform 함으로써 해결할 수 있습니다.

 

override func viewDidLoad() {
    super.viewDidLoad()

    userNotificationCenter.delegate = self

    requestNotificationAuthorization()
    sendNotification(seconds: 10)
}

extension ViewController: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        completionHandler()
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .badge, .sound])
    }
}

 

userNotificationCenter의 delegate에 현재 ViewController를 할당하였습니다. 테스트를 위하여 이렇게 구현하였지만 실제로 사용시에는 옳은 방법은 아닙니다. ✅ 실제로 이 delegate는 앱이 완전히 기동되기 전에 할당되어야 합니다.

 

AppDelegate의 함수인 application(_:willFinishLaunchingWithOptions:) 나 application(_:didFinishLaunchingWithOptions:) 에서 할당을 해야만 한다는 뜻입니다. 만약 이 함수가 호출된 이후에 delegate를 할당하게 된다면 인입되는 알림을 놓칠 수 있습니다.

 

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

    UNUserNotificationCenter.current().delegate = self

    return true
}

 

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        completionHandler()
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .badge, .sound])
    }
}

 

로컬 푸쉬 알림이 뜨는 화면

이제 앱이 백그라운드에 있어도, 앱이 닫아져 있어도, 폰 화면이 꺼져있어도 알림이 뜨는 것을 확인할 수 있을 것 입니다. 😎