Compose에서의 레이아웃

햄햄·2022년 6월 5일
0

Compose

목록 보기
5/7
post-thumbnail

Compose 레이아웃의 목표

Compose 레이아웃 시스템의 구현에는 두 가지 목표가 있습니다.

  • 고성능
  • 쉬운 커스텀 레이아웃 작성

이번 글에서는 고성능을 위해 Compose가 어떻게 동작하는지에 관해 알아보겠습니다.

기존의 뷰 시스템

기존의 뷰 시스템에서는 여러개의 뷰를 중첩하면 중첩된 계층 구조의 뷰를 측정하면서 layout-measure 과정을 두 번 이상 실행하는 Double taxation(이중 과세)이 발생해 성능에 영향을 미칠 수 있었습니다.

Double taxation?
layout-measure 과정이 두 번 이상 실행되는 것입니다. 예를 들어 RelativeLayout를 사용할 때 발생합니다. RelativeLayout를 사용하면 다음과 같은 Double taxation이 발생합니다.
1. 첫 번째 layout-measure 과정에서 각 child의 요청을 기반으로 위치와 사이즈를 계산합니다.
2. 위 데이터와 weight 등을 고려해 연관된 뷰들의 적절한 위치를 파악합니다.
3. 두 번째 layout 과정을 통해 위치를 결정짓습니다.

따라서 flat한 뷰 계층 구조를 위해 복잡한 레이아웃에서는 ConstraintLayout을 권장했습니다.

그렇다면 Compose에서는


Compose는 위와 같은 과정을 거쳐 상태를 UI 요소로 변환합니다.
Composition 단계에서는 composable 함수를 실행하고 UI 트리를 만듭니다.
Layout 단계에서는 트리의 각 노드들의 측정되고 배치됩니다. 각각의 노드들은 그들의 가로, 세로 크기, xy 좌표를 결정짓습니다.
Drawing 단계에서는 트리의 모두 요소들이 렌더링됩니다.
Layout 단계는 측정과 배치 단계로 나누어 있는데, 이는 뷰의 onMeasureonLayout과 비슷합니다.위 예제의 SearchResult composable은 다음과 같이 Layout 단계가 이루어집니다.

  1. 루트 노드 Row에 측정을 요청
  2. 루트 노드 Row는 첫 번째 하위 요소 Image에 측정을 요청
  3. Image는 리프 노드(하위 요소가 없음)이므로 크기를 보고하고 배치 안내(placement instructions)를 반환
  4. 루트 노드 Row는 두 번째 하위 요소 Column에 측정을 요청
  5. Column 노드는 첫 번째 Text 하위 요소에 측정을 요청
  6. 첫 번째 Text 노드는 리프 노드이므로 크기를 보고하고 배치 안내를 반환
  7. Column 노드는 두 번째 Text 하위 요소에 측정을 요청
  8. 두 번째 Text 노드는 리프 노드이므로 크기를 보고하고 배치 안내를 반환
  9. 이제 Column 노드의 하위 요소가 크기가 지정되고 배치되었으니 자체 크기와 배치 결정
  10. 이제 루트 노드 Row의 하위 요소가 크기가 지정되고 배치되었으니 자체 크기와 배치 결정

즉, 각 노드는 자신의 측정을 요청받고, 트리의 아래로 크기 제약 조건등을 전달하며 하위 요소들의 측정을 요청합니다. 리프 노드 크기가 지정되고 배치되면 확인된 크기 및 배치 안내는 다시 트리 위로 전달됩니다.
간단히 말해, 상위 요소는 하위 요소보다 먼저 측정되지만 크기와 위치는 하위 요소 다음에 지정됩니다.상위 요소는 허용 가능한 크기를 전달하고 이를 제약으로 표현합니다. 상위 요소와 하위 요소 간의 협상은 없고, 하위 요소가 제약에 맞는 크기를 선택하면 상위 요소는 이를 받아 처리합니다.

이러한 방식을 통해 single pass로 UI 트리 전체를 측정해 여러번의 측정 사이클을 돌지 않아도되면서 성능을 향상시킬 수 있는 것 입니다.

따라서 기존 뷰 시스템에서 flat한 뷰 계층 구조를 위해 권장하던 ConstraintLayout을 Compose에서는 ConstraintLayout의 사용을 선택사항으로 제안하고 있습니다.

참고: 뷰 시스템에서 ConstraintLayout은 크고 복잡한 레이아웃을 만드는 데 권장된 방법이었습니다. 플랫 뷰 계층 구조가 중첩 뷰보다 성능이 더 우수했기 때문입니다. 그러나 이는 깊은 레이아웃 계층 구조를 효율적으로 처리할 수 있는 Compose에서는 문제가 되지 않습니다.
https://developer.android.com/jetpack/compose/layouts/constraintlayout

https://www.youtube.com/watch?v=zMKMwh9gZuI
https://developer.android.com/topic/performance/rendering/optimizing-view-hierarchies
https://developer.android.com/jetpack/compose/phases?hl=ko

0개의 댓글