UI 버벅거림 감지
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
Android는 앱에서 프레임을 생성하고 화면에 표시하여 UI를 렌더링합니다. 앱의 UI 렌더링 속도가 느리면 시스템이 강제로 프레임을 건너뜁니다. 이 경우 사용자는 화면에서 반복적인 깜박임을 감지하게 되는데, 이러한 깜박임을 버벅거림이라고 합니다.
일반적으로 버벅거림이 발생하는 이유는 UI 스레드에서 비동기 호출이 감속되거나 차단되었기 때문입니다(대부분의 앱에서 UI 스레드가 기본 스레드입니다). 시스템 트레이스를 사용하여 문제의 원인을 찾아낼 수 있습니다.
Android 12 이상에서 버벅거림 감지하기
Android 12(API 수준 31) 이상을 사용하는 기기의 경우 캡처된 트레이스가 CPU 프로파일러의 Display 창 아래 Janky frames 트랙에 표시됩니다.
버벅거림을 감지하려면 다음 안내를 따르세요.
Android 스튜디오에서 View > Tool Windows > Profiler를 선택하거나 툴바에서 Profile
을 클릭합니다.
Select Deployment Target 대화상자에 메시지가 표시되면 프로파일링을 위해 앱을 배포할 기기를 선택합니다. USB를 통해 기기를 연결했는데 목록에 표시되지 않으면 USB 디버깅을 사용 설정했는지 확인하세요.
CPU 타임라인의 아무 곳이나 클릭하여 CPU 프로파일러를 엽니다.
CPU 프로파일러의 구성 메뉴에서 System Trace를 선택하고 Record를 클릭합니다. 앱과의 상호작용을 마친 후 Stop을 클릭합니다.
Display 아래에 Janky frames 트랙이 표시됩니다. 기본적으로 프로파일러는 버벅거리는 프레임을 조사 대상 후보로만 표시합니다. 버벅거리는 각 프레임 내에서 빨간색 부분은 프레임이 렌더링 기한을 초과하는 시간을 강조표시한 것입니다.

버벅거리는 프레임을 찾으면 클릭합니다. M을 누르면 선택한 프레임에 초점을 맞추도록 확대/축소를 조정할 수도 있습니다. 관련 이벤트는 기본 스레드인 RenderThread와 GPU completion과 같은 스레드에 강조표시됩니다.

All Frames와 Lifecycle 체크박스를 각각 전환하여 모든 프레임 또는 렌더링 시간의 세부정보를 확인할 수도 있습니다.
Android 11에서 버벅거림 감지
Android 11(API 수준 30)을 사용하는 기기의 경우 캡처된 트레이스는 CPU 프로파일러의 Frame Lifecycle 섹션에 표시됩니다.

Frame Lifecycle 섹션에는 레이어 이름과 4개의 트랙이 포함됩니다. 각 트랙은 프레임 렌더링 파이프라인의 한 단계를 나타냅니다. Frame Lifecycle의 요소는 다음과 같습니다.
- Frame Lifecycle(레이어 이름): 섹션 제목에 레이어 이름이 괄호 안에 표시됩니다. 레이어는 단일 구성 단위입니다.
- Application: 이 트랙은 앱에 의해 버퍼가 큐에서 제거된 시점으로부터 다시 큐에 추가된 시점까지의 시간을 보여줍니다. 일반적으로
RenderThread
의 트레이스 이벤트에 대응됩니다.
- Wait for GPU: 이 트랙은 GPU가 버퍼를 소유하고 있었던 기간을 보여줍니다. 버퍼가 GPU로 전송된 시점으로부터 GPU가 버퍼의 처리를 마치는 시점까지의 기간입니다. 이것이 GPU가 해당 시간 동안 이 버퍼만을 처리했음을 나타내는 것은 아닙니다. 주어진 시간 동안 GPU가 어떤 작업을 처리했는지 자세히 알아보려면 Android GPU 검사기를 사용하세요.
- Composition: 이 트랙은 SurfaceFlinger가 버퍼에 연결되어 구성을 위해 전송한 시점으로부터 버퍼가 디스플레이에 전송된 시점까지의 기간을 보여줍니다.
- Frames on display: 이 트랙은 프레임이 화면에 얼마나 오래 있었는지를 보여줍니다.
Frame Lifecycle 섹션은 프레임 버퍼가 렌더링 파이프라인의 여러 단계를 어떤 식으로 이동하는지를 그림으로 보여줍니다. 특정 프레임을 쉽게 추적할 수 있도록 프레임 번호별로 다른 색상이 표시됩니다.
Android 스튜디오의 All Frames 탭에서는 트레이스에 있는 모든 프레임을 표 형식으로도 볼 수 있습니다.

