Flutter 개발

Firebase Crashlytics 실전: 프로덕션 크래시 추적과 대응

크래시 리포트부터 Slack 알림까지

John Doe
2026년 3월 8일
7분 읽기
39

Crashlytics가 필요한 이유

배포 후 유저 기기에서 크래시가 나면 로그를 볼 방법이 없습니다. 유저한테 '어떤 에러가 났나요?'라고 물어볼 수도 없고요.

Crashlytics는 크래시 스택트레이스를 자동 수집합니다. 어떤 기기, 어떤 OS 버전에서 터졌는지까지 알 수 있어요.

Flutter 프로젝트에 Crashlytics 세팅

firebase_crashlytics 패키지를 추가하고 main에서 초기화해요. Zone과 FlutterError.onError 두 가지를 모두 잡아야 하죠.
Dart
// pubspec.yaml
dependencies:
  firebase_core: ^2.24.0
  firebase_crashlytics: ^3.4.0

// main.dart
void main() async {
  // Zone으로 비동기 에러 캐치
  runZonedGuarded(() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();

    // Flutter 프레임워크 에러 캐치
    FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;

    runApp(const MyApp());
  }, (error, stackTrace) {
    // Zone에서 잡히는 비동기 에러
    FirebaseCrashlytics.instance.recordError(error, stackTrace, fatal: true);
  });
}

커스텀 키와 로그 남기기

스택트레이스만으로는 원인 파악이 어려울 때가 많습니다. 커스텀 키로 유저 상태를 기록하고, 로그로 크래시 직전 행동을 추적하세요.
Dart
// 유저 식별 정보 설정
FirebaseCrashlytics.instance.setUserIdentifier(userId);

// 커스텀 키 (크래시 리포트에 함께 표시)
await FirebaseCrashlytics.instance.setCustomKey('screen', 'game_detail');
await FirebaseCrashlytics.instance.setCustomKey('game_id', gameId);
await FirebaseCrashlytics.instance.setCustomKey('subscription', 'premium');

// 로그 (크래시 직전 행동 추적, 최대 64KB)
FirebaseCrashlytics.instance.log('게임 상세 화면 진입: $gameId');
FirebaseCrashlytics.instance.log('플레이 버튼 탭');
FirebaseCrashlytics.instance.log('WebView 로딩 시작');

비치명적 에러 기록

앱이 죽지는 않지만 비정상 동작을 일으키는 에러도 추적해야 돼요. try-catch에서 recordError로 보내세요.
Dart
try {
  final response = await apiClient.fetchGameData(gameId);
  return GameData.fromJson(response);
} catch (e, st) {
  // 비치명적 에러 기록 (fatal: false)
  FirebaseCrashlytics.instance.recordError(
    e, st,
    reason: 'fetchGameData 실패',
    fatal: false,
  );
  // 폴백 처리
  return GameData.empty();
}

릴리스별 크래시 추적

버전별로 크래시율을 비교하면 어떤 릴리스에서 문제가 생겼는지 바로 알 수 있어요. Firebase 콘솔에서 버전 필터링이 가능하죠.

새 버전 배포 후 24시간은 크래시율을 집중 모니터링하세요. 0.5%를 넘으면 핫픽스를 고려해야 돼요.

Slack 알림 연동

Firebase 콘솔을 매번 들어가볼 수 없으니 Slack으로 알림을 보냅니다. Firebase Functions + Crashlytics 트리거를 사용해요.
JavaScript
// functions/src/index.ts
import { onNewFatalIssuePublished } from 'firebase-functions/v2/alerts/crashlytics';
import { IncomingWebhook } from '@slack/webhook';

const webhook = new IncomingWebhook(process.env.SLACK_WEBHOOK_URL!);

export const crashlyticsAlert = onNewFatalIssuePublished(async (event) => {
  const { appVersion, id, title, subtitle } = event.data.payload.issue;

  await webhook.send({
    text: `[Crashlytics] 새 크래시 발생`,
    blocks: [
      {
        type: 'section',
        text: {
          type: 'mrkdwn',
          text: `*${title}*\n${subtitle}\n버전: ${appVersion}\n<https://console.firebase.google.com/project/my-project/crashlytics/issues/${id}|상세 보기>`,
        },
      },
    ],
  });
});

실전 대응 사례

배포 직후 Galaxy S21에서만 크래시가 몰렸습니다. Crashlytics에서 기기 필터링으로 확인하니 WebView 초기화 시점에 null 참조가 발생하고 있었습니다.

원인은 One UI 6.0의 WebView 업데이트에서 바뀐 초기화 타이밍이었습니다. 커스텀 키에 OS 버전을 기록해뒀던 덕에 빠르게 범위를 좁힐 수 있었습니다. 핫픽스까지 4시간 만에 처리했거든요.
#Firebase
#Crashlytics
#모니터링
#Slack
#프로덕션
#에러 추적