배운것들을 정리합니다.
三昧境

Flutter/tip

[플러터 Flutter] 상태관리 Provider, MultiProvider

ujo_orr 2024. 7. 9. 00:49

 

상태관리란?

애플리케이션의 상태(state)를 관리하는 것을 의미합니다.
상태는 사용자 인터페이스(UI)와 상호작용하거나 애플리케이션의 내부 동작을 관리하는 데 필요한 데이터를 나타냅니다.
상태 관리는 애플리케이션이 예측 가능한 방식으로 동작하도록 도와주며, 특히 복잡한 애플리케이션에서는 필수적인 요소입니다.

 

상태 관리의 필요성

  • UI 업데이트
    • 상태가 변경될 때 UI를 자동으로 업데이트해야 합니다.
      예를 들어, 사용자가 버튼을 클릭하면 버튼의 상태나 관련된 UI 요소가 변경될 수 있습니다.
  • 일관성 유지
    • 여러 UI 요소가 동일한 상태를 공유하는 경우 상태 변경이 일관성 있게 반영되어야 합니다.
  • 유지보수
    • 상태를 중앙에서 관리하면 코드의 유지보수와 확장이 쉬워집니다.

 

상태 관리의 종류

  • setState
    • Flutter의 내장 상태 관리 방법으로 간단한 상태 변경을 처리할 때 사용.
  • InheritedWidget
    • 데이터 및 상태를 트리 구조의 하위 위젯에 전달하는 데 사용.
  • Provider
    • InheritedWidget을 더 쉽게 사용할 수 있게 해주는 패키지.
    • 의존성 주입과 상태 관리를 간편하게 함.
    • flutter 공식 라이브러리.
  • Riverpod
    • Provider의 단점을 보완한 패키지.
    • 더 안전하고 유연한 상태 관리를 제공.
    • flutter에 의존하지 않음.
    • 컴파일 동안 안전함.
  • BLoC (Business Logic Component)
    • 비즈니스 로직을 분리하여 재사용 가능하게 만드는 패턴.
    • 스트림을 통해 상태를 관리함.
  • Redux
    • 애플리케이션의 상태를 중앙에서 관리.
    • 상태 변경을 예측 가능한 방식으로 처리하는 패턴.

 

요즘은 Provider보단 안전성과 여러 가지 장점 때문에 Riverpod을 많이 사용하는 것 같습니다.
하지만 지금은 이중에서 플러터 공식 라이브러리인 Provider에 대해서 알아보겠습니다.

 


 

 

provider install | Flutter package

A wrapper around InheritedWidget to make them easier to use and more reusable.

pub.dev

 

Provider란?

Provider 패키지는 플러터에서 사용되는 상태 관리 프레임워크 중 하나입니다.
하지만 많은 Provider를 사용할 경우, 각각의 Provider를 개별적으로 선언하면 코드가 복잡해질 수 있습니다.
이를 해결하기 위해 MultiProvider를 사용하면 여러 Provider를 한 번에 선언하고 관리할 수 있습니다.

Provider의 주요 개념

  • 의존성 주입
    • Provider는 객체를 생성하고 그 객체를 트리 구조의 하위 위젯에 주입합니다.
    • 이를 통해 위젯 트리 전체에서 객체를 사용할 수 있습니다.
  • 상태 관리
    • Provider는 상태 변화를 감지하고, 상태가 변경될 때 이를 구독하고 있는 위젯들에게 알림을 보냅니다.
    • 이를 통해 UI를 자동으로 업데이트할 수 있습니다.

 

 

왜 상태 관리 라이브러리를 사용하는가?

플러터 앱은 위젯 트리 구조로 구성되어 있습니다.
위젯 트리에서 각 위젯은 자체적인 상태를 가지고 있으며, 이 상태는 위젯의 UI를 결정하는 데 사용됩니다.
하지만 앱이 복잡해지면서 여러 위젯에서 동일한 상태를 공유해야 하는 경우가 발생하게 됩니다.
이 경우 단순히 setState()를 사용하여 상태를 변경하면 위젯 트리가 불필요하게 다시 빌드되고 코드가 복잡해지고 유지보수하기 어려워질 수 있습니다.

그렇기에 상태 관리 도구를 사용하면 앱의 전체적인 상태를 중앙 집중적으로 관리하고, 여러 위젯에서 쉽게 공유할 수 있습니다.
또한, 상태 변경에 따라 위젯 트리가 다시 빌드되는 것을 최적화하여 앱의 성능을 향상할 수 있습니다.

쉽게 말하면 상태관리 라이브러리를 구독한 위젯만 새로고침이 됩니다.

 


 

사용법

 

flutter pub add provider

위 구문을 복사하여

 

사용하고자 하는 프로젝트의 터미널에서 붙여넣어 줍니다.

사용하고자 하는 클래스에
extends나 with 를 사용하여 ChangeNotifier {} 를 상속하여 줍니다.

그리고 상태를 변경할 때 주는 notifyListeners()를 메서드 끝줄에 넣어 변경사항을 알리도록 합니다.

with와 extends의 차이점은

 

[플러터 Flutter] 객체지향(Object Oriented Programing,OOP)의 이해

객체지향 프로그래밍Object Oriented Programing의 앞글자만 따서 OOP라고 불립니다. 이는 프로그래밍 패러다임의 하나로, 데이터를 객체로 다루며, 객체의 상호작용을 통해 프로그램을 설계하는 방식

ujo-orr.tistory.com

를 참고하시면 됩니다.

runApp에서 MyApp()을 지워주고 멀티프로바이더를 [] 리스트의 형태로 설정해 준 후
하위카테고리에 MyApp()을 선언해 줍니다.

그리고 이러한 형태로 Class를 <widget>화 시켜 사용하면

이러한 형태처럼 MultiProvider를 사용하면 하나의 루트에서 관리할 수 있습니다.

 


 

Consumer

 

Consumer는 특정 데이터(클래스)에 의존하는 위젯을 감싸서, 해당 데이터가 변경될 때만 그 위젯을 리빌드 합니다.
이를 통해 불필요한 리빌드를 방지하고 성능을 최적화 할 수 있습니다.

// 기본 Consumer

Consumer<MyModel>(
  builder: (context, myModel, child) {
    return Text(myModel.someValue);
  },
);

 

멀티 프로바이더를 사용하고 싶을 때

Consumer2<FirstModel, SecondModel>(
  builder: (context, firstModel, secondModel, child) {
    return Column(
      children: [
        Text(firstModel.someValue),
        Text(secondModel.anotherValue),
      ],
    );
  },
);

 

프로바이더의 일부 값만 사용할 때

Consumer<MyModel>(
  builder: (context, myModel, child) {
    return Text(myModel.someSpecificValue);
  },
);

 

미리 정의된 위젯을 재사용할 때

Consumer<MyModel>(
  builder: (context, myModel, child) {
    return Column(
      children: [
        Text(myModel.someValue),
        child,
      ],
    );
  },
  child: RaisedButton(
    onPressed: () {
      // something
    },
    child: Text('Button'),
  ),
);

 

여기서 꺽쇠 안 <MyModel>은 속성이나 매서드를 class로 정의된 class명을 말합니다.