Firebase Performance Monitoring으로 로드 시간 및 화면 렌더링 측정

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

1. 소개

마지막 업데이트: 2021-03-11

View의 성능을 측정해야 하는 이유는 무엇입니까?

보기는 사용자 경험에 직접적인 영향을 미치는 Android 애플리케이션의 핵심 부분입니다. 예를 들어 Activity 또는 Fragment에는 사용자가 상호 작용하는 View 구성 요소를 보유하는 UI가 포함되어 있습니다. 사용자는 화면에 완전히 그려질 때까지 UI의 전체 내용을 볼 수 없습니다. 느리고 정지된 화면은 앱과의 사용자 상호 작용을 직접적으로 손상시키고 나쁜 사용자 경험을 만듭니다.

Firebase Performance Monitoring은 즉시 이러한 성능 측정항목을 제공하지 않습니까?

Firebase 성능 모니터링은 앱 시작 시간(즉, 첫 번째 활동에 대한 로드 시간만) 및 화면 렌더링 성능(즉, 활동에 대해서는 느리고 정지된 프레임과 같은 일부 성능 데이터를 즉시 캡처하지만 파편). 그러나 산업 앱에는 일반적으로 활동이 많지 않고 오히려 하나의 활동과 여러 조각이 있습니다. 또한 많은 앱은 일반적으로 더 복잡한 사용 사례를 위해 고유한 사용자 지정 보기를 구현합니다. 따라서 앱에서 사용자 지정 코드 추적 을 계측하여 활동과 조각 모두의 로드 시간과 화면 렌더링 성능을 측정하는 방법을 이해하는 것이 종종 유용합니다. 이 Codelab을 쉽게 확장하여 Custom View 구성 요소의 성능을 측정할 수 있습니다.

배울 내용

  • Android 앱에 Firebase Performance Monitoring을 추가하는 방법
  • 액티비티 또는 프래그먼트 로드 이해
  • 활동 또는 조각의 로드 시간을 측정하기 위해 사용자 지정 코드 추적을 계측하는 방법
  • 화면 렌더링 및 느린/고정된 프레임의 이해
  • 느린/고정된 화면을 기록하기 위해 메트릭으로 사용자 지정 코드 추적을 계측하는 방법
  • Firebase 콘솔에서 수집된 측정항목을 보는 방법

필요한 것

  • 안드로이드 스튜디오 4.0 이상
  • Android 기기/에뮬레이터
  • 자바 버전 8 이상

2. 설정하기

코드 받기

다음 명령을 실행하여 이 코드랩의 샘플 코드를 복제합니다. 그러면 codelab-measure-android-view-performance 라는 폴더가 생성됩니다.

$ git clone https://github.com/FirebaseExtended/codelab-measure-android-view-performance.git
$ cd codelab-measure-android-view-performance

컴퓨터에 git이 없는 경우 GitHub에서 직접 코드를 다운로드할 수도 있습니다.

measure-view-performance-start 프로젝트를 Android Studio로 가져옵니다. 일부 컴파일 오류 또는 누락된 google-services.json 파일에 대한 경고가 표시될 수 있습니다. 이 단계의 다음 섹션에서 이를 수정할 것입니다.

이 코드랩에서는 Firebase Assistant 플러그인을 사용하여 Android 앱을 Firebase 프로젝트에 등록하고 필요한 Firebase 구성 파일, 플러그인 및 종속성을 Android 프로젝트에 추가합니다. 이 모든 것이 Android Studio 내에서 이루어집니다 .

Firebase에 앱 연결

  1. Android Studio / 도움말 > 업데이트 확인으로 이동하여 최신 버전의 Android Studio 및 Firebase Assistant를 사용하고 있는지 확인하세요.
  2. 도구 > Firebase 를 선택하여 어시스턴트 창을 엽니다.

e791bed0999db1e0.png

  1. 성능 모니터링 을 선택하여 앱에 추가한 다음 성능 모니터링 시작하기 를 클릭합니다.
  2. Firebase에 연결을 클릭하여 Android 프로젝트를 Firebase에 연결합니다 (이렇게 하면 브라우저에서 Firebase 콘솔이 열립니다) .
  3. Firebase 콘솔에서 프로젝트 추가 를 클릭한 다음 Firebase 프로젝트 이름을 입력합니다 (이미 Firebase 프로젝트가 있는 경우 기존 프로젝트를 대신 선택할 수 있음) . 계속 을 클릭하고 약관에 동의하여 Firebase 프로젝트와 새 Firebase 앱을 만듭니다.
  4. 다음으로 새 Firebase 앱을 Android 스튜디오 프로젝트에 연결 하는 대화상자가 표시되어야 합니다.

