Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android는 어떻게 화면을 그릴까?

Android는 어떻게 화면을 그릴까?

2025.04.05
Build With AI 2025

DavidKwon7

April 05, 2025
Tweet

More Decks by DavidKwon7

Other Decks in Technology

Transcript

  1. ◼ XML(eXtensible Markup Language) 은 UI를 정의하는 마크업 언어 ◼

    Android에서는 .xml 파일로 UI를 설계하고, 이를 setContentView()를 통해 분리된 환경에서 화면 구현 XML 이란
  2. 장점 • UI와 로직이 분리되어 있어 가독성이 좋음 • ConstraintLayout,

    LinearLayout 등을 활용해 UI를 쉽게 배치 가능 • Android Studio의 Layout Editor에서 미리보기 제공 단점 • XML과 코드(findViewById())를 연결해야 함 → 번거로움 • RecyclerView 등 동적인 UI 구성 시 코드가 복잡해짐 XML 장점 / 단점
  3. ◼ Jetpack Compose는 Kotlin 기반의 선언형 (Declarative) UI 프레임워크 ◼

    XML 없이 코드에서 직접 UI를 작성 ◼ React, Flutter와 비슷한 개념으로 State 기반 UI 업데이트 지원 Jetpack Compose
  4. @Composable fun MyScreen() { Column { Text(text = "안녕하세요!") Button(onClick

    = { /* 클릭 이벤트 */ }) { Text(text = "클릭하세요") } } }
  5. 장점 • XML 없이 코드에서 직접 UI를 정의 가능 •

    효율적인 UI 업데이트 (필요한 부분만 다시 그림) • 쉬운 컴포넌트 재사용 및 공유 단점 • 기존 View 시스템과 완전히 다르므로 학습 필요 • 커뮤니티 리소스가 XML에 비해 상대적으로 적음 Compose 장점 / 단점
  6. ◼ setContentView() 호출 시, LayoutInflater.inflate()를 내부적으로 호출 ◼ LayoutInflater가 XML을

    읽고, View 객체 생성 ◼ViewGroup(부모 view)과 자식 view들이 계층 구조 (Tree)로 메모리에 로드됨 XML Parsing
  7. View Group, View • View : 위젯이라 하며 Button, TextView

    등을 예로 들 수 있다. • View Group : View를 여러개 담을 수 있다. (LinearLayout, ConstraintLayout..)
  8. <?xml version="1.0"encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/text" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:text="Hello,I am a TextView"/> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello,I am a Button"/> </LinearLayout> View Group View View
  9. ◼ View의 크기를 결정하는 기능 수행 ◼ 각 뷰가 자신에게

    주어진 크기를 기준으로 크기를 결정 ◼ 부모 ViewGroup이 자식 View의 제약조건 (MeasureSpec)을 설정 onMeasure()
  10. ◼ MeasureSpec.EXACTLY : 부모가 자식의 정확한 크기를 결정했습니다. 자식 View가

    얼마나 큰지 관계없이 지정된 크기(경계)가 주어집니다. ◼ MeasureSpec.AT_MOST : 자식은 지정된 크기까지 원하는만큼 커질 수 있습니다. ◼ MeasureSpec.UNSPECIFIED : 부모가 자식에게 어떤 제약도 부과하지 않았습니다. 원하는 크기가 될 수 있습니다. onMeasure()
  11. ◼ View의 위치를 결정하기 위해 onLayout() 메서드 호출 ◼ onMeasure()

    단계에서 결정된 크기를 기반으로 View의 화면상 위치 설정 ◼ 각 View가 부모로부터 위치 정보를 받아 배치됨 ◼ ViewGroup이 onLayout()을 호출하여 자식 View의 위치를 결정 onLayout()
  12. ◼ Canvas 객체를 이용해 View를 그리는 단계 ◼ View의 상태가

    변경되거나 화면을 다시 그려야 하는 경우에 invalidate() 메서드를 호출하여 onDraw() 메서드를 다시 호출할 수 있습니다. onDraw()
  13. ◼ Window는 뭔가를 그릴 수 있는 창이며, WindowManager를 통해 Window를

    관리할 수 있습니다. ◼ Window는 독립적인 Surface를 가지고 있습니다. Window
  14. ◼ Surface는 Window에 표시될 그래픽 데이터를 저장할 수 있는 메모리

    영역을 제공 ◼ App이 Surface에 직접 그림을 그리고, 이를 SurfaceFlinger가 화면에 합성 Surface
  15. ◼ Bitmap에 그림을 그릴 수 있는 도구(렌더링 엔진) ◼ Surface를

    잠그면 Canvas 객체를 얻을 수 있으며, 이 Canvas를 사용하여 Surface의 드로잉 버퍼에 그림을 그릴 수 있습니다. Canvas
  16. ◼ Surface의 Buffer를 잠그고, 그림을 그릴 수 있는 Canvas 객체를

    반환. ◼ Buffer를 잠그는 이유는 여러 스레드에서 동시에 버퍼에 접근하여 데이터를 변경하는 것을 방지하기 위함 Lock Canvas
  17. ◼ lockCanvas()로 잠근 드로잉 버퍼를 잠금 해제하고, 변경된 내용을 SurfaceFlinger에

    전달하여 화면에 표시되도록 한다. ◼ unlockAndPost()를 호출하기 전까지 Surface에 그린 내용은 화면에 표시되지 않습니다. ◼ Buffer의 잠금을 해제하면, 다른 스레드에서 드로잉 버퍼에 접근할 수 있습니다. UnlockAndPost
  18. val surfaceHolder = surfaceView.holder val paint = Paint() paint.color =

    Color.WHITE paint.textSize = 50f val canvas = surfaceHolder.lockCanvas() if (canvas != null) { try { canvas.drawColor(Color.BLACK) canvas.drawText("Hello", 100f, 100f, paint) } finally { surfaceHolder.unlockCanvasAndPost(canvas) } } Canvas에 그리기 수행 그린 내용을 화면에 표시
  19. 동작 방식 Window 생성하고, Window는 자체 Surface 생성 Surface 잠그면

    Canvas 객체를 얻을 수 있습니다 Canvas를 사용하여 View 계층 구조를 따라가며 UI를 그립니다 그리기 작업이 완료되면 Surface를 잠금 해제 SurfaceFlinger는 게시된 버퍼를 사용하여 화면 합성
  20. displayList ◼ View에 변경이 발생하면 View-ViewGroup-Root View-View까지 내려와야하는 과정이 있었고,

    이는 매우 비효율적이었다. 이러한 문제점을 해결하기 위해서 displayList 등장. ◼ UI 관련 그래픽 데이터를 저장해둔 후, 변경이 발생하면 바로 리스트를 확인해서 효율적으로 변경에 대응할 수 있다는 이점 존재.
  21. displayList ◼ View의 onDraw() 메서드가 호출되면 View가 그려진다. 이때 그려지는

    모든 정보는 displayList에 기록. ◼ View의 내용이 변경되지 않았으면, 이전에 생성된 DisplayList를 재사용, 변경(invalidate)되었으면 새로운 displayList 생성 ◼ displayList에 기록된 view 관련 데이터는 GPU로 전송
  22. Rasterization (래스터화) ◼ UI 요소를 그릴 때 직선, 곡선, 도형

    등 백터 데이터를 픽셀 정보(래스터 이미지)로 변환하여 디스플레이로 출력하는 과정 ◼ GPU에서 렌더링 된 데이터는 BufferQueue를 통해 SurfaceFlinger라는 시스템 서비스로 전달됩니다.
  23. SurfaceFlinger ◼ 생산자가 버퍼를 전달하면 SurfaceFlinger는 모든 요소를 디스플레이에 합성해야

    합니다. ◼ V-Sync와 맞춰 디스플레이에 출력 ◼ Hardware Composer(HWC)와 협력하여 디스플레이로 출력
  24. HWC (hardware composer) ◼ UI를 렌더링하고 이를 BufferQueue를 통해 SurfaceFlinger에

    전달 ◼ HWC는 하드웨어 수준에서 화면 합성을 수행 ◻ 여러 레이어(UI, 네비게이션바, 상태바 ..)를 하나의 최종 이미지로 합성 ◻ GPU보다 전력 효율이 좋은 전용 디스플레이 하드웨어를 활용하여 합성 작업을 수행 ◼ HWC는 한정된 resource를 가지고 있는 Android에서 GPU의 부담을 줄이고, 디스플레이 하드웨어를 활용하여 최적의 성능을 제공 가능
  25. Project Butter • Android 모바일 운영 체제의 속도와 반응성을 높이기

    위한 Google의 프로젝트 (Android 4.1 Jelly Bean(2012년)에 처음 소개) • UI의 부드러움과 반응성을 개선하는데 초점
  26. V-Sync 적용 • 화면 주사율(60Hz)에 맞춰 UI를 렌더링하여 부드러운 애니메이션

    제공 • 화면 끊김(Jank) 방지 Triple Buffering 도입 • Double Buffering -> Triple Buffering • UI 렌더링 시 GPU가 다음 프레임을 준비하는 동안 CPU가 UI 로직을 동시에 처리가 가능해짐 • Frame Drop 문제 해결 Project Butter
  27. 터치 반응 속도 향상 V-Sync와 동기화하여 반응 속도 증가 렌더링

    성능 향상 • GPU 하드웨어 가속을 모든 UI 애니메이션에 적용 • 기존에는 일부 UI 요소만 하드웨어 가속을 사용했지만, Project Butter 이후 전체 UI가 GPU 가속 활용 Project Butter
  28. V-Sync(수직동기화) ◼ GPU의 Rendering Rate(fps)와 Device Presenting Rate(hz) 간의 간극이

    있을 때 조정해주는 역할을 수행 ◼ V-Sync는 디스플레이가 화면을 업데이트하는 시점을 나타내는 신호입니다. ◼ 이를 통해 화면 Tearing이나 Frame Drop없이 부드러운 화면 표시를 보장
  29. Choreographer ◼ Project Butter에서 도입 ◼ V-Sync 신호에 맞춰 UI가

    일정한 프레임 속도로 렌더링되도록 보장하는 역할
  30. 렌더링 작업 스케줄링 애니메이션, UI 업데이트가 요청되면 V-Sync 신호에 맞춰

    적절한 시점에 실행되도록 스케줄링 V-Sync 동기화 • V-Sync 신호에 맞춰 App의 렌더링 작업을 실행 • 이를 통해 부드러운 화면 구성을 얻을 수 있다. 콜백 등록 • Choreographer에 콜백을 등록하여 V-Sync 신호가 발생할 때 특정 작업을 수행하도록 설정 가능 • 이를 통해 애니메이션, UI 업데이트, 그리기 작업 등을 V-Sync에 맞춰 실행 가능 Choreographer
  31. Buffering ◼ Buffer는 GPU가 그린 화면을 임시 저장하는 메모리 공간

    ◼ Buffering은 UI를 부드럽게 그리기 위해 한 번에 한 프레임씩 준비하는 것이 아니라 백그라운드에서 미리 프레임을 준비해서 표시하는 방식을 의미
  32. Double Buffering 개념 • 두 개의 버퍼 • Front Buffer

    : 현재 디스플레이에 출력 중인 프레임 • Back Buffer : 다음 프레임을 준비하는 버퍼 동작 방식 • GPU가 Back Buffer에서 새 프레임을 그림 • 프레임이 완료되면 Front Buffer와 교체 • 디스플레이는 새로운 Front Buffer를 출력
  33. Triple Buffering 개념 • 세 개의 버퍼 • Front Buffer

    : 출력 중인 프레임 • Back Buffer1 : 렌더링이 끝난 프레임 • Back Buffer2 : 렌더링 중인 프레임 동작 방식 • GPU가 Back Buffer에서 새 프레임을 그림 • 디스플레이가 준비되면 Back Buffer와 Front Buffer 교체 • 이전 Front Buffer는 Back Buffer로 변경 • 기존에 남아있던 Back Buffer에 다음 프레임 렌더링
  34. Android에서 XML, Jetpack Compose로 작성된 코드는 parsing 진행 parsing된 데이터들은

    displayList에 저장이 되고 래스터화 BufferQueue를 통해 SurfaceFlinger에서 합성된 후 화면에 출력 결론 Android 그래픽 GPU 렌더링 속도 및 오버로드 검사