RenderObject 시스템의 이해
Flitter는 Flutter와 동일한 렌더링 아키텍처를 사용합니다. 화면에 무언가를 그리기 위해서는 세 가지 트리 구조를 이해해야 합니다.
Widget Tree → Element Tree → RenderObject Tree
세 개의 트리 구조
Widget은 설계도, Element는 인스턴스, RenderObject는 실제 렌더링을 담당합니다
Widget Tree
설계도 (불변 객체)
Element Tree
인스턴스 (상태 관리)
RenderObject Tree
실제 렌더링 (레이아웃 & 페인팅)
// Widget Tree (개발자가 작성하는 코드)
Container({
child: Text("Hello")
})
// Element Tree (프레임워크가 자동 생성)
ContainerElement -> TextElement
// RenderObject Tree (실제 렌더링)
RenderDecoratedBox -> RenderParagraph
각 트리의 역할
Widget Tree (설계도)
- 불변(immutable) 객체로 UI의 구조를 선언적으로 표현
- 개발자가 작성하는 코드
- 매 프레임마다 새로 생성될 수 있음
Element Tree (인스턴스)
- Widget과 RenderObject를 연결하는 중간 계층
- 상태를 관리하고 라이프사이클을 처리
- Widget이 변경되어도 Element는 재사용됨
RenderObject Tree (렌더링)
- 실제 레이아웃 계산과 그리기를 담당
- 크기, 위치, 페인팅 정보를 가짐
- 성능상 중요한 부분으로, 가능한 한 재사용됨
Layout과 Paint의 분리
Layout과 Paint 과정
performLayout()에서 크기와 위치를 계산하고, paint()에서 실제로 그립니다
Layout Phase
performLayout()
1. 자식 크기 측정
2. 자신의 크기 결정
3. 자식 위치 결정
Layout Phase
performLayout() {
// 1. 자식에게 제약 전달
child.layout(constraints);
// 2. 자신의 크기 결정
size = computeSize(child.size);
// 3. 자식 위치 결정
child.offset = computeOffset();
}
Paint Phase
paint(context, offset) {
// 1. 배경 그리기
context.drawRect(rect, paint);
// 2. 자식 그리기
child.paint(context, childOffset);
// 3. 전경 그리기
context.drawBorder(border);
}
performLayout(): 크기와 위치 계산
class RenderBox {
performLayout() {
// 1. 자식들의 레이아웃 수행
// 2. 자식들의 크기를 기반으로 자신의 크기 결정
// 3. 자식들의 위치 결정
}
}
paint(): 실제 화면에 그리기
class RenderBox {
paint(context: PaintingContext, offset: Offset) {
// 1. 자신의 내용 그리기 (배경, 테두리 등)
// 2. 자식들에게 paint 요청
}
}
왜 분리되어 있는가?
Layout과 Paint를 분리하는 이유는 성능 최적화 때문입니다:
- 레이아웃 캐싱: 크기나 위치가 변하지 않으면 레이아웃을 다시 계산하지 않음
- 부분 리페인트: 색상만 변경된 경우 레이아웃 없이 페인트만 수행
- 레이어 최적화: 변경되지 않은 부분은 레이어로 캐싱
소스 코드 살펴보기
Flitter의 RenderObject 구현은 packages/flitter/src/renderobject/
디렉토리에서 확인할 수 있습니다:
RenderObject.ts
: 기본 RenderObject 클래스RenderBox.ts
: 2D 박스 모델을 구현하는 RenderBoxRenderFlex.ts
: Row, Column의 기반이 되는 Flex 레이아웃
실제 구현을 보면 Flutter와 거의 동일한 구조로 되어 있음을 알 수 있습니다.
다음 단계
이제 RenderObject의 기본 개념을 이해했으니, 다음 장에서는 레이아웃의 핵심인 Constraints 시스템을 알아보겠습니다. Constraints가 어떻게 부모에서 자식으로 전달되고, 크기가 어떻게 결정되는지 자세히 살펴볼 것입니다.