앱을 개발하고 운영하다보면 예기치 않은 오류를 맞이하게 됩니다.
모든 앱개발자가 앱에서 오류가 발생하지 않기를 원하지만 한번도 오류를 발생시켜보지 않은 개발자는 없을것입니다.(그런 개발자분이 계신다면 지금 바로 지원해주세요)
구글이 만든앱도 오류가 발생합니다. 너무 스스로를 자책하지 마세요
이런 오류를 감지하고 수정하기 위해서 우리는 다양한 오류 리포팅 서비스를 이용하고 있습니다.
[안드로이드/Android]오류 리포팅 서비스 비교(Google Analytics, URQA, Userhabit, Fabric) 학교 과제 제출용이든, 회사 테스트 프로젝트든, 스타트업 서비스를 운영하시든 각자 여러가지 이유로 안드로이드 앱을 개발하고 계실겁니다. (저는 스타트업하는 불효자식입니다...) 그렇게 안드로이드 앱을 개발하고나면…gun0912.tistory.com
요즘에는 안드로이드든 아이폰이든 Firebase Crashlytics를 필수로 사용하고 있는 추세입니다.(Firebase Crashlytics는 Fabric Crashlytics와 같은 서비스입니다.)
이런 오류 리포팅 서비스들을 활용하면 오류가 발생하는것을 알게되고 이를 즉각적으로 수정해서 문제를 조기에 해결할 수 있습니다.
사용자 입장에서의 오류
하지만 그럼에도 불구하고 여전히 사용자의 오류경험은 개선되지 않았습니다.
사용자는 이유도 모른채 앱이 종료되어 버릴것이며 ‘뭐하자는거지?’ 라고 생각하고 앱을 떠나버릴 수도 있습니다. 이는 고객 이탈률의 치명적인 영향을 끼칩니다.
오류가 발생하면 어떻게 처리되면 좋을까?
오류가 발생했을때 개발자와 사용자 모두에게 좋은 경험의 흐름으로 흘러가기위해서는 아래와 같은 시나리오로 흘러가기를 바랬습니다.
오류 발생시 즉각적인 오류 리포팅으로 개발자가 알 수 있도록 함
사용자에게 문제가 생겼음을 알림
이전에 열려있었던 화면을 다시 실행할 수 있도록 제공
그래서 헤이딜러 앱에서는 오류가 발생했을때 아래와 같은 화면을 보여주고 사용자가 다시 이전 화면을 실행할 수 있도록 제공하도록 하고 있습니다.
이것이 바로 헤이딜러에서 오류가 발생했을때 사용자에게 나타나는 화면입니다.
앱을 사용하다가 오류가 발생하면 아래와 같은 시나리오로 사용자경험이 이루어집니다.
어때요? 오류가 발생하더라도 사용자는 앱을 이탈하지 않고 이전화면으로 다시 빠르게 돌아올 수 있게 되어 이탈을 막을 수 있습니다.
이로써 기존에 불친절하고 사용자에게 좋은 경험이 아니었던 화면보다 좀더 유연하고 아름다운 앱의 오류처리가 가능해졌습니다.
QA팀: “QA중에 오류가 발생했어요'
개발팀: “제 폰에서는 되는데요'
또한 개발/QA 모드일경우에는 오류 화면에서 어떤 오류인지까지 표시해주도록 합니다. QA팀과 개발팀간의 사이가 좋아집니다.
개발자가 아닌 대표님이나 기획자분이 이 글을 보셨다면 개발자에게 공유해주시고 각자의 서비스에 맞는 오류대응이 가능하도록 하시면 좋을것 같습니다.
구현
오류 화면에 대한 구현 원리는 아래와 같습니다.
Global하게 오류를 처리하는 Handler생성
오류가 발생할 경우 이 Handler에서 catch
Crashlytics에 해당 오류내용을 보고
직전에 실행했었던 화면 정보를 가져와서 실행
실행먼저 해보고 싶으신 분들은 아래 GitHub을 통해서 확인해보시면 됩니다.
PRNDcompany/Android-ErrorActivity-Sample Contribute to PRNDcompany/Android-ErrorActivity-Sample development by creating an account on GitHub.github.com
Application class에서 오류처리 Handler 설정
defaultExceptionHandler: 안드로이드의 기본 오류 처리 Handler
fabricExceptionHandler: Crashlytics에서 사용되는 오류처리 Handler
HeyDealerExceptionHandler: 위의 2개를 가지고 있으며 오류처리 화면을 표시하기 위한 Handler
Crashlytics에서는 내부적으로 defaultExceptionHandler를 활용해서 오류를 보내도록 구현되어 있습니다. 그래서 기본 Handler를 가져온뒤에 아무 작업도 하지 않는 빈 handler설정을 해주는 작업이 필요합니다.
참고로 Firebase Crashlytics에서도 보여지길 원하신다면 Fabric Crashlytics를 사용설정 하시고 Firebase에서 해당 프로젝트를 연결해두시면 됩니다.
최근 화면 정보 저장하기
오류발생시 최근에 실행된 화면을 재실행하기 위해서 새로운 화면이 보여질때마다 최신 화면정보를 갱신해줍니다.
init { application.registerActivityLifecycleCallbacks( object : SimpleActivityLifecycleCallbacks() { override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { if (isSkipActivity(activity)) { return } lastActivity = activity } override fun onActivityStarted(activity: Activity) { if (isSkipActivity(activity)) { return } activityCount++ lastActivity = activity } override fun onActivityStopped(activity: Activity) { if (isSkipActivity(activity)) { return } activityCount-- if (activityCount < 0) { lastActivity = null } } }) } private fun isSkipActivity(activity: Activity) = activity is ErrorActivity
오류발생 처리
오류가 발생하면 오류리포팅을 위해 Crashlytics에 알립니다.
오류발생을 알리는 Error Activity를 실행합니다.
마지막으로 실행된 화면정보도 함께 포함합니다.
개발/QA모드인경우 오류내용을 표시하기 위해 오류내용도 함께 넘겨줍니다.
override fun uncaughtException(thread: Thread?, throwable: Throwable) { fabricExceptionHandler.uncaughtException(thread, throwable) lastActivity?.run { val stringWriter = StringWriter() throwable.printStackTrace(PrintWriter(stringWriter))
startErrorActivity(this, stringWriter.toString()) } ?: defaultExceptionHandler.uncaughtException(thread, throwable)
Process.killProcess(Process.myPid()) System.exit(-1) }
오류 화면 실행
오류화면을 새로 실행하면서 직전에 보여졌던 화면정보와 오류내용을 함께 전달합니다.
private fun startErrorActivity(activity: Activity, errorText: String) = activity.run { val errorActivityIntent = Intent(this, ErrorActivity::class.java) .apply { putExtra(ErrorActivity.EXTRA_INTENT, intent) putExtra(ErrorActivity.EXTRA_ERROR_TEXT, errorText) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) } startActivity(errorActivityIntent) finish() }
전체 HeyDealerExceptionHandler 코드는 아래와 같습니다.
오류 화면
오류 화면은 간단합니다.
재실행버튼 클릭시 마지막 화면정보를 이용하여 화면 실행
개발/QA모드인경우 오류내용을 화면에 표시
전체 소스코드는 아래 GitHub에서 확인가능합니다.
PRNDcompany/Android-ErrorActivity-Sample Contribute to PRNDcompany/Android-ErrorActivity-Sample development by creating an account on GitHub.github.com
마치며
앱을 개발하면서 오류는 항상 발생하지만 이 오류에 얼마나 잘 대응 하느냐는 개발자의 몫입니다.
이 포스팅을 참고하셔서 각자 운영중인 서비스의 특성에 맞게 아름답게 오류에 대응하셨으면 좋겠습니다.
더 좋은 오류처리 방식이나 피드백이 있으시다면 댓글로 남겨주시면 감사하겠습니다.
저희와 함께 헤이딜러 서비스를 발전 시켜나가실 분들을 기다리고 있습니다.
http://bit.ly/prnd-hiring
위의 채용링크로 많은 지원부탁드립니다.
감사합니다.