이전 버전의 Unity를 사용하는 경우 종료 원인을 파악하기 위해 ANR 플러그인을 사용해야 했지만, Unity 6부터는 ApplicationExitInfo을 통해 직접 정보를 얻을 수 있는 API를 제공합니다.
ApplicationExitInfo는 ANR 및 앱 충돌의 원인을 진단하고 이해하는 데 도움이 되도록 설계된 강력한 Android API입니다. Unity 6 이상을 사용하는 경우 ApplicationExitInfo에 직접 액세스하여 앱이 예기치 않게 종료된 이유에 대한 자세한 정보를 얻을 수 있습니다. ApplicationExitInfo를 사용하면 stack trace 및 tombstone과 같은 중요한 데이터에 액세스할 수 있으며, 이는 문제 해결을 위한 귀중한 컨텍스트를 제공합니다.
또한 API를 사용하여 최대 128바이트 크기의 바이트 배열로 상태 데이터를 저장하고 검색할 수 있습니다. 이 기능을 사용하면 레벨 또는 장면 ID, 플레이어 데이터, 문제 발생 당시 게임 상태와 같은 중요한 정보를 유지할 수 있습니다. ANR이 발생한 후 이 데이터를 분석하면 문제가 있는 부분을 효과적으로 파악하고 해결할 수 있습니다.
Unity 6에서는 ANR을 최소화 할 수 있도록 지속적인 개선 작업을 하고 있습니다. ANR, 크래시 등을 감지하기 위해 ApplicationExitInfo를 제공하는 것 이외에도, 안드로이드에서 게임 앱을 위해 제공하고 있는 GameActivity를 기본으로 사용합니다. 이와 관련된 내용도 함께 소개합니다.
Unity 6에서는 안드로이드의 ApplicationExitInfo를 지원하기 위해, IApplicationExitInfo 인터페이스를 제공합니다. 제공되는 인터페이스를 통해 reason, description, state, trace 등의 정보를 얻을 수 있습니다.
인터페이스에 대한 자세한 정보는 매뉴얼에서 확인하실 수 있습니다.
이제 제공되는 주요 정보들에 대해 알아보겠습니다.
IApplicationExitInfo.reason을 통해 종료 원인에 대한 정보를 얻을 수 있습니다. 미리 정의된 ExitReason에 대한 정보는 매뉴얼에서 제공하고 있습니다.
IApplicationExitInfo.reason의 값으로 ANR이 들어왔을 때, ANR이 발생한 상황임을 확인할 수 있습니다. Unity에서 ANR을 감지했을 때, 디버깅하는 방법은 안드로이드 개발 문서에서 자세히 설명하고 있습니다.
안드로이드에서 종료 원인에 대한 추가 정보를 입력할 수 있는 API를 제공합니다. 128비트 크기의 배열 데이터에 필요한 정보를 입력할 수 있습니다.
Unity 6에서는 이 메서드를 스크립트에서 호출할 수 있도록 ApplicationExitInfoProvider를 통해 제공합니다. ApplicationExitInfoProvider의 SetProcessStateSummary(sbyte[] buffer) 함수를 호출하여 정보를 추가로 입력할 수 있습니다. 이렇게 입력된 정보는 앱이 종료될 때, ApplicationExitInfo.processStateSummary에서 확인할 수 있습니다.
ApplicationExitInfoProvider에 대한 자세한 내용은 매뉴얼을 참고하시기 바랍니다.
지금까지 ApplicationExitInfo에 대해 소개하였습니다. 이제 사용하는 방법을 아래에서 살펴보겠습니다.
정보를 가져오기 위해, ApplicationExitInfoProvider에서 제공하는 함수를 사용할 수 있습니다. 아래의 함수는 이전에 종료되었던 ApplicationExitInfo 정보를 가져오는 함수입니다.
먼저, ApplicationExitInfo을 남길 수 있도록 ANR을 발생시키는 예제를 만들었습니다. 버튼을 클릭했을 때 오랜 시간을 대기하도록 만들었습니다. 추가로 SetProcessStateSummary(sbyte[] buffer)를 호출하여, 1 ~ 7의 값을 입력했습니다. 캔버스에 버튼을 추가하여, 아래의 스크립트가 실행되도록 했습니다. 쓰레드를 일정 시간동안 sleep시켰고, 임의로 ANR이 발생하도록 했습니다. ANR이 발생되면, 앱 닫기를 해줍니다.
그 다음, 다시 앱을 구동하여 아래의 코드가 실행되도록 했습니다. 종료 원인에 따라서는 종료 시점에 로그가 남지 않을 수도 있습니다. 따라서, 이번 예제에서는 pid, maxNum에 값을 따로 주지 않고, 앱을 한 번 종료한 다음, 재시작하여 Awake() 함수에서 로그를 출력해서 확인했습니다.
마지막으로, 디바이스의 로그를 확인하기 위해 안드로이드 로그캣을 이용했습니다. 패키지 매니저에서 android logcat을 검색하여 설치할 수 있습니다. 로그캣을 통해 디바이스에 출력된 로그를 확인하면 아래와 같습니다.
추가로, 버튼을 클릭할 때 입력했던 값이 ApplicationExitInfo에 잘 들어갔는지 확인할 차례입니다. 아래와 같이 코드를 작성하여 로그를 남겼습니다.
결과는 아래와 같습니다. 1 ~ 7의 값이 제대로 들어가 있음을 확인할 수 있었습니다. 실제 프로젝트에 적용할 때는 유효한 값을 입력하여 사용하시기 바랍니다.
GameActivity가 ANR과 관련하여 개선된 기능을 제공하기 때문에 본 아티클에서 함께 소개합니다. GameActivity는 Android Game Development Kit의 구성요소로, 애플리케이션의 C/C++ 코드에서 앱 주기 명령어, 입력 이벤트, 텍스트 입력을 처리하는 데 Android 게임을 지원하도록 설계되었습니다.
기본적으로 NativeActivity를 기반으로 하며 Fragment, SurfaceView 렌더링, 인기 게임 개발 관련 라이브러리 지원 등 게임 앱에 필요한 개선사항을 추가로 제공합니다. 또한, GameActivity는 입력 버퍼에 이중 버퍼링을 사용하므로 입력 볼륨이 큰 게임에서 더욱 개선된 입력 처리가 가능합니다. GameActivity와 NativeActivity의 주요 차이점은 안드로이드 개발자 문서에서 자세히 확인할 수 있습니다.
GameActivity는 게임용으로 설계되었으며, 입력 버퍼 개선 등의 새롭게 제공되는 기능이 ANR 감소에도 큰 도움을 주고 있습니다. 안드로이드 개발자 문서에서 실제 게임에 사용된 사례를 공유하고 있으니 아래의 문서를 참고하시기 바랍니다.
설정 방법은 Project Settings > Player(안드로이드 플랫폼) > Other Settings > Application Entry Point에서 확인할 수 있으며, 기본으로 GameActivity를 사용하도록 설정되어 있습니다. 만약, 프로젝트에서 GameActivity를 사용하지 않을 예정이면 선택을 해제할 수 있습니다.
Unity 6에서는 안드로이드 플랫폼에서의 종료 원인 분석을 위해 ApplicationExitInfo를 새롭게 제공합니다. ApplicationExitInfo를 활용하여 ANR이나 크래시를 해결하는 데 도움이 되는 정보를 얻을 수 있습니다. 그리고 게임 앱을 위해 제공되는 GameActivity가 Unity 6에서 기본으로 사용되고 있으며, 기능과 설정하는 방법에 대해 간단히 소개했습니다.
새롭게 제공되는 기능이 안드로이드 플랫폼에서의 안정적인 서비스를 구현하는 데 도움이 되길 바랍니다.