[Flutter]StatelessWidget & StatefulWidget

한상욱·2024년 8월 20일
0

Flutter

목록 보기
16/26
post-thumbnail

들어가며

Flutter에서 UI의 대부분은 위젯으로 이루어져 있습니다. Flutter의 위젯에 대해서 알아보도록 하겠습니다.

위젯

Flutter에서는 UI를 구성하는 가장 기본 단위를 위젯이라고 합니다. 공식문서에서는 위젯을 아래와 같이 소개합니다.

"Flutter emphasizes widgets as a unit of composition. Widgets are the building blocks of a Flutter app's user interface, and each widget is an immutable declaration of part of the user interface."

위젯은 UI에서 빌딩 블록이며, 각 위젯은 UI 일부에 대한 불변선언이라는 소개인데요. 무슨의미일까요?
아래와 같은 UI를 보도록 하겠습니다.

이 화면은 단순하게 가운데에 Hello World! 라는 글자를 보여주는 예시용 UI이지만, 코드로는 아래와 같이 표현됩니다.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text("Hello World!"),
        ),
      ),
    );
  }
}

Hello World! 라는 글자를 위해 MaterialApp, Scaffold, Center, Text 위젯이 계층형으로 선언되어 있습니다. VSC에서 현재 나의 프로젝트의 계층 구조를 볼 수도 있습니다.

이처럼 Flutter는 인스턴스로 선언된 모든 위젯을 계층형으로 관리합니다. 왜 이렇게 계층적으로 구성될까요?? 사용자가 앱을 사용하면서 특정 이벤트를 통해 UI가 변경될 수 있습니다. 이렇게 계층화된 구조에서 변경될 부분의 위젯 인스턴스를 다른 위젯으로 변경한다면 효율적으로 UI를 업데이트 할 수 있을 것입니다.

그렇습니다. 효율적으로 UI를 갱신하기 위해서 이러한 계층 구조를 사용하는 것입니다. 즉, Flutter는 UI를 이러한 위젯들의 모음으로 표현하고, 계층적으로 구성되므로 빌딩 블록이라고 하는 것이라고 이해할 수 있겠습니다.

위젯 구성

UI를 갱신하기 위해서는 위젯을 재빌드한다고 하였습니다. 각 위젯은 build()라는 메소드를 재정의하는 방식으로 개발자가 UI를 선언할 수 있습니다.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text("Hello World!"),
        ),
      ),
    );
  }
}

MyApp은 runApp()메소드에서 직접 실행하게 되는 인스턴스이지만, 결국 위젯이라고 할 수 있습니다. 이 위젯은 오버라이딩된 build() 메소드를 재정의하여 UI를 선언하였습니다. 이 메소드는 하위 위젯에 따라서 여러개가 존재할 수 있겠죠. 그래서 Flutter는 하위 위젯에 build()를 계속 재귀적으로 호출하여 UI를 랜더링하기 위해서 필요한 모든 요소를 빌드합니다. 그리고 이 객체들을 객체 트리로 묶게 되죠.

UI갱신에서도 해당 build() 메소드를 호출하며 UI를 갱신하는 것입니다. build()메소드는 굉장히 중요한 역할을 맡았네요. 그렇기에 빠르게 실행될 수 있어야 할 것입니다. 이를 위하여 Stateless Widget, Stateful Widget의 개념이 등장했습니다.

Stateless Widget & Stateful Widget

맨 처음에 봤던 예시용 UI(Hello World!)는 단순하게 사용자에게 Text를 보여주는 화면입니다. 이러한 화면은 사용자에 어떠한 상호작용에도 Hello World!라는 글자를 보여줄 뿐입니다. 이러한 경우 Stateless Widget으로 위젯을 표현할 수 있습니다.

하지만 사용자에 상호작용으로 인해 UI가 변경되어야만 하는 부분도 존재합니다. 이러한 경우 Flutter에서는 위젯에 상태를 부여하며 해당 위젯을 갱신할 수 있는데, 이러한 위젯을 Stateful Widget이라고 합니다. 이 위젯 자체에서는 build()메소드를 실행할 수 없습니다.

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

대신, State에서 build()메소드를 재정의하여 UI를 선언할 수 있습니다. Stateful Widget은 setState 메소드를 이용하여 상태를 갱신합니다. Flutter create를 통해서 생성되는 예제앱은 이러한 상태갱신을 확인할 수 있는 좋은 예입니다.

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});


  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
	// 바로 이부분
    // 카운터의 증가를 State에게 전달
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
		...

State를 통해 갱신되는 UI, 즉, StatefulWidget은 자식 위젯의 새 인스턴스를 생성할 수 있습니다.

profile
자기주도적, 지속 성장하는 모바일앱 개발자가 되기 위해

0개의 댓글