
앱에서 푸시알림을 보내기 위해 Local과 Remote방식이 있다. Local은 앱 내에서 미리 푸시알림 보낼 컨텐츠를 설정하여 보내고 Remote는 원격으로 푸시알림을 보낼 수 있다. 이번 글에서는 Local로 푸시 알림 보내는 예제를 학습해 보겠다.
User Notifications
-> User Notifications는 서버에서 사용자 기기로 푸시알람을 보내거나 앱에서 로컬로 알림을 생성할 수 있게 해주는 프레임워크다.
로컬 알림의 경우, 앱에서 알림 콘텐츠를 생성하고 시간이나 위치와 같이 알림 전송을 트리거하는 조건을 지정한다.
알림콘텐츠와 트리거가 당장 이해 안될 수 있지만 밑에 예제에서 다시 다뤄보겠다.
우선 전체 코드부터 보자.
전체 코드
import SwiftUI
struct ContentView: View {
@State private var selectedDate = Date()
var body: some View {
VStack {
//설정된 시간으로 알림 보내기
DatePicker("알림 시간", selection: $selectedDate, displayedComponents: .hourAndMinute)
.datePickerStyle(.wheel)
.labelsHidden()
Button("설정한 시간에 알림 보내기") {
Task { await scheduleNotification(at: selectedDate) }
}
//5초후 알림 보내기
Button("5초후 알림 보내기") {
Task { await scheduleNotification(after: 5) }
}
}
.onAppear {
Task { await requestNotiPermission() }
}
}
//MARK: - 알림 권한 요청
func requestNotiPermission() async {
let center = UNUserNotificationCenter.current()
do {
try await center.requestAuthorization(options: [.alert, .sound, .badge])
} catch {
print(error)
}
}
//MARK: - 설정한 시간에 맞춰 보내기
func scheduleNotification(at date: Date) async {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removeAllPendingNotificationRequests()
//<---- 알람 보낼 콘텐츠 제작 ---->
let content = UNMutableNotificationContent()
content.title = "⏰ 시간 알람"
content.body = "설정한 시간이 되었습니다!"
content.sound = UNNotificationSound(named: UNNotificationSoundName("notiSound.caf"))
//<-------------------------->
//<---- 트리거 설정 ---->
let triggerDate = Calendar.current.dateComponents([.hour, .minute], from: date)
let trigger = UNCalendarNotificationTrigger(
dateMatching: triggerDate, repeats: true)
//<------------------>
//<---- 알림 요청 생성 + 등록 ---->
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
do {
try await notificationCenter.add(request)
} catch {
print(error)
}
//<--------------------------->
}
//MARK: - 특정 시간 후 보내기
func scheduleNotification(after seconds: TimeInterval) async {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removeAllPendingNotificationRequests()
//<---- 알람 보낼 콘텐츠 제작 ---->
let content = UNMutableNotificationContent()
content.title = "⏱ 5초 뒤 알람"
content.body = "방금 요청한 알람이 도착했습니다!"
content.sound = UNNotificationSound(named: UNNotificationSoundName("notiSound.caf"))
//<-------------------------->
//<---- 트리거 설정 ---->
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: seconds, repeats: false)
//<------------------>
//<---- 알림 요청 생성 + 등록 ---->
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
do {
try await notificationCenter.add(request)
} catch {
print(error)
}
//<--------------------------->
}
}
이 코드에서는 크게 두 가지 기능이 있는데,
1. 사용자가 설정한 시간에 알림을 보내는 기능
2. 일정시간 후 알림을 보내는 기능
이렇게 볼 수 있다.
우선, 이 기능들이 가능하게 하기 위해서는 알림 권한 요청이 필요하다.
//MARK: - 알림 권한 요청
func requestNotiPermission() async {
let center = UNUserNotificationCenter.current()
do {
try await center.requestAuthorization(options: [.alert, .sound, .badge])
} catch {
print(error)
}
}
알림 권한을 유저가 허용해야만 푸시알림이 정상적으로 간다 !
이 메서드를 실행하게 되면 유저에게 알림 권한을 허용하라는 팝업이 뜬다.
여기서, UNUserNotificationCenter 객체를 자주 보게될 것인데 이 친구는 앱에서 알림 관련 활동을 중앙에서 관리해주는 친구로 보면 된다.
requestAuthorization(options: [.alert, .sound, .badge])
이 메서드를 통해 알림표시, 알림소리, 앱 아이콘에 숫자로 붙는 뱃지 등을 요청할 수 있다.
//MARK: - 설정한 시간에 맞춰 보내기
func scheduleNotification(at date: Date) async {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removeAllPendingNotificationRequests()
//<---- 알람 보낼 콘텐츠 제작 ---->
let content = UNMutableNotificationContent()
content.title = "⏰ 시간 알람"
content.body = "설정한 시간이 되었습니다!"
content.sound = UNNotificationSound(named: UNNotificationSoundName("notiSound.caf"))
//<-------------------------->
//<---- 트리거 설정 ---->
let triggerDate = Calendar.current.dateComponents([.hour, .minute], from: date)
let trigger = UNCalendarNotificationTrigger(
dateMatching: triggerDate, repeats: true)
//<------------------>
//<---- 알림 요청 생성 + 등록 ---->
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
do {
try await notificationCenter.add(request)
} catch {
print(error)
}
//<--------------------------->
}
그 다음 보게될 메서드는 설정한 시간에 맞춰 알림을 보내는 기능이다.
여기서, 로컬에서 푸시알림을 보내기 위해서는 크게 3가지 흐름으로 볼 수 있는데
1. 알림 콘텐츠 제작 -> 2. 알림 트리거 설정 -> 3. 알림 요청 생성 + 등록
이렇게 볼 수 있다.
무료 mp3파일을 다운받아 caf 형식으로 바꿔서 넣어줬다.이렇게 로컬 푸시알림이 동작하게 된다.
//MARK: - 특정 시간 후 보내기
func scheduleNotification(after seconds: TimeInterval) async {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removeAllPendingNotificationRequests()
//<---- 알람 보낼 콘텐츠 제작 ---->
let content = UNMutableNotificationContent()
content.title = "⏱ 5초 뒤 알람"
content.body = "방금 요청한 알람이 도착했습니다!"
content.sound = UNNotificationSound(named: UNNotificationSoundName("notiSound.caf"))
//<-------------------------->
//<---- 트리거 설정 ---->
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: seconds, repeats: false)
//<------------------>
//<---- 알림 요청 생성 + 등록 ---->
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
do {
try await notificationCenter.add(request)
} catch {
print(error)
}
//<--------------------------->
}
방금 로컬 푸시알림 과정에 대해 알았으니 이 코드도 쉽게 보일 것이다.
똑같이 알림보낼 콘텐츠를 제작, 트리거를 설정, 요청을 생성하고 등록하는 절차를 밟는다.
달라진건 UNTimeIntervalNotificationTrigger 트리거로 변경된 것 뿐이다.
이 트리거 같은 경우에, timeInterval에 원하는 시간을 넣어줄 수 있는데 만약에 60을 넣어주면 60초후 알림이 울리게 된다.
그리고 repeats을 true로 두면 알림이 반복하게 오는데, 60초를 넣으면 60초마다 푸시 알림이 오는 것이다.
하지만 주의할 점은 !! repeats이 true일때, timeInterval을 최소 60초로 두지 않으면 에러가 난다. (아마 짧은 시간에 계속 반복적으로 알림을 쏘면 성능상 문제가 있어서 애플측에서 막아둔거 같다)
그래도 repeats이 false면 5초를 넣어도, 1초를 넣어도 상관없다 ~
실제 구현 영상
*설정한 시간으로 알림보내기

*5초후 알림보내기

* 현재 foreground 에서는 알림이 오지 않는데 foreground 에서도 알림을 받을려면 AppDelegate설정을 해줘야 하는데 이 부분은 다음에 알아보겠습니다.
https://developer.apple.com/documentation/usernotifications
https://developer.apple.com/documentation/usernotifications/asking-permission-to-use-notifications
https://developer.apple.com/documentation/usernotifications/unusernotificationcenter
https://developer.apple.com/documentation/usernotifications/scheduling-a-notification-locally-from-your-app