본 포스팅은 Swift 5.2.4 기준으로 작성되었습니다.
이번 포스팅에서는 우리 모두 너무나도 익숙한 Notification 을 Push 하는 방법에 대해 공부해보겠습니다. 혹시 이게 뭔지 잘 모르는 분들이 있을까봐 한마디로 설명해보자면 카톡이 왔을 때 아이폰에 뜨는 알림이 바로 Notification 입니다. 이제 딱 감이 왔나요?
사용자에게 알림을 보내기위해서는 UserNotifications 라는 Framework 를 사용해야 합니다. 오늘도 공식문서를 하나씩 살펴보면서 공부해볼거에요.
좀 내용이 긴데... 결론적으로 Notification 은 사용자에게 중요한 정보를 알리고자 할 때 사용하면 된다는 것을 길게 풀어놓았어요 ㅎㅎ
아무튼!! 이제 프로젝트를 하나 새롭게 만들고 같이 한번 만들어보도록할게요. 프로젝트가 생성되었으면 UserNotifications Framework 를 import 해줍니다. 참고로 저는 화면 중앙에 버튼을 하나 만들어놓고 이 버튼이 눌렸을 때 Notification 이 올 수 있도록 구현할 예정입니다.
import UserNotifications
우리가 구현하고자하는 기능은 UserNotifications Framework 에서 제공하는 UNUserNotificationCenter 를 이용해야 합니다.
Notification 실행에 관련된 모든 행동들을 관리하는 중요한 Object 라고 하네요.
그리고 이것을 통해서 할 수 있는 일들은 이런 것들이 있다고 합니다.
- 사용자에게 알림 및 뱃지를 보여주기 위한 권한요청
- 어떤 Notification Type 을 사용할 것인지 설정 (승인 및 취소 버튼을 넣는다거나하는 커스터마이징을 할 수 있습니다)
- 언제 Notification 이 보내질지 설정
- 사용자에게 전달된 Notification 에 대한 처리
- 그 외 Notification 에 관련된 여러가지 설정
이중에서 우리가 가장 먼저해야하는 일은 사용자에게 Push 알림을 위한 권한요청을 하는 것이에요. 그럼 권한 요청 코드를 바로 한번 작성해볼게요.
사용자에게 Push 권한 요청하기
먼저 UNUserNotificationCenter 는 Singleton 형태로 사용할 수 있습니다. 그리고 Singleton 인스턴스에는 current() 를 사용해 접근할 수 가 있어요.
let notificationCenter = UNUserNotificationCenter.current()
그냥 사용해도되지만 저는 접근 코드가 조금 긴 것 같으니 편하게 접근할 수 있도록 프로퍼티에 담아두도록 할게요. 이제 권한요청을 할 수 있는 requestAuthorization() method 에 접근이 가능해졌습니다. 이 method 는 parameter 로 options 와 completionHandler 를 받게 되어있는데요. Options 를 통해 우리가 사용자에게 어떤 방식으로 알림을 보내고 싶은지 설정할 수 있으며 completionHandler 를 통해 에러 처리와 사용자가 승인 또는 거부를 했을 상황에 대한 처리를 각각 할 수 있습니다.
이번에는 .alert, .badge, .sound 3가지 옵션만 주도록 해보겠습니다. 이곳에서 전부 설명하기에는 글이 너무 길어질 수 있으니 적당히 넘어갈게요... 아무튼 여러가지 옵션들이 많이 제공되니 어떤 것들이 있나 꼭 한번 확인해보는걸 추천합니다!
private func generateUserNotification() {
notificationCenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if let error = error {
print(error)
} else {
if granted {
print("Granted")
} else {
print("Not Granted")
}
}
}
}
간단한 코드니까 저도 간단하게 설명을 해보자면 completionHandler 로 들어올 수 있는 값 중 granted 와 error 가 있습니다. 이 중 error 는 그냥 따로 처리할 수 있도록 분기를 나눠주었고요. granted 는 Bool 타입이므로 true 와 false 를 반환하니 각 상황에 맞는 코드를 작성할 수 있도록 다시 한번 분기를 나눠주었습니다. 즉 사용자의 승인까지 모든 것이 성공적으로 끝마쳐졌을 때는 print("Granted") 가 있는 곳으로 빠지게 됩니다.
그러니까 이제 우리는 granted 되었을 때 사용자에게 Notification 을 보내주도록 작업해주면 되겠죠? UNUserNotificationCenter.current() 에는 Notification 전달을 도와주는 .add method 가 있습니다. 이제 이것을 이용해서 사용자에게 알림을 보내주면 끝입니다.
.add method 의 공식문서를 보면 총 3가지의 parameter 를 받도록 되어있는데 이 중 우리가 눈여겨 볼 것은 request 입니다. 다른 값들은 optional 로 nil 을 줘도되지만 request 는 필수로 작성해야하는 부분이거든요. UNNotificationRequest 타입을 받도록 되어있는데 얘는 또 무엇일까요?
UNNotificationRequest 은 Notification 의 Content(내용) 와 Trigger Condition (발동 조건) 을 포함하는 요청이라고 나와있네요. 그리고 인스턴스 생성 시 identifier, content, trigger 3가지를 입력 받도록 되어 있어요.
첫번째 identifier 는 각각의 Notification 을 구분해주는 역할을 하며 어떤 Notification 을 임의대로 지우고 싶을 때 이 identifier 를 통해 특정 Notification 만 삭제할 수 있습니다.
Content 생성하기
두번째로는 content 인데요. 무엇인지 정확히 모르지만 UNNotificationContent 타입을 받도록 되어있어요. 처음보는 타입이니까 이 타입이 무엇인지부터 확인해봐야겠죠?
음... 수정할 수 없는 형태의 content 라고하네요. Overview 의 마지막 문단을 읽어보면 이것을 인스턴스화 시키기말고 UNMutableNotificationContent 를 만들어서 쓰라고 되어있어요.
수정이 가능한 Content!! 이제 뭔가 좀 제대로 찾아온 느낌이 드네요 ㅎㅎ 이것을 인스턴스화 해서 사용하라고 나와있어요.
이름에 Content 가 들어가는 만큼 당연히 Notification 의 내용을 구성하는 것에 관련된 class 일 것 같은 느낌이에요. 우리가 접근할 수 있는 method 목록을 봐도 title, subtitle, body 등 내용을 나타내는 것이 확실해졌어요. 그럼 UNMutableNotificationContent 를 인스턴스화 시키고 기본적인 내용들을 입력해보도록 할게요.
private func generateUserNotification() {
notificationCenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if let error = error {
print(error)
} else {
if granted {
let content = UNMutableNotificationContent()
content.title = "This is title"
content.subtitle = "This is subtitle"
content.body = "This is body"
content.badge = 1
} else {
print("Not Granted")
}
}
}
}
이렇게 Content 가 생성되었어요. 이제 마지막 항목인 Trigger Condition 을 만들어 볼까요?
Trigger Condition 생성하기
Trigger Condition 은 UNNotificationTrigger 타입을 받고 있습니다.
이번에도 문서를 읽어보니 이 타입은 바로 인스턴스화 시켜서 사용하지 말고 Subclass 를 이용하라고 나와있네요.
Subclass 의 종류로는 이렇게 4종류가 있습니다.
- UNTimeIntervalNotificationTrigger
- UNCalendarNotificationTrigger
- UNLocationNotificationTrigger
- UNPushNotificationTrigger
이름만 읽어봐도 어떤 것을 기준으로 Notification 이 발동될지 느낌이 오네요. 일단 우리는 이번에 UNTimeIntervalNotificationTrigger 을 사용해서 Trigger Condition 을 생성해보도록 하겠습니다. 이전에 작성한 Content 아래쪽에 입력해주세요.
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
간단하죠? Trigger 가 발동되면 3초 뒤에 Notification 이 올 수 있도록 설정해놓았어요.
Request 생성 및 Notification 등록
이제 Content 와 Trigger Condition 이 모두 준비되었으니까 초반에 만들려고 했었던 UNNotificationRequest 을 생성해보도록 하겠습니다.
let request = UNNotificationRequest(identifier: "Sample Notification", content: content, trigger: trigger)
그리고 이제 마지막으로 .add method 에 생성한 request 를 등록해주면 끝입니다.
private func generateUserNotification() {
notificationCenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if let error = error {
print(error)
} else {
if granted {
let content = UNMutableNotificationContent()
content.title = "This is title"
content.subtitle = "This is subtitle"
content.body = "This is body"
content.badge = 1
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
let request = UNNotificationRequest(identifier: "Sample Notification", content: content, trigger: trigger)
self.notificationCenter.add(request, withCompletionHandler: nil)
} else {
print("Not Granted")
}
}
}
}
이제 실행을 해보면 Notification 이 도착하는 것을 확인해볼 수 있습니다. 추가적으로 우리가 아까 작성했던 Title 과 Subtitle 그리고 Body 가 무엇인지도 확실히 알 수 있겠죠~~??