이번 회사 프로젝트에 오래 걸린 디버깅이 있어서 까먹기전(?)에 정리를 해놓는다.
현재 회사에서 담당하고 있는 프로젝트는 React-Native 로 되어있지만, 특정 테블릿(안드로이드)에만 설치가 되어 제공을 하기에, 철저히 안드로이드 관련된 내용이라
Android와 관련된 공부를 하게되어 기쁘다.
현재 코드푸쉬를 할때마다 1500대정도 꾸준히 업데이트를 성실히 따라오고 있는데, 유독 한 매장에서 자꾸 '앱이 종료된다' 라는 CS가 들어왔다.
당연히 ANR 은 치명적인 오류이기에, 즉각 대응에 나섰다.
일단 지금 서비스에는 data dog / google crashlytic 가 붙어있다.

해당 증상이 발생했다는 날에 정보를 확인해봐도 2600개의 세션중에 crash report 는 없었다.
물론 google crashlytics 도 마찬가지였다.
data dog 의 내부로직은 모르지만, google crashlytics은 MainActivity.java의 UncaughtExceptionHandler 를 오버라이딩해서 사용하고있다.
그러면 해당 에러는 해당 핸들러에 안걸리는 이유로 '앱이 종료된다'고 유추하였다.
해당 핸들러에 안걸리는 가장 큰 이유중의 하나는 '메모리'문제이다.
따라서 해당 매장의 환경(광고대기화면)과 동일한 환경으로 세팅을하여 일주일정도 메모리 사용량을 확인하였다.

adb 로 테블릿을 무선으로 연결한후, adb top 이라는 터미널 명령어로 메모리트래킹을 했는데, 메모리가 점점 쌓이는 현상은 발견되지 않았다.
지금까지 개발을 하면서, 앱이 비정상종료가 되었는데, 아무 이유를 파악할 수 없는 경우는 처음이었다.
CS에서 들어도, 유저가 액션을 하다가 뻗거나, 기능 동작중에 앱이 내려가는 경우가 아니라, 테블릿을 켜놓고 다음날쯤에 꺼지는 경우는 재연이 쉽지가 않았다.
결국 안드로이드 시스템 로그를 확인해보기로 했다.
해당 테블릿을 사용하고 있는 사용자에게 방문하여
adb 로 해당 테이블에 무선연결 후, adb bugreport 로 시스템 로그를 받아왔다.

ApplicationExitInfo 클래스 덕분에 해당 로그에서 우리 앱이 언제 어떻게 왜 종료되었는지 확인을 할 수가있다.
https://developer.android.com/reference/android/app/ApplicationExitInfo
ApplicationExitInfo | Android Developers
developer.android.com
해당 클래스 설명에서 보면, 자세한 원인이 나와있다.
우리의 원인은 13 으로, 안드로이드 문서를 보면

not by problems in apps and not actionable by apps 라고 나와있다.
'앱문제는 아니고, 앱의 액션문제도 아니야'
하지만...고객이 불편하다고 생각하기에 해당 문제를 해결해야한다.
따라서 getDescription 을 통해 자세한 subreason을 확인하기로했다.
this process had been in empty state for a long time;
직역하면, '이 프로세스는 empty state 에 너무 오래있었다' 이다.
안드로이드의 프로세스는
https://developer.android.com/guide/components/processes-and-threads?hl=ko
프로세스 및 스레드 개요 | App quality | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 프로세스 및 스레드 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 애플리케이션 구성요소가 시
developer.android.com
https://developer.android.com/guide/components/activities/process-lifecycle?hl=ko
프로세스 및 앱 수명 주기 | Android Developers
대부분의 경우 모든 Android 애플리케이션은 자체 Linux 프로세스에서 실행됩니다. 이 프로세스는 일부 코드를 실행해야 할 때 애플리케이션용으로 생성되며 더 이상 필요하지 않고 시스템에서 메
developer.android.com
에서 확인할 수 있듯이
foreground > visible > service > cached (empty)
로 나뉜다.
가장 하위 단계의 프로세스에서 너무 오래떠있어서 종료하니까, 우리앱의 프로세스를 높여볼까?
라는 생각으로,
foreground service 를 띄워봤다.
라이브러리를 사용하여 쉽게, 앱이 실행중일때 포그라운드 서비스를 띄워놀수 있게되었다. 해당 포그라운드 서비스는 안드로이드 프로세스의 두번째인 visible process 에 해당한다.
하지만 해당 증상은 계속되었고,
이번에는 WorkManager를 적용하여
java쪽에서
DeviceEventManagerModule.RCTDeviceEventEmitter
네이티브 이벤트를 한시간마다 한번씩 발생해줬고,
를 통해 로그를 찍어놓았다.
이번기회에, 안드로이드의 시스템로그를 보는것과 전반적인 안드로이드의 프로세스에 대해 조금 더 알게되어 기분이 좋다.
'ReactNative' 카테고리의 다른 글
[ React Native ] android device 전원끄기 (1) | 2024.12.20 |
---|---|
[ React Native ] Memory Leak / Memory 초기 사용량 낮추기 (0) | 2024.12.18 |
[ React Native ] Dynamic splash screen by url (서버에서 받아오는 URL 로 스플래시 스크린 세팅하기 ) (1) | 2024.09.05 |
[ React Native ] Dynamic splash screen 적용하기 (0) | 2024.08.12 |
[ React Native ] Kakao login 중 pod install 시 CDN: trunk URL couldn't be downloaded 발생 (0) | 2024.05.02 |