# Flutter 주요 Tree 구조 정리 (Widget / Element / Render)

김재경·2026년 2월 19일

Flutter UI Tree에 관련된 Flutter의 3가지 주요 트리구조 글을 읽었다.

이 글에서는 Flutter의 UI가 단순히 Widget Tree 하나로 구성되는 것이 아니라, 내부적으로 서로 다른 역할을 가진 세 가지 Tree 구조를 통해 구성되고 관리된다고 설명하고 있다.

Flutter UI는 다음과 같은 세 가지 Tree로 구성된다:

Widget Tree
Element Tree
Render Tree

이 세 Tree는 각각 역할이 명확히 나뉘어 있으며, UI 생성, 상태 유지, 렌더링 과정에서 서로 연결되어 동작한다.

전체적인 구조는 다음과 같다:

Widget
  ↓
Element
  ↓
RenderObject

링크 내용 요약

1. Widget Tree (UI 구조 정의)

Widget Tree는 개발자가 작성하는 UI 코드 자체이다.

Widget의 특징:

  • immutable 객체
  • UI 구조를 정의하는 역할
  • rebuild 시 새로 생성됨
  • state를 직접 저장하지 않음

Widget은 UI를 구성하는 실제 객체라기보다는,

UI를 어떻게 구성할지를 설명하는 설정 객체(config)의 역할을 한다.


2. Element Tree (lifecycle 및 state 관리)

Element Tree는 Widget Tree와 Render Tree 사이에서 중간 역할을 수행한다.

Element의 주요 역할:

  • Widget과 RenderObject 연결
  • Widget의 build() 호출
  • state 저장 및 관리
  • Widget 변경 감지 및 update 처리
  • lifecycle 관리

Flutter에서 중요한 구조 중 하나는 state가 Widget이 아니라 Element에 저장된다는 점이다.

이 때문에 Widget이 rebuild되어도 state는 유지된다.

또한 Flutter에서 사용하는 BuildContext는 실제로 Element 객체를 참조한다. (BuildContext = Element)

즉, context는 Tree 상에서의 위치를 나타내는 객체이다.


3. Render Tree --- 실제 렌더링 수행

Render Tree는 실제 화면 렌더링을 담당하는 객체 트리이다.

RenderObject의 역할:

  • layout 계산
  • size 계산
  • 위치 계산
  • paint 수행

대표적인 RenderObject:

RenderBox        → 기본 layout 단위
RenderFlex       → Row / Column layout 처리
RenderParagraph  → Text 렌더링

RenderObject는 Element에 의해 생성되고 관리되며, 실제로 화면에 UI를 그리는 역할을 담당한다.


전체 동작 흐름

초기 생성:

Widget 생성
→ Element 생성
→ RenderObject 생성
→ 화면 렌더링

rebuild 발생 시:

새 Widget 생성
→ 기존 Element와 비교(diff)
→ 필요한 경우만 RenderObject update
→ 화면 업데이트

이 구조를 통해 Flutter는 rebuild가 자주 발생하더라도 전체 UI를 다시
그리지 않고, 변경된 부분만 업데이트하여 높은 성능을 유지할 수 있다.


추가로 궁금했던 점 정리

1. Element와 State lifecycle 및 재사용 원리

Flutter에서 state는 Widget이 아니라 Element에 저장된다.

구조:

StatefulWidget
  ↓
StatefulElement
  ↓
State

rebuild 발생 시:

새 Widget 생성
기존 Element 재사용
기존 State 유지

Element lifecycle

create
mount
update
unmount
dispose

Element 재사용 조건

runtimeType 동일
key 동일

조건이 다르면 Element는 재사용되지 않고 새로 생성된다.


2. BuildContext와 Element 관계 및 unmounted 상태

Flutter에서 BuildContext는 Element 객체이다.

BuildContext = Element

Element가 unmount되면 해당 context도 더 이상 유효하지 않다.

예:

await Future.delayed(...);
Navigator.of(context).pop();

해결:

if (!context.mounted) return;

또는

if (!mounted) return;

3. RenderObject 역할 및 실제 렌더링 구조

RenderObject는 실제 화면 렌더링을 담당한다.

주요 역할:

  • layout 계산
  • size 계산
  • 위치 계산
  • paint 수행

대표:

RenderBox\
RenderFlex\
RenderParagraph


4. GlobalKey와 Element 식별

GlobalKey는 Element를 전역적으로 식별한다.

가능:

  • state 유지하며 위치 이동
  • 특정 widget 직접 접근

주의:

비용이 크므로 필요한 경우에만 사용


5. lifecycle과 context 사용 시점

initState에서는 InheritedWidget 의존 관계가 안정되지 않은 상태이다.

권장 사용 위치:

didChangeDependencies
build
postFrameCallback

didChangeDependencies는 InheritedWidget 변경 시 호출된다.


핵심 요약

Widget       → UI 정의
Element      → lifecycle + state 관리
RenderObject → 실제 렌더링

중요 포인트:

  • Widget은 immutable이며 rebuild 시 새로 생성된다
  • Element는 state와 lifecycle을 관리한다
  • State는 Element에 저장된다
  • BuildContext는 Element이다
  • RenderObject가 실제 UI를 렌더링한다

정리

Flutter는 단순히 Widget rebuild로 UI를 다시 그리는 구조가 아니라,

Element Tree를 통해 변경 사항을 추적하고, 필요한 RenderObject만 업데이트하는 구조이다.

이 구조 덕분에 Flutter는 rebuild가 자주 발생해도 높은 성능을 유지할 수 있다.

0개의 댓글