앱을 개발하다 보면 사용자에게 적절한 타이밍에 메시지를 전달해야 할 순간이 꼭 생깁니다. 예를 들어, 일정이 다가왔을 때 알림을 보내거나, 특정 이벤트가 발생했을 때 유저에게 공지사항을 전송하는 기능은 사용자 경험을 크게 향상시켜주죠. Flutter에서는 이런 알림 기능을 직접 구현할 수 있지만, 플랫폼별로 네이티브 API를 호출해야 하기 때문에 다소 복잡하게 느껴질 수 있어요. 다행히도 flutter_local_notifications라는 패키지를 사용하면 이 과정을 훨씬 쉽게 처리할 수 있어요.
이번 글에서는 Flutter에서 Local Notification을 구현하는 전반적인 과정을 정리해볼게요. 알림 기능의 개념부터 Android 및 iOS 플랫폼별 설정, 그리고 실제 알림 호출까지 실습 중심으로 정리해드릴게요.
Local Notification이란?
우선 로컬 알림(Local Notification)이란, 서버가 아닌 기기 자체에서 발생하는 알림을 의미해요. 즉, 인터넷 연결이 없더라도 알림을 보낼 수 있는 구조죠. 이런 방식은 스케줄 기반 리마인더, 앱 내 특정 액션 트리거 등에 유용하게 쓰입니다. 하지만 Flutter는 기본적으로 네이티브 알림 API를 직접 제공하지 않아요. Android에서는 NotificationCompat, iOS에서는 UserNotification API를 사용해야 하는데, 이를 직접 연동하기에는 진입장벽이 꽤 높습니다.
여기서 등장하는 것이 바로 flutter_local_notifications 패키지예요. 이 패키지는 네이티브의 알림 기능을 내부에서 처리해주며, Flutter 코드로 쉽게 알림을 구현할 수 있도록 도와줘요. 설정도 어렵지 않습니다. 다음과 같은 순서로 구현이 가능해요.
- flutter_local_notifications 패키지 설치
- Android 및 iOS 플랫폼별 설정
- 알림 초기화 및 권한 요청
- 알림 보내기 함수 구현
- 알림 클릭 시 동작 처리
각 단계는 플랫폼 특유의 제약사항이 존재하기 때문에, 정확한 설정과 권한 관리가 중요합니다. 다음 본문에서는 Android와 iOS 각각에서 어떤 설정이 필요한지 구체적으로 설명해볼게요.
Android와 iOS에서의 설정
Flutter에서 로컬 알림 기능을 구현하려면, Android와 iOS 각각의 플랫폼별 권한 설정과 초기화 작업이 반드시 필요해요. 두 운영체제 모두 보안과 사용자 프라이버시를 중요하게 여기기 때문에, 알림을 보내기 위해서는 정해진 권한을 요청하고 명시적으로 초기화 과정을 거쳐야 해요.
Android 설정
Android에서는 flutter_local_notifications 패키지를 통해 네이티브 알림을 연동하지만, 실제로는 내부적으로 NotificationCompat API를 사용해요. 따라서 몇 가지 세부 설정이 필요해요.
1) build.gradle 수정
android/app/build.gradle 파일에서 다음과 같은 설정을 추가합니다.
compileSdk = 34
...
coreLibraryDesugaringEnabled true
multiDexEnabled true
...
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
implementation 'androidx.window:window:1.0.0'
implementation 'androidx.window:window-java:1.0.0'
}
2) AndroidManifest.xml에 권한 추가
알림과 관련된 권한을 명시적으로 선언해줘야 합니다. 예를 들어,
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
Android 13 이상에서는 POST_NOTIFICATIONS 권한이 필수예요. 사용자가 이 권한을 수락해야 알림이 실제로 표시돼요. 따라서 앱 실행 시점에서 별도로 요청해야 합니다.
3) Receiver 등록
알림이 부팅 시 다시 설정되거나 스케줄 알림이 동작할 수 있도록 여러 브로드캐스트 리시버를 등록합니다.
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
...
iOS 설정
iOS는 상대적으로 설정이 간단하지만, 초기화와 권한 요청을 정확히 해줘야 알림이 제대로 작동해요.
1) AppDelegate.swift 수정
알림 기능을 사용할 수 있도록 다음 코드를 삽입합니다.
import flutter_local_notifications
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
2) 알림 권한 요청 (iOS 10 이상)
초기화 시 알림, 사운드, 배지 권한을 모두 요청합니다.
final DarwinInitializationSettings initializationSettingsDarwin =
DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
3) iOS Info.plist에 권한 설명 추가
알림 권한 요청을 위해 아래 항목을 추가하세요.
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
이처럼 Android와 iOS에서 각각의 권한과 설정을 정확히 적용해야 Flutter 앱 내에서 로컬 알림 기능이 안정적으로 작동해요. 다음 단계에서는 실제로 알림을 보내는 코드 구현과 사용자 상호작용을 어떻게 처리하는지 살펴볼게요.
알림 기능 구현, 코드 한 번에 정리하기
이제 Flutter에서 실제 알림을 구현하는 코드를 구성해볼게요. 로컬 알림을 보낼 수 있도록 NotificationHelper 클래스를 만들고, 앱 초기화 시 알림 시스템을 설정하며, 버튼 클릭 시 알림이 표시되도록 연동합니다. 아래 코드는 notification_helper.dart와 main.dart에 각각 들어가는 구성인데, 한 번에 통합해볼 수 있도록 예제 코드로 정리해볼게요.
// notification_helper.dart
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
// 알림 클릭 시 백그라운드에서 실행할 로직
print('백그라운드 알림 클릭됨: ${notificationResponse.payload}');
}
class NotificationHelper {
static final flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
static Future<void> initiailize() async {
const AndroidInitializationSettings androidInit =
AndroidInitializationSettings('@mipmap/ic_launcher');
final DarwinInitializationSettings iosInit = DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
final InitializationSettings initSettings = InitializationSettings(
android: androidInit,
iOS: iosInit,
);
await flutterLocalNotificationsPlugin.initialize(
initSettings,
onDidReceiveNotificationResponse: (response) {
print('포그라운드 알림 클릭됨: ${response.payload}');
},
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
);
await _requestAndroidPermissionForOver33();
}
static Future<bool?> _requestAndroidPermissionForOver33() async {
final androidPlugin = flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();
return await androidPlugin?.requestNotificationsPermission();
}
static Future<void> show(String title, String content) async {
return flutterLocalNotificationsPlugin.show(
0,
title,
content,
const NotificationDetails(
android: AndroidNotificationDetails(
'test_channel_id',
'General Notifications',
importance: Importance.high,
playSound: true,
),
iOS: DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
),
),
payload: 'Open from Local Notification',
);
}
}
// main.dart
import 'package:flutter/material.dart';
import 'notification_helper.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await NotificationHelper.initiailize();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: HomePage());
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('로컬 알림 예제')),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await NotificationHelper.show('새 소식!', '지금 확인해보세요!');
},
child: const Icon(Icons.notifications),
),
);
}
}
이 코드를 실행하면 앱에서 FloatingActionButton을 눌렀을 때 로컬 알림이 전송되고, 알림을 클릭하면 포그라운드 또는 백그라운드에서 지정한 콜백이 실행됩니다.
마치며...
Flutter에서 알림을 구현하는 과정은 겉보기엔 복잡하지만, 핵심은 단순합니다.
- 패키지 설치
- 플랫폼 설정
- 초기화 및 권한 요청
- 알림 호출 및 클릭 이벤트 처리
이 흐름만 이해하면 다양한 상황에 유저 맞춤 알림을 구현할 수 있어요. 알림은 단순한 기능처럼 보이지만, 실제로는 앱의 재방문율과 사용자 경험을 결정짓는 핵심 요소가 될 수 있죠.
Flutter 앱을 개발 중이라면 지금 당장 알림 기능을 도입해보세요. 유저와 앱이 소통하는 가장 직접적인 방법이 될 거예요!
'IT' 카테고리의 다른 글
플러터, Gemini API 연동하기 (0) | 2025.05.07 |
---|---|
바이브 코딩은 세상을 어떻게 바꿀까? (0) | 2025.05.06 |
플러터, 쓰로틀링과 디바운싱 (0) | 2025.05.02 |
플러터, 애니메이션 구현하기 (0) | 2025.05.01 |
바이브 코딩, 오히려 오래된 프레임 워크가 유리하다? (6) | 2025.04.30 |