티스토리 뷰

지금까지 Widget과 Element 관계에 대해서 알아보았다.

이런 관계가 만들어지는 근본적인 이유는 Flutter의 속도를 높이고 Rendering에 필요한 연산을 최소화 하기 위해서 이다.

그래서 Element는 결국 최종적으로 화면에 정보를 표시하기 위한 정보를 담는 RenderObject들과 연결되고 이 정보들을 재활용 함으로써 Widget들의 잦은 빌드 이벤트를 처리한다. 

Widget Tree

개발자가 build함수에서 Widget들을 구성해서 반환하면 이것들이 모여 하나의 큰 Widget tree를 만든다.

Widget tree는  실제로 존재한다기 보다는 개발자가 인지할 수 있도록 편의상 만든 개념에 가깝다
(dart devtool의 widget inspector에서 볼 수 있는 widget tree는 개발의 편의를 제공해 준다.)

Element Tree

Flutter는 선언된  Widget들을 이용해서 실제로 사용할 Element Tree로 만든다.

Element tree는 Element들이 서로 부모 자식 관계를 가지는 논리적인 Tree구조로 되어 있으며, 
Flutter에서 Element tree를 이용해서 화면에 표시할 정보와 상태를 관리한다.

하나의 화면에서 Element tree의 상태를 유지 하며 widget의 변환에 따라 Element tree를 재구성한다.

Flutter는 Element의 상태를 확인해서 화면에 표시할 정보를 표시한다.

 

Element는 크게 RenderObjectElement와 ComponentElement, InheritedElement가 있다.

ComponentElement

개발자가 주로 다루는 StatelessWidget과 StatefulWidget의 Element는 ComponentElement를 상속받는다.

위 두 위젯(StatelessWidget/StatefulWiget)을 보면 Widget을 반환하는 Build함수를 구현해야 하는데 여기서 반환하는 Widget의 구성이 하위 Tree로 배치한다.

ComponentElement는 화면에 정보를 직접 표시하지 않고 자식 Element가 Tree로 구성(부모/자식관계의 설정)될 수 있도록 도와주는 역할을 한다.

InheritedElement

InheritedWidget의 Element로 Tree중간에서 하위 Tree의 Child Element에서 사용할 수 있는 정보를 가지고 있으며, 이 정보가 변경되면 정보를 사용하고 있는 Child Element들에게 정보의 변경을 알려주는 역할을 한다.

이런 형태는 InheritedWidget의 데이터를 자식들이 쉽게 구독하고 사용할 수 있도록 한다.

(참고로 상태관리 라이브러리인 Provider는 내부는 실제로 InheritedWidget를 사용한다. ) 

RenderObjectElement

실제로 화면에 레이아웃을 비롯한 각종 그래픽적인 요소를 표시할 수 있는 RenderObject을 포함하고 있다.

이 Element를 통해 RenderObject는 Rendering을 위한 별도의 RenderObject Tree를 구성하고,

Flutter는 이 RenderObject Tree를 화면에 표시한다.

 

Render Tree

실제 화면에 표현가능한 정보만을 가지고 Tree를 구성하는 것으로

Widget중 RenderObjectWidget에 구현된 createRenderObject함수에서 생성한 RenderObject들로 Tree를 구성한다. 

그렇기 때문에 RenderObjectWidget에 대해서만  Widget -> RenderObjectElement -> RenderObject의 관계를 가진다. 

Widget - Element - RenderObject 관계

아래 코드로 부터 생성되는 Widget-Element-RenderObject의 관계를 예로 들어 보자. 

SafeArea(
  child: Scaffold(
    appBar: AppBar(
      title: Text('Title'),
    ),
    body: Container(
      child: Center(
        child: Text('Body Message'),
      ),
    ),
  ),
 );

위 코드로 부터 Widget를 만들 수 있다.  위에서 우리가 작성한 위젯이 build되면서 실제로 사용하는 위젯들까지 포함하는 위젯트리가 만들어 진다. 

Element Tree는 Widget Tree에 의해 정확히 1:1관계로 만들어진다.  

Render Tree는 Element중 RenderObjectElement에 대해서만 만들어진다.

Flutter는 Element를 이용해 상태를 저장/확인하고, RenderObject로 화면 렌더링에 필요한 정보를 계산한 후 유지한다. 

그렇기 때문에 Widget -> Element -> RenderObject로 갈수록 생성과 계산에 더 많은 시간이 필요하게 된다. 

 

이런 구조 때문에 Flutter는 생성에 더 많은 자원이 필요한 Element와 RenderObject를 최대한 재사용하는 구조로 만들어진 것이다. 

 

마치며

우리가 Flutter Widget을 구성할 때 RenderObject까지 고민할 필요는 없습니다.

개발자는 Widget으로 화면을 구성하면 많은 부분을 Flutter가 최적화해서 Element들을 재사용해서 화면을 그려주기 때문입니다.

하지만 만약 자신이 원하는 것과 다르게 화면이 표시되거나 화면 표시가 느리거나 버벅거림이 발생한다면 

Widget-Element-RenderObject 관계를 다시한번 확인 불필요한 Element 생성이 있는 것은 아닌지 확인해 보시기바랍니다.

 

 

참고자료
https://docs.flutter.dev/resources/architectural-overview#build-from-widget-to-element

 

Flutter architectural overview

A high-level overview of the architecture of Flutter, including the core principles and concepts that form its design.

docs.flutter.dev

https://youtu.be/996ZgFRENMs

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함