Flutter에서 StatelessWidget과 StatefulWidget을 나누는 기준

2026. 10. 23. 09:55·Flutter
728x90

왜 이 내용을 정리하나

Flutter로 화면을 만들다 보면 위젯 클래스를 만들 때마다 StatelessWidget으로 할지 StatefulWidget으로 할지 먼저 고민하게 된다. 버튼을 누르면 숫자가 바뀌는 카운터, 체크박스 상태, 입력창에 적힌 글자처럼 화면 안에서 값이 변하는 경우에는 StatefulWidget이 필요하다. 반대로 받은 값을 그대로 화면에 그리기만 하는 경우에는 StatelessWidget으로 충분하다. 이 구분을 잘못하면 상태가 필요 없는 위젯을 괜히 복잡하게 만들거나, 반대로 값이 바뀌어도 화면이 갱신되지 않는 문제가 생긴다. 이 노트에서는 두 위젯의 차이와 나누는 기준을 정리해 본다.

개념 설명

StatelessWidget은 생성된 뒤에 자기 안에서 바뀌는 값을 갖지 않는다. build 메서드는 생성자로 받은 값만 사용해 화면을 그린다. 부모가 다시 그려지면서 새 값을 넘겨주면 그때 새로 그려질 뿐이다.

StatefulWidget은 위젯 자체와 State 객체를 분리해서 갖는다. 위젯 클래스는 설정값을 담고, 실제로 바뀌는 값은 State 클래스 안에 둔다. 값을 바꿀 때는 setState를 호출해서 Flutter에게 이 위젯을 다시 그리라고 알린다. setState 안에서 값을 바꾸지 않고 그냥 변수만 고치면 화면은 갱신되지 않는다.

기준은 간단하다. 위젯이 그리는 데 쓰는 값 중에 시간이 지나면서 위젯 내부에서 바뀌는 값이 있는지 본다. 있으면 StatefulWidget이고, 없으면 StatelessWidget이다. 값이 부모에서 내려온 것이라도 위젯이 스스로 바꾸지 않는다면 StatelessWidget이 맞다.

코드 예제

아래 예제는 같은 화면을 두 방식으로 나타낸다. 첫 번째는 카운터 숫자가 버튼을 누를 때마다 바뀌는 StatefulWidget이고, 두 번째는 받은 제목만 보여주는 StatelessWidget이다.

import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: HomePage()));
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('기준 비교')),
      body: const Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          TitleLabel(title: '방문 횟수'),
          CounterBox(),
        ],
      ),
    );
  }
}

class TitleLabel extends StatelessWidget {
  final String title;

  const TitleLabel({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    return Text(
      title,
      style: const TextStyle(fontSize: 20),
    );
  }
}

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

  @override
  State createState() => _CounterBoxState();
}

class _CounterBoxState extends State {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('$_count', style: const TextStyle(fontSize: 48)),
        ElevatedButton(
          onPressed: () {
            setState(() {
              _count++;
            });
          },
          child: const Text('눌러 보기'),
        ),
      ],
    );
  }
}

이 코드를 실행하면 화면 위쪽에 '방문 횟수'라는 제목이 보이고, 아래에는 0부터 시작하는 숫자와 버튼이 나타난다. 버튼을 누르면 _count가 1씩 증가하고 setState 덕분에 숫자만 새로 그려진다. TitleLabel은 생성자로 받은 title을 그대로 출력할 뿐이므로 StatelessWidget으로 두었다.

헷갈리는 점

가장 많이 헷갈리는 부분은 부모가 StatefulWidget이면 자식도 상태를 가져야 하는지 여부다. 자식이 값을 바꾸지 않는다면 자식은 StatelessWidget으로 두는 편이 낫다. 상태를 가진 위젯의 범위를 가능한 작게 잡으면 setState가 다시 그리는 범위도 줄어든다.

또 하나는 StatelessWidget이라도 값이 바뀌지 않는다는 뜻이 아니라는 점이다. 부모가 새 값을 넘기면 StatelessWidget은 다시 build된다. 자기 안에 저장된 상태가 없을 뿐이고, 입력이 바뀌면 화면도 바뀐다.

StatefulWidget의 initState와 dispose처럼 생명주기 메서드가 필요한 경우에도 StatefulWidget을 쓴다. 컨트롤러를 만들거나 구독을 해제하는 작업이 여기에 해당한다. 값 변화가 없어도 이런 작업이 필요하면 StatefulWidget이 맞다.

정리

위젯을 만들 때는 먼저 위젯 안에서 시간에 따라 바뀌는 값이 있는지 확인한다. 값이 있으면 StatefulWidget을 쓰고 setState로 바뀐 값을 알린다. 값이 없고 받은 값만 그리면 StatelessWidget을 쓴다. 상태는 필요한 가장 낮은 위치에 두고, 상태가 필요 없는 부분은 StatelessWidget으로 분리해 두면 코드가 읽기 쉬워지고 다시 그리는 범위도 줄어든다. 이 노트에서는 두 위젯의 차이와 나누는 기준을 정리해 보았다.

#Flutter #StatelessWidget #StatefulWidget #위젯 #setState

728x90
LIST

'Flutter' 카테고리의 다른 글

Dart 레코드를 함수 반환값으로 쓰고 구조 분해로 받아 확인하는 방법  (0) 2026.10.24
Flutter Column과 Row로 화면을 배치하는 방법  (0) 2026.10.23
Flutter 시작하기 - SDK 다운로드 및 환경 설정 가이드  (1) 2025.09.03
Riverpod 3.0 정리 – 주요 변경사항과 사용법  (0) 2025.07.20
Flutter에서 토스 복권 스크래치 복권 구현하기  (2) 2025.07.14
'Flutter' 카테고리의 다른 글
  • Dart 레코드를 함수 반환값으로 쓰고 구조 분해로 받아 확인하는 방법
  • Flutter Column과 Row로 화면을 배치하는 방법
  • Flutter 시작하기 - SDK 다운로드 및 환경 설정 가이드
  • Riverpod 3.0 정리 – 주요 변경사항과 사용법
Mr. Joo
Mr. Joo
  • Mr. Joo
    삽질의 시작
    Mr. Joo
  • 전체
    오늘
    어제
    • 분류 전체보기 (252) N
      • Python (6) N
      • 개발 요약 (10)
      • Flutter (76) N
      • Android (9)
      • Swift (8) N
      • React (15) N
      • 인공지능 (4)
      • 대학원 (3)
      • CS (10)
      • 개발 뉴스 (108)
      • IT 기기 (1)
      • 알면 유용한 정보 (2)
  • 인기 글

  • 태그

    기술 뉴스
    오늘의 뉴스
    Dart 기초
    앱 개발
    플러터
    앱
    오늘의 이슈
    개발 이슈
    오늘의 기술 뉴스
    기술
    오늘의 개발 뉴스
    개발
    Swift
    이슈
    DART
    Flutter
    개발 뉴스
    android
    뉴스
    react
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
Mr. Joo
Flutter에서 StatelessWidget과 StatefulWidget을 나누는 기준
상단으로

티스토리툴바