42c498d28ead2b77.png

  1. Android Studio로 돌아가서 Assistant 창에 앱이 Firebase에 연결되었다는 확인 메시지가 표시되어야 합니다.

dda8bdd9488167a0.png

앱에 성능 모니터링 추가

Android Studio의 Assistant 창에서 Add Performance Monitoring to your app 을 클릭합니다.

필요한 모든 종속성이 추가되었는지 확인하기 위해 Android Studio에서 앱을 동기화해야 하는 변경 사항 수락 대화 상자가 표시되어야 합니다.

9b58145acc4be030.png

마지막으로 Android Studio의 Assistant 창에 모든 종속성이 올바르게 설정되었다는 성공 메시지가 표시되어야 합니다.

aa0d46fc944e0c0b.png

추가 단계로 "(선택 사항) 디버그 로깅 활성화" 단계의 지침에 따라 디버그 로깅 을 활성화합니다. 공개 문서 에서도 동일한 지침을 사용할 수 있습니다.

3. 앱 실행

앱을 Performance Monitoring SDK와 성공적으로 통합했다면 이제 프로젝트가 컴파일되어야 합니다. Android Studio에서 Run > Run 'app' 을 클릭하여 연결된 Android 기기/에뮬레이터에서 앱을 빌드하고 실행합니다.

앱에는 다음과 같이 해당 활동 및 조각으로 이동하는 두 개의 버튼이 있습니다.

410d8686b4f45c33.png

이 코드랩의 다음 단계에서는 활동 또는 프래그먼트의 로드 시간 및 화면 렌더링 성능을 측정하는 방법을 배웁니다.

4. 액티비티 또는 프래그먼트 로딩 이해하기

이 단계에서는 Activity 또는 Fragment를 로드하는 동안 시스템이 수행하는 작업을 배웁니다.

활동 로드 이해

Activity의 경우 로드 시간은 Activity 객체가 생성된 시점부터 화면에 First Frame 이 완전히 그려질 때까지의 시간으로 정의됩니다( 이때 사용자는 Activity의 전체 UI를 처음으로 볼 수 있습니다). 시간 ). 앱이 완전히 그려졌는지 측정하기 위해 reportFullyDrawn() 메서드를 사용하여 애플리케이션 실행과 모든 리소스 및 보기 계층 구조의 완전한 표시 사이의 경과 시간을 측정할 수 있습니다.

높은 수준에서 앱이 startActivity(Intent) 를 호출하면 시스템이 자동으로 다음 프로세스를 수행합니다. 각 프로세스는 완료하는 데 시간이 걸리므로 활동 생성과 사용자가 화면에서 활동에 대한 UI를 볼 때까지의 시간이 추가됩니다.

c20d14b151549937.png

프래그먼트 로딩 이해하기

Activity와 유사하게 Fragment의 로드 시간은 Fragment가 호스트 Activity에 연결될 때부터 Fragment View의 첫 번째 프레임 이 화면에 완전히 그려질 때까지의 시간으로 정의됩니다.

5. 활동의 로드 시간 측정

첫 번째 프레임의 지연은 나쁜 사용자 경험으로 이어질 수 있으므로 사용자가 경험하는 초기 로드 지연을 이해하는 것이 중요합니다. 이 로드 시간을 측정하기 위해 사용자 지정 코드 추적 을 계측할 수 있습니다.

  1. Activity 개체가 생성되는 즉시 Activity 클래스에서 사용자 지정 코드 추적( 이름 TestActivity-LoadTime )을 시작합니다.

테스트 활동.자바

public class TestActivity extends AppCompatActivity {   
    // TODO (1): Start trace recording as soon as the Activity object is created.
    private final Trace viewLoadTrace = FirebasePerformance.startTrace("TestActivity-LoadTime");

    // ...

}
  1. onCreate() 콜백을 재정의하고 setContentView() 메서드로 추가된 보기를 가져옵니다.
