프로그래밍/Android

[안드로이드] 앱이 버벅거리지 않게 하기 위해서 해야할 일

Lou Park 2021. 3. 31. 23:52

앱이 버벅댄다는건, 60FPS가 나오지 않는 상태를 의미한다. 16ms마다 그리기를 완성해야하는데 작업량이 많아 그것보다 시간이 더 걸리게되면 사용자가 알아채기 시작한다.

 

버튼이 그려지기까지의 과정

 

 

버튼같은 UI 오브젝트들은 먼저 CPU에의해 폴리곤(Polygon)과 텍스쳐(Texture)로 변환되어야한다. 이 변환 작업도 시간이 많이 걸리며(time-consuming), 이들을 CPU에서 OpenGL ES API를 통해 GPU로 업로드하는 작업도 시간이 많이 걸린다. GPU는 이들을 픽셀로 바꾸어 스크린에 보일 수 있게 만든다. 이 작업을 래스터화(Rasterization)라고한다.

 

GPU로 올라간 메쉬(mesh)는 곧바로 사라지지않고, GPU에 머물게되고 나중에 사용할 일이있을때 재사용하게 된다. 메쉬를 재사용하게 될 경우 앞서 CPU의 폴리곤/텍스쳐 변환작업이나 OpenGL ES 업로드 작업이 필요없게되어 렌더링 성능을 최적화 할 수 있다.

 

 

View의 생명주기(Life Cycle)

이것이 안드로이드 View의 생명주기다. 문서에 따르면 onMeasure()는 현재 뷰와 현재 뷰의 모든 자식뷰들의 크기 요구사항을 결정하기 위해서 호출되고, onLayout()도 현재 뷰의 모든 자식뷰들의 위치를 할당할때 호출되는데, 이로서 알 수 있는 점은 부모 뷰가 조금만 바뀌어도, 꼬리를 물고 자식의 자식의 자식의...최종 자식까지 영향을 받게 된다는 점이다.

 

버튼을 줄이는 단순한 동작을 하게 되더라도, 크기가 바뀌니 onMeasure()부터 시작해서 다시 모든 과정을 반복해야한다.

 

 

성능 개선을 위한 팁

 

1. 불필요한 배경색을 넣지마라.

 

가끔 앱이 하얗지만 아래 코드처럼 의미없이 색깔을 집어넣는 경우가 있다. 위에서 GPU는 스크린에 그려질 픽셀을 렌더링한다고 했는데, 어차피 보이지도 않을 픽셀을 불필요하게 여러번 렌더링하게 되어 성능에 영향을 줄 수 있다.

<LinearLayout android:id="@+id/parent" android:background=”@android:color/white”/>

 

설정 > 개발자 옵션 > 오버드로 디버그 > 오버드로 영역 표시를 누르면 Overdraw 단계에 따라 색상표시를 해줘서 내가 불필요하게 그리는 영역이 어디인지 한 눈에 볼 수 있다.

 

 

2. 뷰 계층 구조를 평평하게 하라.

뷰 계층 구조가 깊고 복잡하다면, 유지보수가 어려운건 물론이고 부모 뷰가 변했을때 많은 뷰들을 변화시켜야하고, 겹겹이 쌓인 뷰에대한 오버드로가 생긴다. ConstraintLayout으로 대부분의 View들을 평평하게 할 수 있다.

 

3. 투명함을 줄여라.

투명한 픽셀들을 스크린에 표시하는걸 알파 렌더링이라고 하는데, 페이드 아웃, 그림자, 반투명 등등의 비주얼 효과등이 포함된다. 이것들은 오버드로우에 꽤 영향을 미치니 사용을 주의해야한다. 회색 글자를 나타내기 위해 검은글자에 Alpha를 주는 일은 당연히 피하자!

 

4. ViewStub을 사용하라.

사실 처음부터 모든 뷰가 보이지 않아도 될 경우가 있다. 휴대폰 화면은 기껏해야 손크기정도기 때문에. ViewStub은 보이지 않는 뷰로, 런타임중에 원하는 뷰를 Inflate할 수 있다 (Lazy-inflate). 설명이 다소 개인적이지만 하스스톤에서 고치덱(?)처럼 고치를 소환했다가 원할때 진화해서 고치를 대신해 성체가되는 식이다! ViewStub의 inflate()를 호출하면 레이아웃이 전개되고 ViewStub 자신을 대체한다.