[Android] View 렌더링

문승연·2024년 2월 18일
0

Android 기초

목록 보기
8/8

본 포스트는 안드로이드 View가 렌더링 되는 과정 해당 블로그의 글을 제가 이해하기 쉽게 옮겨 적은 포스트입니다. 자세한 내용은 위 글을 참고해주세요.

View의 렌더링 과정

안드로이드 XML로 작성한 View는 어떻게 최종적으로 화면에 렌더링되어 보여지는 것일까?

View는 크게 onMeasure(), onLayout(), onDraw() 3가지 생명주기 메소드 과정을 거쳐 사용자에게 보여진다. 더 자세한 내용은 View의 생명주기에 관한 글을 참고하자.

Rasterization(래스터화)

래스터화는 문자열, 버튼 또는 도형과 같은 객체들을 픽셀로 변환시키고 스크린상의 텍스쳐로 나타내는 과정을 말한다.

일반적으로 래스터화는 비용이 큰 작업에 속한다. 그러므로 GPU가 래스터화 가속을 위해 사용된다. GPU는 폴리곤, 텍스쳐 등을 계산하고 처리하는데 특화되어 설계되었다(병렬처리).

CPU가 화면에 무언가를 그리기 위해 GPU에게 폴리곤이나 텍스쳐의 래스터화를 위임하고 GPU의 최종적인 처리결과가 화면에 나타나게 된다.

CPU와 GPU간 데이터 전송 처리는 일반적으로 OpenGL ES API의 호출에 의해 일어난다. 안드로이의 UI 객체(점, 선, 면, 버튼, 이미지 등)가 화면에 나타나기 위해서는 항상 OpenGL ES를 거친다.

버튼을 화면에 렌더링하는 과정을 상상해보자. 우선 버튼이 있어야하고, 이를 CPU에 의해 폴리곤과 텍스쳐로 변환시킨 뒤 GPU에게 넘겨지게 된다.

위에서 언급했듯이 이렇게 UI 객체를 메쉬로 변환하는 과정은 비용이 큰작업이다. 모든 변환과정이 끝난 뒤 변환된 데이터가 OpenGL ES API에 의해 CPU에서 GPU로 전달되게 된다.

GPU에 업로드된 UI 객체 데이터는 GPU에 메모리상에 적재된 상태로 다음 프레임을 그릴때 재사용되므로, 매번 변환과정을 거칠 필요는 없다. 단지 GPU상에 업로드된 데이터를 참조하여 어떻게 그릴지 OpenGL ES에게 알려주기만 하면된다.

결국 렌더링 퍼포먼스를 최적화한다는 의미는 GPU 메모리에 데이터를 얼마나 많이 적재하고, 제거하며, 이를 얼마나 잘 참조하냐는 것이다.

디스플레이 리스트(Display List)

View의 렌더링이 필요할때 디스플레이 리스트가 생성되며, 디스플레이 리스트에서는 렌더링이 필요한 View에 대한 그리기 명령들이 포함되어있다.

View가 렌더링 된 이후에 View의 속성에 대한 변화가 있다면, 간단히 디스플레이 리스트를 변경하여 렌더링할 수 있지만, 눈에 보이는 변화가 크다면 이전 디스플레이 리스트는 더이상 유효하지 않으므로 새롭게 디스플레이 리스트를 생성하고 화면 갱신이 필요하다.

결국 View의 복잡도가 성능에 영향을 미치기 때문에, 디스플레이 리스트가 반복적으로 재생성되고 재실행되는 것을 제어하는것이 퍼포먼스를 향상 시킬 수 있는 방법 중 하나이다.

사이즈가 변경되는 View가 있다고 가정하자. 그러면 onMeasure() 단계에서 계층 모든 View들의 새로운 사이즈를 계산하게 되고, 만약 View의 포지션이 변경된다면 requestLayout()를 호출하게 된다. 또는 ViewGroup이 자식 View들을 재배치하는경우 onLayout()이 호출되고 View 전체 계층이 다시 배치되게 된다.

View의 생명주기 단계는 그다지 큰 시간이 걸리지 않아 퍼포먼스에 영향이 없으나, 다른 ViewViewGroup이 많이 연관되어 있다면 성능에 영향을 주게 된다.

업로드중..

더 나은 성능의 앱을 위해서는 View의 계층을 플랫하게 유지해야할 필요가 있다. 그래야 종속된 View들이 영향을 받지 않아 View가 갱신 되는데 시간이 줄어들게 된다. View의 계층을 플랫하게 유지하는데는 ConstraintLayout을 사용하면 좋다.

렌더링 퍼포먼스

개발자는 앱의 퍼포먼스를 체크해야할 의무가 있다. UI 퍼포먼스는 애플리케이션 성능에서 주요한 비율을 차지한다. UI 퍼포먼스를 저하시키는 오버드로잉에 대해서 알아보자.

오버드로우(Overdraw)

오버드로우(Overdraw)는 시스템이 단일 렌더링 프레임에서 같은 픽셀에 여러번 덧 그리는 것을 말한다. 이러한 GPU의 리소스 낭비로 인해 퍼포먼스가 떨어지고, 사용자에게 나쁜경험을 제공할 수 있다.

오버드로잉을 줄이기 위한 방법을 알아보자.

1. 레이아웃에서 불필요한 배경 제거하기

레이아웃 XML 파일에서 사용자가 절대 볼 일이 없는 불필요한 배경을 최대한 제거한다.

<LinearLayout 
    android:id="@+id/parent" 
    android:background=”@android:color/black”>
    <android.support.v4.widget.NestedScrollView>
        <LinearLayout 
             android:id="@+id/child" 
             android:background=”@android:color/black”>
             ...
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
</LinearLayout>

위 코드는 LinearLayoutNestedScrollView 둘 다 배경색이 검정색이다. 이 경우 가장 바깥쪽 LinearLayout만 검정색으로 배경을 지정해도 똑같이 보이기 때문에 굳이 NestedScrollView 배경까지 검정으로 지정해서 오버드로잉할 필요가 없다.

2. View 계층 평탄화하기

View 계층을 평탄화 하기 위해 ConstraintLayout을 사용하면 최상의 퍼포먼스를 낼 수 있다. ConstraintLayout은 레이아웃 내에 또 다른 레이아웃을 포함시킬 필요없이 간단한 제약조건으로 평탄한 계층구조를 만든다. 평탄한 뷰 계층을 구성하여 퍼포먼스를 향상하자.

3. 투명도 줄이기

화면에서 투명한 픽셀을 렌더링하는 것을 알파 렌더링이라고 한다. 페이드 아웃 및 그림자 같은 시각적 효과와 같은 투명한 애니메이션에는 투명도가 포함되므로 오버 드로우가 크게 발생한다. 이러한 상황에서 렌더링되는 투명 객체의 수를 줄임으로써 오버드로잉 비용을 줄일 수 있다.

예를 들어 TextView 에서 알파 값이 설정된 검정색 텍스트를 그려 회색 텍스트를 얻을 수 있는데, 이는 단순히 텍스트를 회색으로 그리는것보다 훨씬 비용이 많이 들기 때문에 그냥 투명도 없는 회색을 적용하는 편이 퍼포먼스를 높이는데 도움이 된다.

profile
"비몽(Bemong)"이라는 앱을 개발 및 운영 중인 안드로이드 개발자입니다.

0개의 댓글