[Flutter] 앱에서 background 푸시 알림 다국어 처리하기(안드로이드) with easy_localization

Kim Gaeun·2023년 2월 8일
0

Flutter

목록 보기
5/5
post-thumbnail

0. 안드로이드와 ios의 차이 : notification, 다국어

Flutter를 하면서 안드로이드에서 ios와 다르게 동작해서 해결하기 어려웠던 경우가 꽤 있었는데 notification이 특히 그랬다.

특히 안드로이드는 ios와 달리 background에서 별도의 isolate가 생기기 때문에 foreground의 context 등 변수를 사용할 수 없고, 설정에서 언어를 변경했을 때 앱이 재시작되는 ios와 달리 앱이 재시작되지 않기 때문에 다국어와 관련해서도 추가적으로 처리가 필요할 수 있다.

앱에서 notification 텍스트를 자체적으로 다국어 처리한다면 foreground에서는 크게 문제가 되지 않지만, background에서는 위와 같은 안드로이드의 특성에 영향을 받을 수 있다.

1. background에서 다국어 처리하기

기존에는 다국어 처리를 위해 l10n을 사용하고 있었는데, 항상 context를 사용해야 한다.

AppLocalizations.of(context).save

그런데 안드로이드 background에서는 context가 저장되지 않기 때문에 먼저 context를 사용하지 않는 다국어 패키지인 easy_localization을 찾았다.

easy_localization
https://pub.dev/packages/easy_localization

이 패키지를 사용하면 context를 사용하지 않지만, 안드로이드 background에서는 다국어 정보를 찾지 못했다.

분명 비슷한 문제를 겪는 사람이 있을 거라고 생각했고, 구글링하던 중에 easy_localization 깃헙에서 다음과 같은 issue를 찾았다.
https://github.com/aissat/easy_localization/issues/210

그리고 댓글을 참고해서 background에 새로운 easy_localization는 init해주는 코드를 추가하였다.

// 자동으로 import되지 않으므로 추가해주어야 함
import 'package:easy_localization/src/easy_localization_controller.dart';

FirebaseMessaging.onBackgroundMessage(_handleBackgroundMessage);

Future<void> _handleBackgroundMessage(RemoteMessage event) async {
  ...
  const locales = [Locale('en'), Locale('ko')];
  const localizationPath = 'assets/translations';

  // background에서 EasyLocalization 다시 init
  await EasyLocalization.ensureInitialized();
  final controller = EasyLocalizationController(
  	// true로 설정하면 처음 불러온 locale이 저장되고, 그 다음에는 저장된 locale을 먼저 불러옴
    saveLocale: true,
    supportedLocales: locales,
    useOnlyLangCode: true,
    fallbackLocale: locales[0],
    useFallbackTranslations: true,
    path: localizationPath,
    onLoadError: (FlutterError e) {},
    assetLoader: const RootBundleAssetLoader(),
  );

  await controller.loadTranslations();
  Localization.load(
    controller.locale,
    translations: controller.translations,
    fallbackTranslations: controller.fallbackTranslations,
  );
  ...
}

이렇게 하면 background에서도 다국어 처리된 메시지를 볼 수 있다.

2. 기기 언어 변경 대응하기

그런데 여기까지만 처리하면 안드로이드 설정에서 기기 언어를 변경했을 때 변경된 언어가 반영되지 않는다.
(하지만 실제 언어를 변경해서 사용하는 사용자는 많지 않을 것 같다)

특히 saveLocale을 true로 설정하면 처음 설정된 언어가 저장되어 계속 불러온다.
saveLocale을 false로 바꾸고, background에서 기기 언어를 불러오기 위해 다음과 같은 코드를 사용하였지만 background에서 기기 언어를 아에 읽지 못했다.

Platform.localeName
WidgetsBinding.instance.window.locales

// easy_localization
context.deviceLocale

기기의 언어를 알 수 있는 방법을 찾다가 devicelocale이라는 패키지를 찾았고, 이 패키지를 사용하면 background에서도 현재 locale을 읽을 수 있었다.

devicelocale
https://pub.dev/packages/devicelocale

그래서 위의 코드에 현재 기기의 언어를 확인해서 easy_localization으로 locale을 바꿔주는 코드를 추가하였다.

  // 현재 언어 확인
  final currentLocale = await Devicelocale.currentLocale;
  
  await EasyLocalization.ensureInitialized();
  final controller = EasyLocalizationController(
    saveLocale: false,
    supportedLocales: locales,
    useOnlyLangCode: true,
    fallbackLocale: locales[0],
    useFallbackTranslations: true,
    path: localizationPath,
    onLoadError: (FlutterError e) {},
    assetLoader: const RootBundleAssetLoader(),
  );
  
  // 현재 기기 언어로 locale set
  if (currentLocale != null) {
    await controller.setLocale(Locale(currentLocale.substring(0, 2)));
  }
  
  await controller.loadTranslations();
  Localization.load(
    controller.locale,
    translations: controller.translations,
    fallbackTranslations: controller.fallbackTranslations,
  );

3. 느낀점

열심히 삽질을 해서 결국 발견한 문제들은 모두 해결하였지만 다국어 처리를 포함해서 notification message 자체를 서버에서 내려주기로 변경되어, 최종적으로 이 코드들은 사용되지 않았다.

아무래도 앱에서 notification message까지 처리하게 되면 새로운 notification을 추가할 때마다 앱을 새로 배포해야 하고, 앱 심사기간이 있기 때문에 공지 같은 단발성 notification에도 빠르게 대응하기 어려울 것이다.

그렇지만 이 문제를 해결하면서 notification과 관련해서 많은 부분을 새로 공부할 수 있었다.
단순히 문서나 다른 사람의 기록을 보는 것 보다 실제로 코드를 짜보고 특히 에러가 발생했을 때 해결하면서 많이 배우게 되는 것 같다.

또, 플러터를 사용한지 이제 반년정도 됬는데 문제를 하나씩 해결할 때마다 뿌듯하기도 하지만 한편으로는 아직 참고할만한 자료가 많지 않은 것 같다.
물론 아직 검색어를 잘 못 잡거나, 공식문서를 제대로 살펴보지 않아서 그럴 수도 있지만, 분명 나만 겪는 문제가 아닐 것 같은데??? 생각보다 찾아보면 자료 찾기가 어렵다고 느낀다.

플러터 생태계가 빨리 빨리 커지길....!

profile
Flutter로 앱개발하고 있어요! iOS도 공부하고 있습니다.

0개의 댓글