뚝딱뚝딱 모바일

[Flutter] 앱 성능 측정을 해보자 본문

Flutter 지식

[Flutter] 앱 성능 측정을 해보자

규석 2023. 11. 14. 19:38

안녕하세요!

Flutter로 앱을 개발하다 보면, 정말 성능이 괜찮을까? 괜스레 걱정이 든 적이 많으실 겁니다.

직접 눈으로 보고 확인할 수 있도록 Flutter로 만든 앱의 성능을 한번 측정해 보겠습니다.


앱의 성능을 체크하기 위해서 Flutter에서는 Flutter DevTools를 지원합니다!

https://docs.flutter.dev/tools/devtools/overview

 

DevTools

How to use the DevTools with Flutter.

docs.flutter.dev

이 DevTools로 측정을 하기 전에 앱을 profile 모드로 켜줄 겁니다. 

Android Studio 상단의 Run -> Profile을 클릭하여 실행시켜 줍시다.

Profile

앱이 실행되면, Android Studio 우측 바에서 Flutter Perfomance가 툭 튀어나와 그래프가 보이실 겁니다.

안 나오셔도 오른쪽 옆에 보시면 있으실 겁니다...!

여기서도 볼 수 있지만, 콘솔 상단 좌측에 Flutter 버튼을 눌러서 열리는 웹 창으로도 볼 수 있습니다.

사실 저 모양이 무슨 모양인지 모르겠어요

창을 여니, UI 렌더링 시간이 얼마나 걸렸는지 그래프를 보여주고 있습니다. 뭔가 빨간색으로 무섭게 경고도 하고 있습니다...

화면을 이동하거나 스크롤을 움직이거나 등의 UI가 변화하는 행동을 할 때, 그래프가 더욱 추가되어 UI 렌더링 시간에 대해 표현해줍니다.

막대그래프가 표현하는 것들을 간단하게 설명드리면,

UI

UI 스레드는 Dart VM을 통해 Dart 코드를 실행하는 스레드입니다. Widget Tree를 Layout Tree로 변환하고 (이 부분에 대해선 추후 포스팅하겠습니다.) 이를 Raster 스레드로 보냅니다. 또한 이 스레드는 정지되어선 안됩니다.

Raster

Raster 스레드(GPU 스레드라고도 함)는 Flutter 엔진에서 그래픽 코드를 실행합니다. Layout Tree를 가져와 GPU와 통신하며 UI를 업데이트합니다. 이 스레드와 데이터들은 직접적으로 접근이 불가하지만, 이 스레드가 느리다면, Dart code 때문이라고 합니다. 느려지는 원인에는 불필요한 saveLayer() 함수 호출, Opacity, Clip, Shadow가 주요하다고 합니다.

Jank

Jank는 앱이나 웹이 화면의 주사율에 맞추지 못하고 버벅거리는 것을 뜻합니다.

Flutter에서는 Skia 엔진을 활용하여 네이티브 컴포넌트 (Android, iOS)들을 거치지 않고 바로 화면에 렌더링 하고 있습니다.

이 Skia 엔진은 기기 주사율에 맞게 업데이트하는데, 이 주기(60 fps 기준 16ms)보다 UI 렌더링 속도가 길어지면 화면의 주사율에 못 맞추게 되니 사용자는 '버벅거리네'라고 생각할 수 있습니다.

Shader compilation

Shader compilation은 shader(그래픽 요소를 정의하는 작은 조각)가 Flutter에서 처음 사용될 때 발생합니다. 

 

이렇게 설명할 수 있습니다. [참고 링크

 

각 렌더링 그래프를 클릭해 보면, 어떤 상황에서 얼마나 시간이 걸렸는지에 대해 알려줍니다.

저 같은 경우에는 UI pharse에서 Build가 0.3ms, Layout이 0.1ms 미만, Paint가 0.3ms, 총 0.7ms가 걸렸습니다. UI 부분은 매우 빠르게 진행이 되었군요! 그러나, Raster pharse에서 Raster가 18.9ms를 차지했다고 합니다. (뭐가 문제일까...)

개선하려면...?

먼저 Shader compilation jank에 대해서는 Flutter에서 제시하는 방법이 있습니다. 초기에 실행할 때 생기는 문제이므로, 이를 미리 저장해 두고, 실행한다면 더욱 좋은 UX를 보일 수 있습니다.

https://docs.flutter.dev/perf/shader

 

Shader compilation jank

What is shader jank and how to minimize it.

docs.flutter.dev

또 코드를 작성할 때

Build 함수는 가볍게

Build 함수는 UI 변경에 따라 호출되는 함수로, 함수 내에서 무거운 작업을 지양하고, 자주 불리지 않게 관리해주는 것이 좋습니다.

이를 위해 상위의 뷰는 StatelessWidget, 그 안의 세부적인 위젯들은 StatefulWidget을 사용하기도 합니다.

또, const를 활용하면 위젯이 rebuild 되어도, build 되지 않기 때문에, 효율적으로 사용할 수 있습니다.

Lazy Load 활용

ListView보다는 ListView.build를 권장합니다. ListView.builder는 화면에 표시되는 위젯만 build 하고 화면에서 사라지게 되면, 메모리에 남아있지 않습니다. 하지만 ListView는 처음부터 내부 모든 위젯을 build 하여 jank를 유발합니다.

 

를 신경 써서 코드를 짜시면, 조금 더 좋은 성능 개선을 보실 수 있습니다.