@Override     
public void onCreate(Bundle savedInstanceState) {    
    super.onCreate(savedInstanceState);          

    // Current Activity's main View (as defined in the layout xml file) is inflated after this            
    setContentView(R.layout.activity_test);          

    // ...

    // TODO (2): Get the View added by Activity's setContentView() method.         
    View mainView = findViewById(android.R.id.content);     

    // ...
}
  1. onDrawingStart()onDrawingFinish() )의 두 가지 콜백이 있는 FistDrawListener 구현을 포함했습니다( FirstDrawListener 및 성능에 영향을 줄 수 있는 항목에 대한 자세한 내용은 아래 다음 섹션 참조 ). Activity의 onCreate() 콜백 끝에 FirstDrawListener 를 등록합니다. onDrawingFinish() 콜백에서 viewLoadTrace 를 중지해야 합니다.

테스트 활동.자바

    // TODO (3): Register the callback to listen for first frame rendering (see
    //  "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when View drawing is
    //  finished.
    FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {              
        @Override             
        public void onDrawingStart() {       
          // In practice you can also record this event separately
        }

        @Override             
        public void onDrawingFinish() {
            // This is when the Activity UI is completely drawn on the screen
            viewLoadTrace.stop();             
        }         
    });
  1. 앱을 다시 실행합니다. 그런 다음 " Logging trace metric "으로 logcat을 필터링합니다. LOAD ACTIVITY 버튼을 누르고 아래와 같은 로그를 찾습니다.
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 축하합니다! 활동의 로드 시간을 성공적으로 측정하고 해당 데이터를 Firebase Performance Monitoring에 보고했습니다. 이 코드랩의 뒷부분에서 Firebase 콘솔에서 기록된 측정항목을 볼 것입니다.

FirstDrawListener의 목적

바로 위 섹션에서 FirstDrawListener 를 등록했습니다. FirstDrawListener 의 목적은 첫 번째 프레임이 그리기 시작하고 끝낸 시간을 측정하는 것입니다.

ViewTreeObserver.OnDrawListener 를 구현하고 View 트리가 그려지려고 할 때 호출되는 onDraw() 콜백을 재정의합니다. 그런 다음 결과를 래핑하여 두 개의 유틸리티 콜백 onDrawingStart()onDrawingFinish() 를 제공합니다.

FirstDrawListener 의 전체 코드는 이 코드랩의 소스 코드 에서 찾을 수 있습니다.

6. 프래그먼트의 로드 시간 측정

Fragment의 로드 시간을 측정하는 것은 Activity에 대해 측정하는 방법과 유사하지만 약간의 차이가 있습니다. 다시 사용자 정의 코드 추적 을 계측합니다.

  1. onAttach() 콜백을 재정의하고 fragmentLoadTrace 기록을 시작합니다. 이 추적의 이름 Test-Fragment-LoadTime 지정하겠습니다.

이전 단계에서 설명한 것처럼 Fragment 개체는 언제든지 생성할 수 있지만 호스트 활동에 연결된 경우에만 활성화됩니다.

테스트프래그먼트.자바

public class TestFragment extends Fragment {

   // TODO (1): Declare the Trace variable.
   private Trace fragmentLoadTrace;

