본문 바로가기
비전공자를 위한 Flutter/Flutter 심화과정

Flutter StatelessWidget 란? 코드 뜯어보기 (주석 한글 번역)

by 밍잔 2022. 4. 30.

Flutter에 있는 2가지 위젯 중 오늘은 StatelessWidget에 대해 알아보겠습니다. 한 줄로 요약하자면 시간이 지나도 변하지 않는 위젯입니다. 아래 동영상은 2018년에 나온 StatelessWidget을 설명하는 동영상이니 한 번 시청해보시죠.

 

[설정 > 자동번역 > 한국어]로 설정하면 자막을 볼 수 있어요.

 

한글 자막 제공

 

Widget은 element를 화면에 그리기 위한 청사진입니다. Widget 트리에 1:1 매칭된 Element 트리의 element들이 바로 우리의 휴대폰 화면에 보이는 UI입니다. StatelessWidget을 만드는 건 위젯트리에 상태변화가 없는 UI 설계도를 만드는 작업이라고 생각하시면 됩니다.

 


 

StatelessWidget의 build 메소드는 세 가지 상황에서만 호출됩니다. 


1. 위젯이 트리에 처음 삽입될 때

2. 위젯의 부모가 구성을 변경할 때 
3. InheritedWidget이 변경에 종속될 때

 

위젯의 부모가 위젯의 구성을 정기적으로 변경하거나 자주 변경되는 상속된 위젯에 의존하는 경우 화면 렌더링 성능을 유지하기 위해 [build] 메소드의 성능을 최적화하는 게 중요합니다.

 

그래서 StatelessWidget의 rebuild를 최소화할 수 있는 몇 가지 기술이 있습니다.

1. 빌드 메소드와 생성하는 위젯에 의해 자동으로 생성되는 노드의 수를 최소화하세요.
> [Row], [Column], [Padding] 및 [SizedBox] 대신 [Align] 또는 [CustomSingleChildLayout] 위젯을 사용하세요. 
> [Container], [Decoration] 대신 [CustomPaint] 위젯을 사용하세요.

2. 가능하면 const 위젯을 사용하고, const 생성자를 제공하세요.

3. StatelessWidget을 StatefulWidget으로 리팩토링해서 하위 트리 공통 부분을 캐싱하세요.

4. InheritedWidget으로 인해 자주 리빌드될 가능성이 있는 경우 StatelessWidget을 여러 위젯으로 리팩토링하세요. 


 

2가지 케이스의 StatelessWidget의 코딩 컨벤션을 보여드릴게요. 아래의 코딩 규칙에 맞춰 코딩을 하시면 됩니다.

 

첫번째 케이스

 

두번째 일반적인 케이스

 


 

StatelessWidget 관련 번역 전문을 남깁니다. 오역이 있다면 댓글로 알려주세요!

 

