[Flutter] StatefulBuilder의 사용 이유(Feat.바텀시트 상태관리 에러)

임효진·2024년 3월 11일
2

Flutter

목록 보기
5/22
BottomSheet 내에서 상태가 즉각 반영되는 UIUX요청이 있어 작업하던 도중,
GetX로 상태관리를 함에도 업데이트가 되지 않는 이슈를 발견했다.

showModalBottomSheet에서 상태관리가 쉽지 않은 이유가 뭐지?

Flutter에서 showModalBottomSheet와 같은 모달 방식의 위젯을 사용할 때, 이러한 모달은 일반적으로 상태를 가지지 않는(context-free) 상태에서 생성된다.
showModalBottomSheet 함수는 현재의 위젯 트리와 독립적으로 새로운 BuildContext를 생성하여 바텀시트를 렌더링한다.
따라서 바텀시트 내부에서 발생하는 상태 변경이 바로 반영되지 않는 주된 이유는 다음과 같다:

상태 비보존:
showModalBottomSheet로 생성된 바텀시트는 기본적으로 상태가 없는(stateless) 위젯으로 간주된다.
따라서 내부 상태의 변경을 바로 UI에 반영하기 위해서는 상태를 관리하고 변경할 수 있는 메커니즘이 필요하다.

독립된 BuildContext:
바텀시트는 호출된 컨텍스트와 별개의 BuildContext를 가진다.
이는 바텀시트 내에서 발생하는 상태 변경이 바로 상위 위젯에 반영되지 않게 만든다.
상위 위젯의 상태 변경 메서드(setState)를 직접 호출할 수 없기 때문에, 내부 상태를 관리하기 위한 별도의 방법이 필요하다.

상태 관리 솔루션의 범위:
전역 상태 관리 솔루션(GetX, Provider 등)을 사용하는 경우에도, showModalBottomSheet가 생성하는 독립적인 BuildContext로 인해,
바텀시트 내에서의 상태 변경이 상위 위젯과 자동으로 동기화되지 않을 수 있다.
(나와 같은 경우다.)
이 경우, 명시적으로 상태를 업데이트하는 로직이 필요하다.

StatefulBuilder란 무엇인가

StatefulBuilder는 Flutter에서 상태를 갖는 위젯 내부에서 로컬 상태를 갱신하기 위해 사용되는 위젯이다.
주로 showModalBottomSheet, AlertDialog, SimpleDialog 등의 함수 내에서 상태 변경이 필요한 경우에 사용된다.
이러한 함수들은 상태가 없는(context-free) 환경에서 호출되며, 따라서 기본적으로 내부 상태를 변경하고 UI를 업데이트하는 기능을 제공하지 않는다.

StatefulBuilder를 사용하는 주된 이유는 다음과 같다:

로컬 상태 관리:
StatefulBuilder는 상태가 없는 위젯 내에서 간단한 상태 관리가 필요할 때 유용하다.
별도의 상태 관리 클래스를 만들지 않고도, 로컬 변수의 상태를 변경하고 그에 따른 UI 업데이트를 수행할 수 있다.

성능 최적화:
전체 앱 수준에서 상태를 관리할 필요 없이, 바텀시트나 다이얼로그와 같은 임시 UI 컴포넌트 내에서만 상태를 관리하려는 경우에 적합하다.
이는 불필요한 전역 상태 변경과 리렌더링을 방지하여 성능을 최적화할 수 있다.

구현 용이성:
상태 관리 솔루션을 도입하는 것이 비효율적이거나 과도한 경우(예: 단일 체크박스 상태 관리, 간단한 입력 폼 처리 등), StatefulBuilder를 사용하여 빠르고 간단하게 상태 관리 로직을 구현할 수 있다.

StatefulBuilder 사용 방법

showModalBottomSheet(
  context: context,
  builder: (BuildContext context) {
    // 로컬 상태 변수 선언
    bool isChecked = false;

    return StatefulBuilder(
      builder: (BuildContext context, StateSetter setState) {
        return CheckboxListTile(
          title: Text('항목 선택'),
          value: isChecked,
          onChanged: (bool? value) {
            // StatefulBuilder의 setState를 사용하여 상태 변경 및 UI 업데이트
            setState(() {
              isChecked = value!;
            });
          },
        );
      },
    );
  },
);

주의 사항 및 권장 사항

StatefulBuilder는 간단한 상태 관리에 유용하지만, 복잡한 상태 관리가 필요한 경우에는 Provider, GetX, Riverpod 등의 전역 상태 관리 솔루션을 사용하는 것이 더 적합하다고 한다(나의 경우에는 GetX로 반영이 되지 않아 혼용하여 사용하였다)
StatefulBuilder의 setState는 오직 StatefulBuilder 내부에서만 상태 변경을 유발한다.
외부 상태 변경이 필요한 경우, 콜백 함수를 통해 상위 위젯으로 이벤트를 전달하거나, 상태 관리 솔루션을 사용이 필요하다.
StatefulBuilder를 사용할 때는 성능 최적화를 고려하여, 상태 변경이 필요한 최소 범위 내에서만 사용하는 것이 좋다.
상태 변경이 빈번하게 발생하는 대규모 UI에 StatefulBuilder를 사용하면 성능 저하의 원인이 될 수 있다.

profile
핫바리임

0개의 댓글