앱 응답성 유지

그림 1. 사용자에게 표시되는 ANR 대화상자.

이 문서에서는 Android 시스템이 앱의 응답 여부를 판단하는 방법을 설명하고 앱의 응답성을 유지하는 방법을 보여줍니다.

코드를 아무리 잘 작성했더라도 앱이 여전히 느리게 느껴지거나, 멈추거나, 상당한 시간 동안 정지되거나, 입력을 처리하는 데 시간이 너무 오래 걸릴 수 있습니다. 앱이 포그라운드에 있고 응답하지 않으면 그림 1과 같이 사용자에게 애플리케이션 응답 없음(ANR) 대화상자가 표시됩니다. ANR 대화상자를 통해 사용자가 앱을 강제 종료할 수 있습니다. 앱이 포그라운드에 있지 않으면 자동으로 중지됩니다. ANR 대화상자를 최소화하도록 앱의 응답을 설계하는 것이 중요합니다.

ANR 트리거

일반적으로 앱이 기본 스레드(UI 스레드라고도 함)의 사용자 입력에 응답할 수 없어 시스템에서 수신되는 사용자 입력 이벤트를 처리하지 못하는 경우 ANR이 표시됩니다.

예를 들어 앱이 UI 스레드에서 네트워크 액세스와 같은 차단 I/O 작업을 실행하면 ANR이 발생할 수 있습니다. 또 다른 예는 앱이 정교한 메모리 내 구조를 구축하거나 UI 스레드에서 게임의 다음 동작을 계산하는 데 너무 많은 시간을 소비하는 경우입니다.

Android에서는 ActivityManagerWindowManager 시스템 서비스로 앱 응답성을 모니터링합니다. Android는 다음 조건 중 하나를 감지하면 앱의 ANR 대화상자를 표시합니다.

  • 입력 이벤트(예: 키 누름 또는 화면 탭 이벤트)에 5초 내에 응답하지 않음
  • 포그라운드 인텐트의 경우 BroadcastReceiver가 10~20초 내에 실행을 완료하지 못함 자세한 내용은 Broadcast receiver 시간 초과를 참고하세요.

ANR 방지

다음은 ANR을 방지하기 위한 일반적인 팁입니다. 다양한 유형의 ANR 진단 및 디버깅에 관한 자세한 내용은 이 섹션의 다른 페이지를 참고하세요.

  • 항상 기본 스레드를 차단 해제 상태로 유지하고 스레드를 전략적으로 사용합니다.

    • 앱의 기본 스레드에서 차단 작업이나 장기 실행 작업을 실행하지 않습니다. 대신 작업자 스레드를 만들어 대부분의 작업을 거기에서 수행합니다.

    • 기본 스레드와 다른 스레드 간의 잠금 경합을 최소화합니다.

    • 브로드캐스트를 처리하거나 서비스를 실행할 때와 같이 기본 스레드에서 UI 외 작업을 최소화합니다. UI 스레드에서 실행되는 메서드는 해당 스레드에서 가능한 한 작업을 적게 실행해야 합니다. 특히 활동은 가능한 한 적게 실행되어 onCreate()onResume()과 같은 주요 수명 주기 메서드에서 설정해야 합니다. 백그라운드 스레드에서 작업을 예약하고 UI와 다시 통신하는 데 사용할 수 있는 솔루션에 관한 자세한 내용은 백그라운드 작업 개요를 참고하세요.

    • 구성요소 간에 스레드 풀을 공유할 때는 주의해야 합니다. 장시간 차단의 가능성이 있는 작업과 브로드캐스트 수신과 같이 시간에 민감한 작업에는 동일한 스레드를 사용하지 마세요.

  • 앱 시작 속도를 빠르게 유지합니다. 앱의 시작 코드에서 느린 작업이나 차단 작업(예: dagger 초기화 중에 실행되는 메서드)을 최소화합니다.

  • BroadcastReceiver를 사용 중인 경우 Context.registerReceiver를 사용하여 기본 스레드가 아닌 스레드에서 broadcast receiver를 실행하는 것이 좋습니다. 자세한 내용은 BroadcastReceiver의 ANR을 참고하세요.

BroadcastReceiver의 ANR

broadcast receiver는 백그라운드에서 설정 저장이나 Notification 등록과 같은 별개의 소규모 작업을 하기 위한 것이므로 BroadcastReceiver 실행 시간은 제한적입니다. 따라서 UI 스레드에서 호출되는 다른 메서드와 마찬가지로 앱은 broadcast receiver에서 장기 실행 가능성이 있는 작업이나 계산을 피해야 합니다. 장기 실행 작업은 UI 스레드를 통해 실행하는 대신 나중에 실행할 수 있도록 백그라운드에서 실행합니다. 가능한 솔루션에 대한 자세한 내용은 백그라운드 작업 개요를 참고하세요.

BroadcastReceiver 객체의 또 다른 일반적인 문제는 객체가 너무 자주 실행될 때 발생합니다. 백그라운드에서 자주 실행하면 다른 앱에서 사용할 수 있는 메모리가 줄어듭니다. BroadcastReceiver 객체를 효율적으로 사용 설정 및 중지하는 방법에 관한 자세한 내용은 브로드캐스트 개요를 참고하세요.

응답성 강화

일반적으로 사용자가 앱의 속도 저하를 인식하는 기준점은 100~200ms입니다. 다음은 앱이 사용자에게 응답하는 것처럼 보이게 하는 추가적인 팁입니다.

  • 앱이 사용자 입력에 응답하여 백그라운드에서 작업을 실행하는 경우 진행 상황을 보여줍니다(예: UI의 ProgressBar).

  • 특히 게임의 경우 작업자 스레드에서 이동을 계산합니다.

  • 앱에 시간이 많이 소요되는 초기 설정 단계가 있는 경우 스플래시 화면을 표시하거나 최대한 빨리 기본 보기를 렌더링하는 것이 좋습니다. 로드가 진행 중임을 표시하고 비동기식으로 정보를 채웁니다. 어떤 경우든 사용자가 앱이 정지된 것을 인식하지 못하도록 진행 중임을 표시하는 것이 좋습니다.

  • PerfettoCPU 프로파일러와 같은 성능 도구를 사용하여 앱 응답성의 병목 현상을 확인합니다.