Frame #, Application, Wait for GPU 및 Composition 열은 위의 Frame Lifecycle 섹션에 있는 트랙과 같은 데이터를 나타냅니다. Frame Duration 열은 Application의 시작 시점부터 Frames on Display의 시작 시점까지의 기간을 나타냅니다. 이는 프레임을 처음부터 끝까지 렌더링하는 데 소요되는 시간입니다.
프레임 표를 원하는 열로 정렬하여 가장 짧거나 긴 프레임을 빠르게 찾을 수 있습니다. 수백 개의 프레임을 편리하게 볼 수 있도록 표에서 페이지로 나누기 설정도 지원합니다.
Android 11에서 버벅거림을 감지하고 조사하려면 다음 단계를 따르세요.
가장 오래 걸리는 프레임이 맨 위에 표시되도록 All Frames 표에서 Application 열을 기준으로 내림차순 정렬합니다.

가장 오래 실행되는 프레임을 찾아서 표의 행을 선택합니다. 이렇게 하면 왼쪽의 타임라인 뷰에서
선택한 프레임이 확대됩니다

Frame Lifecycle 섹션과 Threads 섹션에서 관련 스레드를 찾습니다.

Android 10 이하에서 버벅거림 감지하기
Android 10 (API 수준 29) 이하를 사용하는 기기의 경우 관련 OS 그래픽 파이프라인 정보가 Display라는 CPU 프로파일러 시스템 트레이스의 단일 섹션에 표시됩니다.

- Frames: 이 섹션에는 앱의 UI 스레드와
RenderThread
트레이스 이벤트가 표시됩니다. 16밀리초보다 긴 이벤트는 60fps(초당 프레임 수)의 렌더링 기한을 초과하기 때문에 버벅거림을 유발할 수 있습니다. 이러한 프레임은 빨간색으로 강조표시됩니다.
- SurfaceFlinger: 이 섹션에는 SurfaceFlinger가 프레임 버퍼를 처리하는 시점이 표시됩니다. SurfaceFlinger는 디스플레이에 버퍼를 보내는 일을 담당하는 시스템 프로세스입니다.
- VSYNC: 이 섹션에는 디스플레이 파이프라인을 동기화하는 신호인 VSYNC가 표시됩니다. 트랙에는 VSYNC-app 신호가 표시되는데, 이는 앱이 너무 늦게 시작되는 경우 나타냅니다. 일반적으로 앱이 너무 늦게 시작되는 이유는 UI 스레드가 사용 중이기 때문입니다. 이로 인해 애니메이션이 재생되는 동안 화면에 눈에 띄는 버벅거림이 발생하며, 애니메이션 또는 스크롤이 완료되기 전까지 추가적인 입력 지연 시간이 더해집니다.
화면 재생 빈도가 높은 디스플레이의 경우 재생 빈도가 초당 60초보다 높아지거나 빈도가 변할 수 있기 때문에 특히 유의하여 살펴보아야 합니다.
- BufferQueue: 이 섹션에는 큐에 추가되어 SurfaceFlinger가 소비하기를 기다리고 있는 프레임 버퍼의 개수가 표시됩니다. Android 9 (API 수준 28) 이상을 실행하는 기기에 배포된 앱의 경우 이 트랙은 앱의 노출 영역 BufferQueue(
0
, 1
, 2
)의 버퍼 수를 보여줍니다. BufferQueue는 이미지 버퍼가 Android 그래픽 구성요소 간에 이동할 때 이미지 버퍼의 상태를 이해하는 데 도움이 될 수 있습니다. 예를 들어, 값이 2
인 경우 앱이 현재 삼중 버퍼링되어 있음을 나타내며, 이로 입력 지연 시간이 추가로 발생하게 됩니다.
Display 섹션에서는 버벅거림이 발생할 가능성을 나타내는 유용한 신호를 볼 수 있습니다(예: UI 스레드 또는 RenderThread
가 16밀리초보다 오래 걸리는 경우). 버벅거림을 유발한 원인의 정확한 세부정보를 조사하려면 UI 렌더링과 관련된 스레드를 보여주는 Threads 섹션을 살펴보세요.

위 그림에서 Threads 섹션은 UI 스레드(java.com.google.samples.apps.iosched
), RenderThread
, GPU completion
스레드를 보여줍니다. 이들은 UI 렌더링과 관련 있는 스레드로, 버벅거림의 원인이 될 수 있습니다.
Android 10 이하에서 버벅거림을 감지하려면 다음 단계를 따르세요.
Display의 Frames 트랙을 살펴봅니다. 조사가 필요한 프레임이 빨간색으로 표시됩니다.

