아이폰을 사용하다보면 카카오톡 알림, 여러 앱에서 주는 알림 등을 받아 화면이 위의 사진처럼 되었던 경험들이 있을 것입니다. 이렇게 알림을 보내는 기능을 하는 것이 바로 User Notifications입니다. 오늘은 바로 이 User Notifications에 대해 알아보겠습니다.
User Notification이란??
간단히 말하자면 애플에서 만들어놓은 프레임워크 중 하나로 유저의 디바이스에 알림을 서버 혹은 앱 자체에서 보내는 것이라고 보면 되겠습니다. 사용자가 앱을 다운 받고 나중에 사용을 안 할수도 있는데 다시 사용할 수 있도록 중요한 정보나 이벤트들을 알려주어 재사용률(Retention)에 기여하기 때문에 중요한 부분이라고 볼 수 있겠습니다.
User Notifications Framework는 다음과 같은 특징을 가집니다.
- 사용자가 초기에 알림을 허용해야 알림이 표시됩니다.(추후 설정 가능)
- 알림과 함께 소리, 앱 아이콘에 뱃지(카카오톡 앱 우측 상단의 빨간 숫자)를 줄 수 있습니다.
- 알림은 로컬 환경(앱 자체)에서 생성하는 법(Local Notification)과 서버에서 원격으로 알림을 생성하는 법(Remote Notification) 두 가지가 존재합니다.
이 포스팅에선 로컬 환경에서 notification을 설장하는 법 Local Notification에 대해 다루고자합니다.
로컬알림(Local Notification)이란?
로컬 즉 앱 자체에서 알림을 전달하는 방법을 뜻합니다. 앱 자체에 notificaion의 내용과 보내는 주기 등을 설정해 두었기 때문에 비슷한 시각, 비슷한 내용들을 주로 다룹니다. 대표적으로 캘린더 앱, 알람 앱을 생각해보시면 되겠습니다. 알람이나 일정들을 우리가 임의로 설정할 수 있는 것이 이 Local Notfication의 기능을 사용하는 것입니다.
그렇다면 로컬 알림(Local Notification)은 어떻게 우리가 설정해줄 수 있을까요? 이제부터 그 방법에 대해 알아봅시다.
1. Local Notification 가져오기
제일 처음 우리가 해야할 일은 앱이 Local Notification을 사용할 수 있도록 기능을 불러오는 것입니다. 이 때 우리는 UNUserNotificationCenter 클래스를 사용합니다.
NSObject를 상속받는 클래스로서 우리가 notification에 관련된 기능을 사용하게 해줍니다. 그리고 이와함께 current메소드를 사용해 현재 앱에서 UNUserNotificationCenter을 가져옵니다.
let notificationCenter = UNUserNotificationCenter.current()
2. 권한요청
알림의 옵션 alert, badge, sound 등을 설정해주고 권한을 요청합니다. 앱을 다운받으시면 알림 설정이나 위치 정보등에 대한 권한을 허용하거나 취소하거나 할 수 있는 얼럿을 보셨던 경험이 있을 겁니다. 이런 권한에 대해 사용자가 허용을 했을 경우 그리고 허용을 하지 않았을 경우를 나눠 표시해줍니다.
권한 허용시에 줄 수 있는 notification의 옵션을 UNAhtorizationOptions(arrayLiteral:_)함수, UNUserNotificationCenter의 메소드로 권한을 허용할지 말지를 정해주는 requestAuthorization(options:_)함수를 사용하면 됩니다.
func requestAuthorization() {
let authorizationOptions = UNAuthorizationOptions(arrayLiteral: [.alert, .badge, .sound])
notificationCenter.requestAuthorization(options: authorizationOptions) { success, error in
if success {
self.sendNotification()
}
}
}
3. 사용자에게 알림 요청(시간, 컨텐츠)
마지막으로 권한을 허용했다면 사용자에게 1. 어떤 컨텐츠를 보낼 건지 2. 언제 알림을 보낼건지를 정해주어야합니다. 때문에 각각의 역할을 담당할 두 가지 객체가 필요하게됩니다.
- UNMutableNotificationContent
- 알림을 통해 전달할 내용을 담당하는 클래스입니다.
- title, subtitle, body, sound 등을 통해 어떤 내용을 보낼지 정할 수 있습니다.
- 알림 트리거
- 시간 간격(UNTimeIntervalNotificationTrigger) : 최소 60초 간격일 때 반복 알림 설정 가능
- 캘린더(UNCalendarNotificationTrigger)
- 위치 기반(UNLocationNotificationTrigger)
마지막으로 두 객체로 만든 알림의 내용들을 UNNotificationRequest 클래스에 할당해줍니다. 이 때 identifier를 정해주게되는데 이게 동일할 경우 알림의 내용이 수정되는 형태로 나타나고 다른 경우엔 알림이 스택처럼 쌓이는 형태로 나타납니다. 때문에 identifier를 Date()로 정해주면 겹칠일이 없어 스택형태로 나타낼 때 용이하게 사용됩니다.
func sendNotification() {
let notificationContent = UNMutableNotificationContent()
notificationContent.title = "다마고치에게 밥을주세요"
notificationContent.subtitle = "오늘 행운의 숫자는 \(Int.random(in: 1...77))"
notificationContent.body = "저는 방실방실 다마고치에요... 너무 배고파요ㅠㅠ"
notificationContent.badge = 30 // 카톡 앱 아이콘 우측상단에 생기는 숫자
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
let request = UNNotificationRequest(identifier: "\(Date())", content: notificationContent, trigger: trigger)
notificationCenter.add(request)
}
그리고 앱을 실행하면 다음과 같은 화면이 나옵니다.
여기서 Allow를 눌러주고 나서 버튼을 눌러주면 다음과 같이 알림이 오게됩니다. 뱃지도 생긴 것을 확인하실 수 있습니다.
실행해보시면 아시겠지만 앱이 백그라운드 상태로 들어갈 때에만 알림이 오는 것을 확인할 수 있습니다. 그렇다면 어떻게 해야 앱을 실행하는 중에도 알림을 받을 수 있을까요? 이는 AppDelegate에서 델리게이트패턴을 사용해 쉽게 만들어볼 수 있습니다.
UNUserNotificationCenterDelegate를 받아와 userNotificationCenter메소드를 사용해줬습니다. 여기서 주의할 점은 .alert가 삭제되고 iOS14.0이후로 .list와 .banner로 바뀌었다는 점과 반드시 delegate를 self로 지정해주어야 한다는 점입니다.
그러면 이렇게 앱을 실행중에도 다음과 같이 알림을 받아볼 수 있습니다.
다음으로 이제 뱃지에 생긴 숫자를 없애봅시다. 어떻게 해야 숫자를 없앨 수 있을까요? 앱의 생명주기를 생각해보면 쉽습니다. 우리가 앱을 실행할 때 뱃지의 숫자가 0이되면 되겠죠? 그렇다면 여기서 우리는 두 가지 선택지를 가지게 됩니다. Foreground 상태일 때 0으로 만들어주는 것과 Active 상태일 때 0으로 만들어주는 것입니다.
우리가 앱을 키는 순간 앱은 Foreground 상태에 들어갑니다. 그리고 서버나 로컬에서 앱의 데이터 등을 받아오고 나서야 Active 상태에 들어서게 되죠. 그렇다면 만약 앱을 키자마자 전화가 걸려온다면 어떻게 될까요?
바로 Foreground 상태에서 Active 상태로 가지 못하게 됩니다. 만약 이 때 앱을 종료시켜버렸다면 Foreground 상태에서 앱을 확인하지 않고 종료시킨 것이 됩니다. 조금 감이 오셨나요??? 네 우리가 Foreground에서 뱃지숫자를 0으로 만들어준다면 제대로 앱을 확인하지 않고도 0이 될 수 있는 경우가 발생할 수도 있다는 것입니다. 고로 우리는 Active상태일 때 뱃지의 숫자를 0으로 만들어 주어야합니다.
마지막으로 앱을 실행시키면 이전까지 생겼던 알림을 모두 없애주는 기능을 만들어봅시다. 우리는 보통 앱을 실행시키면 이전까지 쌓여왔던 알림을 없앨 수 있다는 것을 경험적으로 알고있습니다. 그렇다면 이 기능은 어떻게 만들어야할까요??? 앱을 실행시킬 때 notification을 모두 삭제해주면되지 않을까요?
네 맞습니다. 우리는 AppDelegate파일에서 didFinishLaunchingOptions에 notification을 삭제해주는 removeAllPendingNotificationRequests() 메소드와 removeAllDeliveredNotificationRequest() 메소드를 사용할 수 있습니다.
Pending의 경우 알림 요청을 모두 해제하는 것 즉 우리가 30분 뒤에 알람을 설정해놓는다면 그것마저도 해제시킵니다. 반대로 delivered의 경우 이미 우리에게 전달된 알림을 해제해줍니다. 저는 pending을 사용해보았습니다.
알림이 쌓이고난게 앱을 실행시키고 확인해보면 사라진 것을 확인하실 수 있습니다.
참고
https://developer.apple.com/documentation/usernotifications/unusernotificationcenter
'iOS' 카테고리의 다른 글
[iOS] - Push Notification(feat. Firebase) (0) | 2022.10.11 |
---|---|
[iOS] Map Kit View 사용하기 - 1 (0) | 2022.08.11 |
[iOS] WKWebView (0) | 2022.07.28 |
[iOS] 컬렉션뷰(Collection View) (0) | 2022.07.21 |
[iOS] TableViewController - Custom Table View Cell (0) | 2022.07.19 |