   @Override
   public void onAttach(@NonNull Context context) {
       super.onAttach(context);

       // TODO (2): Start trace recording as soon as the Fragment is attached to its host Activity.
       fragmentLoadTrace = FirebasePerformance.startTrace("TestFragment-LoadTime");
   }
  1. onViewCreated() 콜백에 FirstDrawListener 를 등록합니다. 그런 다음 Activity 예제와 유사하게 onDrawingFinish() 에서 추적을 중지합니다.

테스트프래그먼트.자바

@Override
public void onViewCreated(@NonNull View mainView, Bundle savedInstanceState) {
   super.onViewCreated(mainView, savedInstanceState);

   // ...

   // TODO (3): Register the callback to listen for first frame rendering (see
   //  "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when view drawing is
   //  finished.
   FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {

       @Override
       public void onDrawingStart() {
           // In practice you can also record this event separately
       }

       @Override
       public void onDrawingFinish() {
           // This is when the Fragment UI is completely drawn on the screen
           fragmentLoadTrace.stop();
       }
   });
  1. 앱을 다시 실행합니다. 그런 다음 " Logging trace metric "으로 logcat을 필터링합니다. LOAD FRAGMENT 버튼을 누르고 아래와 같은 로그를 찾습니다.
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 축하합니다! 프래그먼트의 로드 시간을 성공적으로 측정하고 해당 데이터를 Firebase Performance Monitoring에 보고했습니다. 이 코드랩의 뒷부분에서 Firebase 콘솔에서 기록된 측정항목을 볼 것입니다.

7. 화면 렌더링의 이해와 느린/고정된 프레임이란 무엇입니까?

UI 렌더링은 앱에서 프레임을 생성하여 화면에 표시하는 작업입니다. 사용자와 앱 간의 원활한 상호 작용을 위해 앱은 초당 60프레임을 달성하기 위해 16ms 미만의 프레임을 렌더링해야 합니다( 60fps가 필요한 이유는? ). 앱에서 느린 UI 렌더링이 발생하는 경우 시스템은 강제로 프레임을 건너뛰고 사용자는 앱에서 끊김 현상을 감지하게 됩니다. 우리는 이것을 버벅거림 이라고 부릅니다.

마찬가지로 고정된 프레임 은 렌더링하는 데 700ms보다 오래 걸리는 UI 프레임입니다. 이 지연은 앱이 정지된 것처럼 보이고 프레임이 렌더링되는 동안 거의 1초 동안 사용자 입력에 응답하지 않기 때문에 문제입니다.

8. Fragment의 Slow/Frozen 프레임 측정

Firebase 성능 모니터링은 활동에 대해 느리거나 정지된 프레임을 자동으로 캡처합니다( 단, 하드웨어 가속인 경우에만 해당 ). 그러나 이 기능은 현재 프래그먼트에 사용할 수 없습니다. Fragment의 느린/고정된 프레임은 Fragment의 수명 주기에서 onFragmentAttached()onFragmentDetached() 콜백 사이의 전체 활동에 대한 느린/고정된 프레임으로 정의됩니다.

AppStateMonitor 클래스( Activity 에 대한 화면 추적 기록을 담당하는 Performance Monitoring SDK의 일부) 에서 동기를 부여하여 ScreenTrace 클래스( 이 코드랩 소스 코드 리포지토리의 일부 )를 구현했습니다. ScreenTrace 클래스를 Activity의 FragmentManager 수명 주기 콜백에 연결하여 느리거나 정지된 프레임을 캡처할 수 있습니다. 이 클래스는 두 가지 공개 API를 제공합니다.

  • recordScreenTrace() : 화면 추적 기록을 시작합니다.
  • sendScreenTrace() : 화면 추적 기록을 중지하고 사용자 지정 메트릭 을 첨부하여 총, 저속 및 고정 프레임 수를 기록합니다.

이러한 사용자 지정 측정항목을 연결하면 프래그먼트에 대한 화면 추적을 활동에 대한 화면 추적과 동일한 방식으로 처리할 수 있으며 Firebase 콘솔의 성능 대시보드에 다른 화면 렌더링 추적 과 함께 표시할 수 있습니다.

조각에 대한 화면 추적을 기록하는 방법은 다음과 같습니다.

  1. Fragment를 호스팅하는 Activity에서 ScreenTrace 클래스를 초기화합니다.

메인 액티비티.자바

// Declare the Fragment tag
private static final String FRAGMENT_TAG = TestFragment.class.getSimpleName();

// TODO (1): Declare the ScreenTrace variable.
private ScreenTrace screenTrace;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // TODO (2): Initialize the ScreenTrace variable.
    screenTrace = new ScreenTrace(this, FRAGMENT_TAG);

    // ...
}
  1. Fragment를 로드할 때 FragmentLifecycleCallbacks 에 등록하고 onFragmentAttached()onFragmentDetached() 콜백을 재정의합니다. 우리는 당신을 위해 이것을했습니다. onFragmentAttached() 콜백에서 화면 추적 기록을 시작하고 onFragmentAttached() onFragmentDetached() 에서 기록을 중지해야 합니다.

메인 액티비티.자바

private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks =
       new FragmentManager.FragmentLifecycleCallbacks() {

           @Override
           public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) {
               super.onFragmentAttached(fm, f, context);

               // TODO (3): Start recording the screen traces as soon as the Fragment is
               //  attached to its host Activity.
               if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
                   screenTrace.recordScreenTrace();
               }
           }

           @Override
           public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {
               super.onFragmentDetached(fm, f);

               // TODO (4): Stop recording the screen traces as soon as the Fragment is
               //  detached from its host Activity.
               if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
                   screenTrace.sendScreenTrace();
               }

               // Unregister Fragment lifecycle callbacks after the Fragment is detached
               fm.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks);
           }
       };
  1. 앱을 다시 실행합니다. 그런 다음 LOAD FRAGMENT 버튼을 누릅니다. 몇 초 동안 기다린 다음 하단 탐색 모음에서 back button 을 클릭합니다.

" Logging trace metric "으로 logcat을 필터링하고 아래와 같은 로그를 찾습니다.