버벅거림이 발생할 가능성이 있는 프레임을 찾았으면 W
를 누르거나 Control(macOS에서는 Command)을 누른 상태로 마우스 휠을 스크롤하여 확대합니다. UI 스레드와 RenderThread
에서 트레이스 이벤트가 보이기 시작할 때까지 계속 확대합니다.

위 그림에서 Choreographer#doFrame
은 UI 스레드가 Choreographer
를 호출하여 애니메이션, 뷰 레이아웃, 이미지 그리기 및 관련 프로세스를 조정하는 시점을 보여줍니다. DrawFrames
는 RenderThread
가 실제 그리기 명령을 구성하여 GPU에 전달하는 시점을 보여줍니다.
특히 긴 트레이스 이벤트가 있다면 한층 더 확대하여 느린 렌더링의 원인이 무엇인지 확인할 수 있습니다. 위의 그림은 UI 스레드의 inflate
를 보여줍니다. 즉, 앱이 레이아웃을 확장하는 데 시간을 소비하고 있음을 의미합니다.
inflate
이벤트 중 하나를 확대해 보면 아래와 같이 각 UI 구성요소의 소요 시간을 정확히 알아볼 수 있습니다.

자세히 알아보기
버벅거림을 줄이는 방법을 자세히 알아보려면 버벅거림의 일반적인 원인을 참고하세요.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 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,["# UI jank detection\n\nAndroid renders UI by generating a frame from your app and displaying it on\nthe screen. If your app suffers from slow UI rendering, then the system is\nforced to skip frames. When this happens, the user perceives a recurring flicker\non their screen, which is referred to as *jank*.\n\nWhen jank occurs, it's usually because of some deceleration or blocking async\ncall on the UI thread (in most apps, it's the main thread). You can use system\ntraces to identify where the problem is.\n\nDetect jank on Android 12 and higher\n------------------------------------\n\nFor devices using Android 12 (API level 31) or higher, a captured trace is shown\nin the **Janky frames** track under the **Display** pane in the CPU Profiler.\n\nTo detect jank,\n\n1. In Android Studio, select **View \\\u003e Tool Windows \\\u003e Profiler** or click **Profile**\n in the toolbar.\n\n If prompted by the **Select Deployment Target** dialog, choose the device to\n which to deploy your app for profiling. If you've connected a device over USB\n but don't see it listed, ensure that you have\n [enabled USB debugging](/studio/debug/dev-options#enable).\n2. Click anywhere in the **CPU** timeline to open the CPU Profiler.\n\n3. Select **System Trace** from the configurations menu in the CPU Profiler and\n click **Record** . After you finish interacting with your app, click **Stop**.\n\n4. You should see the **Janky frames** track under **Display** . By default, the\n Profiler only shows janky frames as candidates for investigation. Within each\n janky frame, the red portion highlights the duration the frame takes past its\n rendering deadline.\n\n5. Once you find a janky frame, click on it; optionally, you can press **M** to\n adjust the zoom to focus on the selected frame. The relevant events are\n highlighted in these threads: the main thread, **RenderThread** and\n **GPU completion** .\n\n6. You can optionally see all frames or a breakdown of the rendering time by\n toggling the checkboxes **All Frames** and **Lifecycle** , respectively.\n\nDetect jank on Android 11\n-------------------------\n\nFor devices using Android 11 (API level 30), a captured trace is shown in the\n**Frame Lifecycle** section in the CPU Profiler.\n\nThe **Frame Lifecycle** section contains the layer name and four tracks. Each\ntrack represents one stage in the frame rendering pipeline. The **Frame\nLifecycle** elements are as follows:\n\n1. **Frame Lifecycle (Layer name)** : The section title contains the layer name in parentheses. A *layer* is a single unit of composition.\n2. **Application** : This track shows the time from when the buffer was dequeued by the app to when it was enqueued back. This usually corresponds to the trace events in `RenderThread`.\n3. **Wait for GPU** : This track shows how long the buffer was owned by the GPU. This is the time from when the buffer is sent to the GPU to when the GPU finishes its work on the buffer. **This does not indicate that the GPU was working only on\n this buffer during this time.** For detailed info on what the GPU works on during a given time, you may want to use [Android GPU Inspector](/agi).\n4. **Composition**: This track shows the time starting from when SurfaceFlinger latches on to the buffer and sends it for composition, to when the buffer is sent to the display.\n5. **Frames on display**: This track shows how long the frame was on the screen.\n\nThe **Frame Lifecycle** section illustrates how a frame buffer moves between\ndifferent stages of the rendering pipeline. The frames are color coded by frame\nnumber so that it's easier to track a particular frame.\n\nAndroid Studio also shows all frames in the trace in a table format in the **All\nFrames** tab.\n\nThe **Frame #** , **Application** , **Wait for GPU** , and\n**Composition** columns represent the same data as the tracks in the **Frame\nLifecycle** section as above. The column **Frame Duration** represents the time\nfrom the start of **Application** to the start of **Frames on Display**. This is\nessentially how long it takes to render a frame end-to-end.\n\nYou can sort the frames table by any column to quickly find the shortest or\nlongest frame. The table also supports pagination controls that help you navigate\nthrough hundreds of frames.\n\nTo detect and investigate jank on Android 11, follow these steps:\n\n1. Sort the **All Frames** table by the **Application** column in descending\n order, so that the frames that take the longest appear first.\n\n2. Find the longest running frames and select the table row. This zooms in on\n the selected frame in the timeline view to the left.\n\n3. Look for relevant threads in the **Frame Lifecycle** and **Threads** sections.\n\nDetect jank on Android 10 and lower\n-----------------------------------\n\nFor devices using Android 10 (API level 29) and lower, relevant OS graphics\npipeline information is displayed in a single section on the CPU Profiler system\ntrace called **Display**.\n\n- **Frames** : This section shows the UI thread and `RenderThread` trace events in your app. Events that are longer than 16ms are colored red to highlight potential janky frames because they exceed the deadline to render at 60 frames per second (fps).\n- **SurfaceFlinger**: This section shows when the SurfaceFlinger processes the frame buffers. SurfaceFlinger is a system process that is responsible for sending buffers to display.\n- **VSYNC**: This section displays the VSYNC, a signal that synchronizes the display pipeline. The track displays the VSYNC-app signal, which shows when your app is starting too late. Typically, this occurs because the UI thread is busy. It causes a visible flicker to appear on your screen during an animation and adds extra input latency until the animation or scroll completes. This is especially important to view for high-refresh-rate displays, as they may occur more frequently than 60 times per second or at a variable rate.\n- **BufferQueue** : This section shows how many frame buffers are queued up and are waiting for SurfaceFlinger to consume. For apps deployed to devices running Android 9 (API level 28) or higher, this track shows the buffer count of the app's surface [BufferQueue](https://source.android.com/devices/graphics#bufferqueue) (`0`, `1`, or `2`). BufferQueue can help you understand the state of image buffers as they move between the Android graphics components. For example, a value of `2` means that the app is currently triple-buffered, which results in extra input latency.\n\nThe **Display** section provides useful signals to detect potential jank---for\nexample, when the UI thread or `RenderThread` takes longer than 16 ms. To investigate\nexact details of what caused the jank, you can probe the **Threads**\nsection, which shows the threads relevant to UI rendering.\n\nIn the figure above, the **Threads** section shows the UI thread\n(`java.com.google.samples.apps.iosched`), `RenderThread`, and the `GPU completion`\nthread. These are the threads relevant to UI rendering and may contribute to\njank.\n\nTo detect jank on Android 10 or lower, follow these steps:\n\n1. Look at the **Frames** track in **Display**. The red frames are candidates\n for investigation.\n\n2. Once you find a potentially janky frame, zoom in by pressing `W` or\n scrolling the mouse wheel while holding \u003ckbd\u003eControl\u003c/kbd\u003e\n (\u003ckbd\u003eCommand\u003c/kbd\u003e on macOS). Continue zooming in until you start to see the\n trace events in the UI thread and `RenderThread`.\n\n In the figure above, `Choreographer#doFrame` shows when the UI thread calls\n [`Choreographer`](/reference/android/view/Choreographer) to coordinate\n animation, view layout, image drawing, and related processes. `DrawFrames`\n shows when `RenderThread` forms and issues actual drawing commands to the GPU.\n3. If you see a particularly long trace event, you can zoom in further and find out\n what may have contributed to the slow rendering. The figure above shows `inflate`\n in the UI thread, which means the app is spending time on inflating the layout.\n When you zoom into one of the `inflate` events, you can find out exactly how long\n each UI component is taking, as shown below.\n\nLearn more\n----------\n\nTo learn more about how to reduce jank, see\n[Common sources of jank](/topic/performance/vitals/render#common-jank)."]]