이 문서에서는 Android 시스템이 앱의 응답 여부를 판단하는 방법을 설명하고 앱의 응답성을 유지하는 방법을 보여줍니다.
코드를 아무리 잘 작성했더라도 앱이 여전히 느리게 느껴지거나, 멈추거나, 상당한 시간 동안 정지되거나, 입력을 처리하는 데 시간이 너무 오래 걸릴 수 있습니다. 앱이 포그라운드에 있고 응답하지 않으면 그림 1과 같이 사용자에게 애플리케이션 응답 없음(ANR) 대화상자가 표시됩니다. ANR 대화상자를 통해 사용자가 앱을 강제 종료할 수 있습니다. 앱이 포그라운드에 있지 않으면 자동으로 중지됩니다. ANR 대화상자를 최소화하도록 앱의 응답을 설계하는 것이 중요합니다.
ANR 트리거
일반적으로 앱이 기본 스레드(UI 스레드라고도 함)의 사용자 입력에 응답할 수 없어 시스템에서 수신되는 사용자 입력 이벤트를 처리하지 못하는 경우 ANR이 표시됩니다.
예를 들어 앱이 UI 스레드에서 네트워크 액세스와 같은 차단 I/O 작업을 실행하면 ANR이 발생할 수 있습니다. 또 다른 예는 앱이 정교한 메모리 내 구조를 구축하거나 UI 스레드에서 게임의 다음 동작을 계산하는 데 너무 많은 시간을 소비하는 경우입니다.
Android에서는 ActivityManager 및 WindowManager 시스템 서비스로 앱 응답성을 모니터링합니다. Android는 다음 조건 중 하나를 감지하면 앱의 ANR 대화상자를 표시합니다.
다음은 ANR을 방지하기 위한 일반적인 팁입니다. 다양한 유형의 ANR 진단 및 디버깅에 관한 자세한 내용은 이 섹션의 다른 페이지를 참고하세요.
항상 기본 스레드를 차단 해제 상태로 유지하고 스레드를 전략적으로 사용합니다.
앱의 기본 스레드에서 차단 작업이나 장기 실행 작업을 실행하지 않습니다.
대신 작업자 스레드를 만들어 대부분의 작업을 거기에서 수행합니다.
기본 스레드와 다른 스레드 간의 잠금 경합을 최소화합니다.
브로드캐스트를 처리하거나 서비스를 실행할 때와 같이 기본 스레드에서 UI 외 작업을 최소화합니다. UI 스레드에서 실행되는 메서드는 해당 스레드에서 가능한 한 작업을 적게 실행해야 합니다. 특히 활동은 가능한 한 적게 실행되어 onCreate() 및 onResume()과 같은 주요 수명 주기 메서드에서 설정해야 합니다. 백그라운드 스레드에서 작업을 예약하고 UI와 다시 통신하는 데 사용할 수 있는 솔루션에 관한 자세한 내용은 백그라운드 작업 개요를 참고하세요.
구성요소 간에 스레드 풀을 공유할 때는 주의해야 합니다. 장시간 차단의 가능성이 있는 작업과 브로드캐스트 수신과 같이 시간에 민감한 작업에는 동일한 스레드를 사용하지 마세요.
앱 시작 속도를 빠르게 유지합니다. 앱의 시작 코드에서 느린 작업이나 차단 작업(예: dagger 초기화 중에 실행되는 메서드)을 최소화합니다.
broadcast receiver는 백그라운드에서 설정 저장이나 Notification 등록과 같은 별개의 소규모 작업을 하기 위한 것이므로 BroadcastReceiver 실행 시간은 제한적입니다. 따라서 UI 스레드에서 호출되는 다른 메서드와 마찬가지로 앱은 broadcast receiver에서 장기 실행 가능성이 있는 작업이나 계산을 피해야 합니다. 장기 실행 작업은 UI 스레드를 통해 실행하는 대신 나중에 실행할 수 있도록 백그라운드에서 실행합니다. 가능한 솔루션에 대한 자세한 내용은 백그라운드 작업 개요를 참고하세요.
BroadcastReceiver 객체의 또 다른 일반적인 문제는 객체가 너무 자주 실행될 때 발생합니다. 백그라운드에서 자주 실행하면 다른 앱에서 사용할 수 있는 메모리가 줄어듭니다. BroadcastReceiver 객체를 효율적으로 사용 설정 및 중지하는 방법에 관한 자세한 내용은 브로드캐스트 개요를 참고하세요.
응답성 강화
일반적으로 사용자가 앱의 속도 저하를 인식하는 기준점은 100~200ms입니다. 다음은 앱이 사용자에게 응답하는 것처럼 보이게 하는 추가적인 팁입니다.
앱이 사용자 입력에 응답하여 백그라운드에서 작업을 실행하는 경우 진행 상황을 보여줍니다(예: UI의 ProgressBar).
특히 게임의 경우 작업자 스레드에서 이동을 계산합니다.
앱에 시간이 많이 소요되는 초기 설정 단계가 있는 경우 스플래시 화면을 표시하거나 최대한 빨리 기본 보기를 렌더링하는 것이 좋습니다.
로드가 진행 중임을 표시하고 비동기식으로 정보를 채웁니다.
어떤 경우든 사용자가 앱이 정지된 것을 인식하지 못하도록 진행 중임을 표시하는 것이 좋습니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Keep your app responsive\n\n**Figure 1.** An ANR dialog displayed to the user.\n\nThis document describes how the Android system determines whether an app isn't\nresponding and shows how to keep your app responsive.\n\nNo matter how well-written your code is, it's possible for your app to still\nfeel sluggish, hang, freeze for significant periods, or take too long to process\ninput. If your app is in the foreground and is unresponsive, the user gets an\nApplication Not Responding (ANR) dialog, as shown in figure 1. The ANR dialog\nlets the user force quit the app. If the app isn't in the foreground, then it's\nsilently stopped. It's critical to design responsiveness into your app to\nminimize ANR dialogs.\n\nANR triggers\n------------\n\nGenerally, the system displays an ANR if an app can't respond to user input on\nthe main thread---also known as the UI thread---preventing the system from\nprocessing incoming user input events.\n\nFor example, an ANR can occur if an app performs a blocking I/O operation, such\nas network access, on the UI thread. Another example is when an app spends too\nmuch time building an elaborate in-memory structure or computing the next move\nin a game on the UI thread.\n\nIn Android, app responsiveness is monitored by the [`ActivityManager`](/reference/android/app/ActivityManager) and\n[`WindowManager`](/reference/android/view/WindowManager) system services. Android displays the ANR dialog for an app\nwhen it detects one of the following conditions:\n\n- No response to an input event---such as key press or screen tap events---within 5 seconds.\n- A [`BroadcastReceiver`](/reference/android/content/BroadcastReceiver) doesn't finish executing within 10 to 20 seconds, for foreground intents. For more information, see [Broadcast receiver timeout](/topic/performance/anrs/diagnose-and-fix-anrs#broadcast-receiver-anr).\n\nAvoid ANRs\n----------\n\nThe following are general tips to avoid ANRs. For more details about diagnosing\nand debugging different types of ANRs, see the other pages in this section.\n\n- Keep the main thread unblocked at all times, and use threads strategically.\n\n - Don't perform blocking or long-running operations on the app's main thread.\n Instead, create a worker thread and do most of the work there.\n\n - Try to minimize any lock contention between the main thread and other\n threads.\n\n - Minimize any non-UI related work on the main thread, such as when handling\n broadcasts or running services. Any method that runs in the UI thread must\n do as little work as possible on that thread. In particular, activities must\n do as little as possible to set up in key lifecycle methods, such as\n `onCreate()` and `onResume()`. See [Background work overview](/guide/background) for more\n information about available solutions for scheduling work on a background\n thread and communicating back with the UI.\n\n - Be careful when sharing thread pools between components. Don't use the same\n threads for potentially long-blocking operations and time-sensitive tasks\n such as broadcast receiving.\n\n | **Note:** Because such threading usually is accomplished at the class level, you can think of responsiveness as a class problem. Compare this with basic code performance, which is a method-level concern.\n- Keep app startup fast. Minimize slow or blocking operations in the app's\n startup code, such as methods run during dagger initialization.\n\n- If you're using `BroadcastReceiver`, consider running broadcast receivers in a\n non-main thread using [`Context.registerReceiver`](/reference/android/content/Context#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter,%20java.lang.String,%20android.os.Handler,%20int)). For more information,\n see [ANRs in BroadcastReceiver](#anrs-in-broadcast-receiver).\n\n - If you use [`goAsync()`](/reference/android/content/BroadcastReceiver#goAsync()), make sure [`PendingResult.finish`](/reference/kotlin/android/content/BroadcastReceiver.PendingResult?#finish) is called quickly before the ANR timeout.\n\nANRs in BroadcastReceiver\n-------------------------\n\n`BroadcastReceiver` execution time is constrained because broadcast receivers\nare meant to do small, discrete amounts of work in the background, such as\nsaving a setting or registering a [`Notification`](/reference/android/app/Notification). So, as with other\nmethods called in the UI thread, apps must avoid potentially long-running\noperations or calculations in a broadcast receiver. Instead of performing\nlong-running tasks via the UI thread, perform them in the background for later\nexecution. See [Background work overview](/guide/background) for more information about possible\nsolutions.\n\nAnother common issue with `BroadcastReceiver` objects occurs when they execute\ntoo frequently. Frequent background execution can reduce the amount of memory\navailable to other apps. For more information about how to enable and disable\n`BroadcastReceiver` objects efficiently, see [Broadcasts overview](/guide/components/broadcasts).\n| **Tip:** You can use [`StrictMode`](/reference/android/os/StrictMode) to help find potentially lengthy operations such as network or database operations that you might accidentally be doing on your main thread.\n\nReinforce responsiveness\n------------------------\n\nGenerally, 100 to 200ms is the threshold beyond which users perceive slowness in\nan app. Here are additional tips for making your app seem responsive to users:\n\n- If your app is doing work in the background in response to user input, show\n that progress is being made, such as with a [`ProgressBar`](/reference/android/widget/ProgressBar) in your UI.\n\n- For games specifically, do calculations for moves in a worker thread.\n\n- If your app has a time-consuming initial setup phase, consider showing a\n [splash screen](/develop/ui/views/launch/splash-screen) or rendering the main view as quickly as possible.\n Indicate that loading is in progress and fill the information asynchronously.\n In either case, we recommend indicating somehow that progress is being made,\n so that the user doesn't perceive that the app is frozen.\n\n- Use performance tools such as [Perfetto](/topic/performance/tracing) and [CPU Profiler](/studio/profile/cpu-profiler) to\n determine bottlenecks in your app's responsiveness."]]