I/FirebasePerformance: Logging trace metric: _st_MainActivity-TestFragment (duration: XXXms)

" FireperfViews "로 logcat을 필터링한 다음 아래와 같은 로그를 찾습니다.

D/FireperfViews: sendScreenTrace MainActivity-TestFragment, name: _st_MainActivity-TestFragment, total_frames: XX, slow_frames: XX, frozen_frames: XX

🎉 축하합니다! Fragment의 느린/고정된 프레임을 성공적으로 측정하고 해당 데이터를 Firebase Performance Monitoring에 보고했습니다. 이 코드랩의 뒷부분에서 Firebase 콘솔에서 기록된 측정항목을 볼 것입니다.

9. Firebase 콘솔에서 측정항목 확인

  1. logcat에서 Firebase 콘솔 URL을 클릭하여 추적에 대한 세부정보 페이지를 방문합니다. ceb9d5ba51bb6e89.jpeg

또는 Firebase 콘솔 에서 앱이 있는 프로젝트를 선택합니다. 왼쪽 패널에서 릴리스 및 모니터 섹션을 찾은 다음 성능 을 클릭합니다.

  • 기본 대시보드 탭에서 추적 테이블까지 아래로 스크롤한 다음 맞춤 추적 탭을 클릭합니다. 이 표에는 앞서 추가한 사용자 지정 코드 추적과 _app_start 추적 과 같은 일부 기본 추적이 표시됩니다.
  • 두 개의 사용자 지정 코드 추적인 TestActivity-LoadTimeTestFragment-LoadTime LoadTime 을 찾습니다. 수집된 데이터에 대한 자세한 내용을 보려면 둘 중 하나의 기간 을 클릭하십시오.

a0d8455c5269a590.png

  1. 사용자 지정 코드 추적에 대한 세부 정보 페이지는 추적 기간(즉, 측정된 로드 시간)에 대한 정보를 보여줍니다.

5e92a307b7410d8b.png

  1. 사용자 정의 화면 추적에 대한 성능 데이터를 볼 수도 있습니다.
  • 기본 대시보드 탭으로 돌아가 추적 테이블까지 아래로 스크롤한 다음 화면 렌더링 탭을 클릭합니다. 이 표에서는 앞에서 추가한 사용자 지정 화면 추적과 MainActivity 추적과 같은 기본 화면 추적 을 볼 수 있습니다.
  • 사용자 정의 화면 추적 MainActivity-TestFragment 십시오. 추적 이름을 클릭하면 느린 렌더링 및 정지된 프레임의 집계 데이터를 볼 수 있습니다.

ee7890c7e2c28740.png

10. 축하합니다

축하합니다! Firebase 성능 모니터링을 사용하여 활동 및 프래그먼트의 로드 시간과 화면 렌더링 성능을 성공적으로 측정했습니다.

당신이 성취한 것

무엇 향후 계획

Firebase 성능은 맞춤 추적 외에 앱의 더 많은 성능 측정 방법을 제공합니다. 앱 시작 시간, 포그라운드 앱 및 백그라운드 앱 성능 데이터를 자동으로 측정합니다. 이제 Firebase 콘솔 에서 이러한 측정항목을 확인할 차례입니다.

또한 Firebase Performance는 자동 HTTP/S 네트워크 요청 모니터링 을 제공합니다. 이를 통해 코드를 한 줄도 작성하지 않고도 네트워크 요청을 쉽게 계측할 수 있습니다. 앱에서 일부 네트워크 요청을 보내고 Firebase 콘솔 에서 측정항목을 찾을 수 있습니까?

보너스

이제 사용자 지정 코드 추적을 사용하여 Activity/Fragment의 로드 시간과 화면 렌더링 성능을 측정하는 방법을 알았 으므로 오픈 소스 코드 기반 을 탐색하여 모든 Activity/Fragment에 대해 즉시 이러한 메트릭을 캡처할 수 있는지 확인할 수 있습니다. 앱의 일부인가요? 원하시면 PR을 보내주세요 :-)

11. 보너스 학습

활동을 로드하는 동안 어떤 일이 발생하는지 이해하면 앱의 성능 특성을 더 잘 이해하는 데 도움이 됩니다. 이전 단계에서 활동을 로드하는 동안 어떤 일이 발생하는지 상위 수준에서 설명했지만 다음 다이어그램은 각 단계를 훨씬 더 자세히 설명합니다.

cd61c1495fad7961.png