Android

Firebase Crashlytics 적용하기

MJ핫산 2022. 12. 8. 10:53

작년 여름부터 진행하던 사이드 프로젝트가 드디어 어느정도 마무리 되었다. 그래서 사이드 프로젝트를 스토어에 올리기 전에 Firebase Crashlytics를 적용하려고 한다.

Firebase Crashlytics에 대해 간단히 소개하자면 “앱이 비정상적으로 종료되었을 때 개발자에게 알려주는 일종의 오류 보고 도구”이다. 그리고 공식 문서에서는 아래와 같이 소개한다.

실시간 비정상 종료 보고 도구인 Firebase Crashlytics는 실제 사용자에 미치는 영향을 기반으로 가장 심각한 비정상 종료의 우선순위를 지정하고 문제를 해결하는 데 도움을 줍니다.
https://firebase.google.com/products/crashlytics?hl=ko
 

Firebase Crashlytics | 강력한 Android 및 iOS 비정상 종료 보고 솔루션

Android 및 iOS 실시간 비정상 종료 보고 도구인 Firebase Crashlytics는 실제 사용자에 미치는 영향을 기반으로 가장 심각한 비정상 종료의 우선순위를 지정하고 문제를 해결하는 데 도움을 줍니다. 또

firebase.google.com

즉, 운영환경에서 내 앱이 어떤 상황에서, 어떤 코드에서 죽었는지 알 수 있다.

User Driven Develop이 가능해진다. ㅎ

🥑 프로젝트에 적용해보자

적용 방법은 간단하다.

Firebase Console에서 Crashlytics 메뉴로 들어가보면 이런 화면이 뜬다. 여기서 ”SDK추가” 버튼을 누르면 공식문서로 이동하는데, 해당 내용을 참고해서 프로젝트에 라이브러리를 import해주면 끝!

현재 최신 버전 또는 원하는 버전 라이브러리를 import 시키면 된다. 아래는 예시.

// build.gradle(:project)
dependencies {
	classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
}

// build.gradle(:app)
plugins {
	...

	id 'com.google.firebase.crashlytics'
}

dependencies {
	...

	implementation platform("com.google.firebase:firebase-bom:$firebase_version") // 29.1.0
	implementation 'com.google.firebase:firebase-crashlytics-ktx'
	implementation 'com.google.firebase:firebase-analytics-ktx'
}

Crashlytics 라이브러리를 무사히 import 시켰다면 이제 테스트를 해볼 차례다.

throw RuntimeException("Test Crash") // Force a crash

이렇게 코드로 테스용 크래시를 발생시켜준다. 실제 상황에서는 NullPointerException이나 IndexOutOfBoundsException.. 등의 에러가 발생할 수 있을것이다. 위와 같이 강제로 크래시를 발생시키는 코드를 넣고 앱을 실행시키면, 앱이 죽게 되고 파이어베이스 콘솔에는 "Test Crash"라는 에러 기록이 남을 것이다 🌟

 

Crashlytics가 적용된 프로젝트(앱)에서 크래시를 발생시킨 후 다시 콘솔로 돌아가면?

큼큼,, 조금만 기다려 봅시다… ⏳

보통 약 5분 정도 걸린다고 하네요.. ^^;

위 사진과 같이 크래시 종류, 로그 뿐만 아니라 버전, 사용 기기 등 크래시를 잡는데 도움이 될만한 데이터가 쌓이게 된다!

 

🌤 크래시에 대한 더 많은 힌트를 얻기 위해서는..

기본 로그와 정보들로도 충분히 많은 정보를 얻을 수 있지만, 오류 해결을 위해 더 많은 힌트를 얻으려면 추가적인 작업을 해줄 수 있다. 예를들면 커스텀 키, 로그 등을 활용하거나 사용자 구분 넣기, 심각하지 않은 예외 보고 등이 있다. 차례대로 살펴보면...

 

1. 커스텀 키

커스텀 키를 사용하면 비정상 종료된 앱의 구체적인 상태를 확인할 수 있다. 임의의 “키-값” 쌍을 비정상 종료 보고서에 연결하고 커스텀 키를 사용하여 검색/필터링 할 수 있다.

crashlytics.setCustomKeys {
    key("my_string_key", "foo") // String value
    key("my_bool_key", true)    // boolean value
    key("my_double_key", 1.0)   // double value
    key("my_float_key", 1.0f)   // float value
    key("my_int_key", 1)        // int value
}

키-값은 덮어씌울 수도 있다.

crashlytics.setCustomKeys {
    key("current_level", 3)
    key("last_UI_action", "logged_in")
}

 

2. 커스텀 로그

상세한 배경정보 파악을 위해 로그를 추가할 수 있는데, 로그는 비정상 종료 데이터에 연결되고 만약 세션의 로그 크기가 한도(64KB)를 초과하면 이전 로그 항목을 삭제한다고 한다.

Firebase.crashlytics.log("message")

 

3. 사용자 식별자

어떤 사용자에게서 비정상 종료가 발생했는지 파악하기 위해 사용자 식별자를 추가할 수 있다.

만약 사용자 식별자를 삭제해야 하는 경우라면 빈 문자열로 재설정하면 된다. (사용자 식별자를 지워도 기존 Crashlytics 기록들은 삭제되지 않는다.)

Firebase.crashlytics.setUserId("user123") // 사용자 id, 고객번호 등
Firebase.crashlytics.setUserId("") // 초기화

 

4. 심각하지 않은 예외 보고

심각하지 않은 (앱이 죽지는 않는 경우..?) 예외를 기록해뒀다가 다음 앱 실행 때 이 로그를 받을 수 있다. 

참고로 최대 8개까지만 저장할 수 있고, 8개를 초과하면 이전 로그를 삭제한다.

try {
    methodThatThrows()
} catch (e: Exception) {
    Firebase.crashlytics.recordException(e)
    // handle your exception here
}

 

🐣 활용해보자

val crashlytics = FirebaseCrashlytics.getInstance()

object CrashlyticsLogger {
    private const val LAST_UI_ACTION = "last_ui_action"

    fun setLastUIAction(action: String) {
        crashlytics.setCustomKey(LAST_UI_ACTION, action)
    }

    fun setUser(id: String) {
        crashlytics.setUserId(id)
    }

    fun log(message: String) {
        crashlytics.log(message)
    }
}

나는 이런식으로 유틸 클래스를 하나 만들어두고, 각 함수들을 이용해서 프로젝트의 상황을 로깅하고 있다.

 

예를 들면

  • 로그인하면 setUser(userNumber)
  • 버튼 클릭할 때 setLastUIAction(”회원가입 버튼 클릭”)
  • try-catch문 안에 recordException()로 예외상황 기록하기

 

🍮 마무리

앱이 죽지 않는다면 제일 좋겠지만… 앱이 죽을 정도의 이슈가 있다면 얼른 해결하는 것이 가장 좋기 때문에 프로젝트에 Crashlytics 적용해두는거 좋은 것 같습니다~

 

생각보다 개복치였던 나의 앱.. 🐠