적용 배경
외주를 진행했던 프로젝트에서 앱이 설치된 테블릿은 24시간 켜져있어야 되는데 어느 순간 꺼진다는 문제가 발생했다.
처음에 현장에 갔을때 다음 이미지와 같이 오류창이 나오길 기대했었는데 해당 오류창도 안나오고 그냥 꺼져있는 화면이 나를 반기고있었다.
테블릿에 대한 테스트 환경은 마련되었으니까 결과적으로 필요한건 앱이 왜 꺼지는가? 로그를 분석하기위해 Firebase 에서 제공하는 Crashlytics 를 적용해서 꺼지는 이유를 알아보려고 한다.
Crashlytics 는 뭘까?
https://firebase.google.com/docs/crashlytics?hl=ko
Firebase Crashlytics
Apple, Android, Flutter, Unity를 위한 강력한 비정상 종료 보고 솔루션으로 앱 문제에 대한 명확하고 활용 가능한 분석 정보를 확인해 보세요.
firebase.google.com
공식 문서의 한 부분을 보면 다음과 같이 쓰여있다.
Firebase Crashlytics는 가벼운 실시간 비정상 종료 보고 도구로 앱 품질을 저하하는 안정성 문제를 추적하고 우선순위를 지정하고 문제를 해결하는 데 도움이 되빈다. Crashlytics는 비정상 종료를 지능적으로 그룹화하고 이러한 비정상 종료를 유발하는 상황을 강조하여 보여주므로 문제 해결 시간이 절약 됩니다.
특정 비정상 정료가 여러 사용자에게 영향을 미치는지 확인해 보세요. 문제의 심각도가 급격히 증가하면 알림이 전송됩니다. 어떤 코드 줄이 비정상 종료를 일으키는지 파악할 수 있습니다.
어디서 어떤 오류로 종료되는가를 알기위해서 완전 내가 필요한 부분이다.
공식 문서에서 정의된 주요 기능으로는 다음과 같다.
선별된 비정상 종료 보고서
- Crashlytics는 다량의 비정상 종료를 처리하기 쉽게 문제 목록으로 종합하여 보여주고, 상황 정보를 제공하고, 비정상 종료의 심각도와 발생률을 강조 표시하므로 근본 원인을 더욱 빠르게 파악할 수 있습니다.
자주 말생하는 비정상 종료 해결법
- Crashlytics가 제공하는 비정상 종료 통계는 자주 발생하는 안정성 문제를 강조 표시하고, 더욱 쉽게 문제를 파악하고 분류하고 해결 할 수 있도록 리소스를 제공하는 유용한 도움말 입니다.
애널리틱스와 통합
- Crashlytics는 앱의 오류를 Analytics의 app_exception 이벤트로 캡쳐할 수 있습니다. 이벤트는 각 비정상 종료로 이어지는 다른 이벤트 목록에 대한 액세스를 제공하여 디버깅하고 단순화하고, 비정상 종료가 발생한 사용자의 Analytics 보고서를 가져와 잠재 고객 통계를 제공합니다.
실시간 알림
- 즉각적인 대응이 필요할 수 있는 새로운 문제, 재발된 문제, 증가 중인 문제에 대해 실시간 알림을 받을 수 있습니다.
Crashlytics 적용해 보기
모든 순서는 공식문서상의 내용을 기반으로 작성했다.
iOS 시절부터 느끼지만 파이어베이스 공식문서는 너무나도 잘되어있다.
Firebase Crashlytics 시작하기
의견 보내기 Firebase Crashlytics 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. iOS+ Android Flutter Unity 이 빠른 시작에서는 Firebase Crashlytics SDK를 사용해
firebase.google.com
우선적으로 프로젝트에 Firebase를 구성해야한다.
만약 프로젝트 내부에 Firebase 가 구성이 되어있지 않다면 구성해 주도록 한다.
[Flutter] Firebase 연동하기
Flutter를 사용해서 Firebase를 연동하기 Intro이번에는 개인 프로젝트에서 가장많이 사용하는 Firebase의 연동방법에 대해서 알아보려고 합니다.Firebase 관련 아예 처음 한다고 생각하고 최대한 자세하
sj-d.tistory.com
다음으로 Firebase 공식문서의 권장사항인데 Google Analytics를 사용설정 해주는 것이다.
어려운건 없고 Firebase Console > 톱니바퀴 > 통합 > Google Analytics 사용설정을 해주면 된다.
1. Flutter 프로젝트 폴더로 이동 후 다음 명령어 실행
flutter pub add firebase_crashlytics && flutter pub add firebase_analytics
2. Flutter 프로젝트의 루트 디렉토리에서 다음 명령어 실행
flutterfire configure
3. Flutter 빌드
정상적으로 되었다면 플러터 프로젝트를 다시 빌드해봅니다.
4. 비정상 종료 핸들러 구성
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
// Pass all uncaught "fatal" errors from the framework to Crashlytics
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
runApp(MyApp());
}
이렇게 사용하게되면 FlutterError.onError를 FirebaseCrashlytics.instance.recordFlutterFatalError 로 재정의하여 Flutter 프레임 워크 내에서 발생하는 모든 오류를 자동으로 포착할 수 있다.
Flutter 프레임워크에서 처리하지 않는 비동기 오류에 대해서 포착하려면
PlatformDispatcher.instance.onError 를 사용한다.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FlutterError.onError = (errorDetails) {
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
};
PlatformDispatcher.instance.onError = (error, stack) {
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
return true;
};
runApp(const MyApp());
}
예를 들어 기존 앱에서 강제로 오류를 발생해서 테스트해 볼수있다.
관련 예시
강제 크래시 발생 시키기
ElevatedButton(
// onPressed: () => checkDocumentExists(),
onPressed: () => throw Exception('오류 테스트'),
child: const Text('확인'),
),
다음과 같이 로그가 발생하는 걸 볼 수있다.
다양한 예외 상황 테스트
NullPointerException 또는 IndexOutOfBoundsException과 같은 일반적인 비정상 종료 상황을 강제로 발생시켜 테스트 할 수도 있다.
IndexOutOfBoundsException 발생 예제
IndexOutOfBoundsException 발생 예제
List<String> testList = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
ElevatedButton(
onPressed: () {
print(testList[10]);
},
child: const Text('확인'),
),
리스트는 현재 10개의 항목을 담고있는데 11번쨰 리스트에 대해서 출력을 찍으면 다음과 같이 오류를 보여주게된다.
NullPointerException 발생 예제
String? testString;
ElevatedButton(
onPressed: () {
print(testString!);
},
child: const Text('확인'),
),
다음과 같이 친절하게 어디서 어떤 오류가 발생했는지 보여준다.
지금 값은 경우에는 옵셔널값에 대해서 강제로 출력을 찍어서 발생한 오류이다.
앱 자체의 비정상 종료에 대한 테스트
Throw 대신 FirebaseCrashlytics.instance.crash() 코드를 사용하게 되면 아예 앱 자체를 비정상 종료 시킬 수 있다.
이렇게 되면 파이어베이스 콘솔에 다음과 같이 오류가 나타난다.
사용자 정의 테이터 추가
앱 상태를 더 구체적으로 기록하기 위해서 다음과 같이 커스텀 키를 사용하거 유저 식별자를 넣어서 보내줄 수도있다
ElevatedButton(
onPressed: () async {
try {
// Crashlytics 사용자 정보 및 커스텀 키 설정
await FirebaseCrashlytics.instance.setCustomKey("schoolId", _schoolIdController.text);
await FirebaseCrashlytics.instance.setUserIdentifier(_classUniqueNumberController.text);
// 테스트용 강제 크래시 발생
FirebaseCrashlytics.instance.crash();
} catch (error, stackTrace) {
// 에러 발생 시 Crashlytics에 기록
await FirebaseCrashlytics.instance.recordError(
error,
stackTrace,
reason: '로그인 시도 중 에러 발생',
);
}
},
child: const Text('확인'),
),
크래시가 발생하는건 똑같은데 이제는 커스텀키에 schoolId 와 텍스트를 넣어놨었다.
다음과 같이 키에 값이 들어오게 되고
유저 식별자 또한 넣어놨기때문에 검색을 통해 해당 유저가 발생하는 오류에 대해서 찾을수 있다.
이제 해당 앱 배포하고 진짜 오류가 오길 기다리면 된다!
결론
현재 회사 프로젝트에는 적용되어있긴한데 아직 정확하게 로그를 찍어보고 활용해 보진 못했다.
적용되어있었고 결과적으로 내가 적용한것도 아니고 iOS를 공부하면서도 해당 부분에 대해 크게 신경쓰지 않아서 설치해본적 없었는데 상당히 편리한 도구인것 같다.
개발을하면서 오류는 피할수없는 상황이 많은데 이제 어디서 어떤 오류가 발생하는지 조금 더 디테이하게 핸들링 할수있을것 같다.
자세하게 알아보기 전 까진 이정도로 딥하게 오류에 대해서 제공해 주는지도 몰랐다.
이제 개발을하면서 조금 더 오류 핸들링에 대해서 신경쓰면서 해야겠다고 느꼈다.
'📱Flutter' 카테고리의 다른 글
Flutter 신용카드 예제 Like 카카오페이 1편 (1) | 2025.02.19 |
---|---|
Flutter 의 annotation 에 대해 (0) | 2025.02.12 |
Flutter 에서의 비동기 프로그래밍 Future, async/await (0) | 2025.01.31 |
Dart로 알아보는 SOLID 원칙 (0) | 2025.01.09 |
Flutter Equatable의 이해 (0) | 2024.12.29 |