(Flutter-기초 강의) 6.StatelessWidget & StatefulWidget, Scaffold 란 무엇인가?

오늘은 Flutter 프로젝트의 가장 기본이 되는 Widget들인 StatelessWidget & StatefulWidget과 Scaffold에 대해 소개하도록 하겠습니다.

Widget 이란?

Flutter에서 Widget은 화면의 모든 요소를 나타내는 기본 단위입니다. 텍스트, 이미지, 버튼, 레이아웃 등 모든 UI 요소는 Widget으로 표현됩니다.

Flutter의 Widget은 계층 구조로 구성됩니다.
가장 상위 Widget은 MaterialApp 위젯이며, 이 위젯 아래에 다른 Widget들이 계층 구조로 배치됩니다.

Widget은 다수의 서브트리를 동시에 구성할 수 있는 불변 객체입니다.
Widget이 트리에 배치될 때마다 Element로 instance화 되므로 Element는 특정 트리 위치에서 Widget을 대표한다고 볼 수 있습니다.

Widget Tree

Flutter의 위젯 트리는 Flutter 애플리케이션에서 사용자 인터페이스를 구축하기 위한 계층적 구조입니다.

이 구조는 여러 위젯들의 배열과 관계를 나타내며, 각 위젯은 UI의 기본 구성 단위로 동작합니다. 위젯 트리는 복잡한 UI 디자인을 중첩과 조합을 통해 가능하게 하며, UI 요소들의 렌더링과 상태 관리를 효율적으로 관리합니다.

이 트리 구조는 각 위젯이 전체 UI 레이아웃에서 자신의 역할과 위치를 알 수 있도록 도와줍니다.

Official Document (UI)

widget-tree-in-flutter

Widget 분류

Flutter에서는 다양한 Widget들이 존재하는데 크게 StatelessWidget과 StatefulWidget으로 나뉩니다.

Flutter의 가장 기본이 되는 Layout 위젯인 Scaffold 까지 소개하고자 합니다.

StatelessWidget 이란?

개요

StatelessWidget상태가 없는 위젯입니다.

이는 위젯의 생성 시점에 모든 구성이 결정되며, 데이터 변경에 따라 다시 Rendering 되지 않습니다.

간단히 말해, 어떤 입력에 의해서 특정 상태(값)이 변경되지 않는 Widget을 의미합니다.

공식문서(StatelessWidget)

statelesswidget

특징

  • 성능이 좋습니다. 데이터가 변경되지 않기 때문에 리소스를 적게 사용합니다.
  • build() 메소드는 위젯 생성 시 한 번만 호출됩니다.

사용예

정적인 데이터를 표시할 때 사용합니다.

Ex) Text Label, Icon, Image와 같이 앱이 실행되는 동안 변경되지 않는 UI 요소에 적합합니다.

예제코드

build() 메서드에서, ‘StatelessWidget Example’이라는 텍스트를 중앙에 표시하고 별도의 상태 변화를 제공하지 않습니다.

class MyStatelessWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('StatelessWidget Example'),
    );
  }
}

결과

StatefulWidget 이란?

개요

StatefulWidget상태가 있는 위젯입니다.

이는 동적 데이터를 관리하고, 데이터가 변경될 때마다 UI가 업데이트될 수 있습니다.

공식문서(StatefulWidget)

특징

  • 동적인 상호작용을 지원합니다.
  • State 객체를 통해 상태 관리가 이루어지며, setState 메소드를 호출하면 build 메소드가 다시 실행되어 UI가 업데이트됩니다.
StatefulWidget

사용예

사용자 상호작용이나 데이터 변경에 응답하여 UI를 업데이트해야 할 때 사용합니다.

예를 들어, 폼 필드, 체크 박스, 혹은 사용자 인터랙션이 있는 모든 요소에 사용됩니다.

예제코드

다음 예제에서는 text라는 상태값이 버튼을 눌렀을 때, setState() 메소드 안에서 text 값이 변경 되고,
해당 상태가 업데이트 되어 Rendering 됩니다.

import 'package:flutter/material.dart';

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

  @override
  _MyStatefulPageState createState() => _MyStatefulPageState();
}

class _MyStatefulPageState extends State<MyStatefulPage> {
  String text = 'StatefulWidget Example';

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            text,
            textAlign: TextAlign.center,
            style: const TextStyle(fontSize: 30),
          ),
          ElevatedButton(
            onPressed: () {
              setState(() {
                text = 'State is Changed!';
              });
            },
            child: const Text('Button'),
          ),
        ],
      ),
    );
  }
}

결과

Statefulwidget_example

Scaffold 란?

개요

Scaffold는 기본적인 Material Deisgn Layout 구조를 구현하는 데 사용됩니다.

Scaffold 위젯은 앱의 기본 구조를 제공하며, 여러 Child Widget들과 함께 사용될 수 있는 빌딩 블록입니다.

기능

  • AppBar: 페이지의 상단에 표시되는 앱 바를 제공합니다. 앱 바에는 애플리케이션의 제목, 탐색 버튼, 상태 표시줄 등이 포함될 수 있습니다.
  • body: 페이지의 본문 콘텐츠를 제공합니다. 텍스트, 이미지, 버튼, 레이아웃 등 다양한 위젯을 사용하여 구성할 수 있습니다.
  • floatingActionButton: 페이지의 하단에 표시되는 플로팅 버튼을 제공합니다. 플로팅 버튼은 일반적으로 주요 기능을 수행하는 데 사용됩니다.

속성

속성설명
AppBar화면 상단에 위치하며 앱의 타이틀, 액션 아이템, 오버플로우 메뉴 등을 포함할 수 있습니다.
Body앱의 주요 콘텐츠가 표시되는 부분으로, 다양한 위젯들을 이곳에 배치할 수 있습니다.
FloatingActionButton화면에 부동하는 버튼으로, 일반적으로 액션을 유도하는 메인 기능에 사용됩니다.
BottomNavigationBar화면 하단에 위치하는 네비게이션 바로, 여러 탭으로 구성될 수 있습니다.
Drawer화면의 옆에서 슬라이드하여 나오는 메뉴로, 네비게이션 링크나 옵션을 포함할 수 있습니다
SnackBar간단한 메시지를 잠깐 동안 보여주는데 사용되며, 화면 하단에 일시적으로 표시됩니다.
BottomSheet화면 하단에서 올라오는 패널로, 추가 정보나 입력 폼을 제공할 수 있습니다.

예제

이 코드는 간단한 Flutter 애플리케이션의 Scaffold 예제입니다.
AppBar에는 애플리케이션의 제목이 표시되고, body에는 각 종 주요 표시 Widget들이 표시되고
floatingActionButton에는 Floating Button으로 Action을 할수 있는 버튼이 표시됩니다.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
결과

참고 링크

Leave a Comment