/// 상태가 변할 필요가 없는 위젯입니다.
///
/// StatelessWidget은 사용자 인터페이스를 보다 구체적으로 설명하는 
/// 다른 위젯의 집합을 구축하여 사용자 인터페이스의 일부를 설명하는 위젯입니다. 
/// 빌드 프로세스는 사용자 인터페이스에 대한 설명이 완전히 구체화될 때까지 반복적으로 계속됩니다
/// (예: 구체적인 [RenderObject]를 설명하는 [RenderObjectWidget]으로 완전히 구성됨).
/// 
/// StatelessWidget은 화면에 그리고 있는 UI의 일부가 [BuildContext] 이외의 
/// 다른 것에 의존하지 않을 때 유용합니다. 
/// 일부 시스템 상태에 따라, 시간에 따라 동적으로 변경되어야 하는 경우, 
/// [StatefulWidget]을 사용하세요.
///
/// ## 성능 최적화
///
/// [StatelessWidget]의 [build] 메서드는 세 가지 상황에서만 호출됩니다. 
/// 위젯이 트리에 처음 삽입될 때, 위젯의 부모가 구성을 변경할 때, 
/// 그리고 [InheritedWidget]이 변경에 종속될 때입니다.
/// 
/// 위젯의 부모가 위젯의 구성을 정기적으로 변경하거나 
/// 자주 변경되는 상속된 위젯에 의존하는 경우 
/// 화면 렌더링 성능을 유지하기 위해 [build] 메소드의 성능을 최적화하는 것이 중요합니다.
/// 
/// [StatelessWidget] 재구축의 영향을 최소화하는 데 사용할 수 있는 몇 가지 기술이 있습니다.
///
/// * 빌드 메소드와 생성하는 위젯에 의해 전이적으로 생성되는 노드의 수를 최소화합니다. 
/// 예를 들어, [Row], [Column], [Padding] 및 [SizedBox]를 정교하게 배열하여 
/// 멋진 방식으로 단일 자식을 배치하는 대신 [Align] 또는 [CustomSingleChildLayout]를 사용하세요. 
/// 여러 [Container]의 복잡한 레이어링과 [Decoration]을 사용하여 그래픽 효과를 그리는 대신 
/// [CustomPaint] 위젯을 사용하세요.
///
/// * 가능하면 `const` 위젯을 사용하고, `const` 생성자를 제공하세요.
/// 
/// * [StatelessWidget]을 [StatefulWidget]으로 리팩토링하여 
/// 트리 구조를 변경할 때 [GlobalKey]를 사용하는 것처럼 [StatefulWidget]의
/// 하위 트리 공통 부분을 캐싱하는 기술을 사용할 수 있도록 [StatefulWidget]으로 
/// 변경하는 것을 고려하십시오.
///
/// * 이 위젯이 [InheritedWidget]으로 인해 자주 다시 빌드될 가능성이 있는 경우 
/// [StatelessWidget]을 여러 위젯으로 리팩토링하세요. 
/// 예를 들어 [Theme]에 따라 마지막 위젯을 4개의 위젯의 트리로 구축하는 대신,
/// 마지막 위젯을 자체 위젯으로 구축해서 테마가 변경되면 내부 위젯만 다시 빌드시키는 거죠.
/// 
///
///  * [StatefulWidget] 과 [State]는 각각의 생명주기에 따라 다르게 빌드하기 위한 위젯입니다.
/// 
///  * [InheritedWidget], 부모 위젯에서 state를 읽을 수 있기 위한 위젯입니다.
/// 
abstract class StatelessWidget extends Widget {
  /// subclass들을 위해 [key]를 초기화 합니다.
  const StatelessWidget({ Key? key }) : super(key: key);

  /// 위젯트리에서 위젯의 위치를 관리하기 위해 [StatelessElement]를 만듭니다.
  ///
  /// subclass에서 이 메소드를 오버라이드 하는 건 좋지 않습니다.
  @override
  StatelessElement createElement() => StatelessElement(this);

  /// 이 위젯으로 유저 인터페이스를 나타내는 일부를 묘사합니다.
  ///
  /// 이 프레임워크는 이 createElement 메소드를 이 위젯이 [BuildContext]의 위젯트리 안에 삽입되었을 때 또는
  /// 이 위젯에 의존하는 위젯이 변경되었을 때 호출합니다.
  /// (예를 들면, 이 위젯이 참조하는 [InheritedWidget]이 변경되었을 때). 
  /// 이 메소드는 잠재적으로 매 프레임마다 호출될 수 있으며, 위젯을 빌드하는 것 외의 부작용은 없어야 합니다.
  ///
  /// 프레임워크는 이 메소드를 통해 서브트리의 이 위젯 아래에 있는 하위트리를 위젯으로 바꿉니다.
  /// 서브트리를 업데이트 할때, 서브트리를 삭제할 때, 서브트리를 확장할 때에도 이 메소드를 호출합니다.
  /// 이 메소드에서 반환된 위젯이 [Widget.canUpdate]를 호출하여 결정된 대로 기존 하위 트리의 루트를 업데이트할 수 있는지 여부에 따라 다릅니다.
  ///
  /// 일반적으로 이 위젯의 생성자와 지정된 [BuildContext]의 정보로 구성된 새로 생성된 위젯 집합을 반환합니다.
  ///
  /// [BuildContext]에는 이 위젯이 빌드되는 트리의 위치에 대한 정보가 포함됩니다. 
  /// 예를 들어 context는 트리의 이 위치에 대해 상속된 위젯 set를 제공합니다. 
  /// 위젯이 트리 주위로 이동되거나, 위젯이 한 번에 여러 위치에서 트리에 삽입되는 경우 
  /// 위젯은 시간이 지남에 따라 여러 개의 다른 [BuildContext]로 빌드될 수 있습니다.
  ///
  /// 이 메소드의 구현은 반드시 다음에 의존해야합니다:
  ///
  /// * 시간이 지나도 변경되지 않는 위젯의 필드
  /// * [BuildContext.dependOnInheritedWidgetOfExactType]를 통해 context에서 모든 상태 정보를 얻은 상태
  ///
  /// 만약 위젯의 [build] 메소드가 다른 것에 의존한다면 [StatefulWidget]을 사용하세요.
  ///
  ///  * [StatelessWidget], 퍼포먼스를 고려한 논의 사항을 참고해보세요.
  @protected
  Widget build(BuildContext context);
}

 

 

댓글