4.3 상태 관리 - 확장 가이드

개요

Flutter에서 상태 관리는 앱의 데이터와 UI 상태를 체계적으로 관리하는 핵심 개념이다12. 상태는 앱의 ‘기억’으로, 사용자 로그인 정보, 화면 전환, 폼 입력 데이터 등 시간에 따라 변화하는 모든 정보를 포함한다34. 효과적인 상태 관리는 확장성, 유지보수성, 테스트 용이성을 보장하는 핵심 요소이다15.

상태 유형 분류

Flutter 상태는 크게 두 가지로 분류된다62:

상태 유형특성관리 방법예시
Ephemeral State지역적, 임시적63StatefulWidget, setState()62텍스트 필드 입력, 체크박스 상태3
App State전역적, 지속적63Provider, Riverpod, Bloc 등17사용자 인증, 테마 설정, 장바구니3

주요 상태 관리 라이브러리 비교

Provider vs Riverpod vs Bloc

구분ProviderRiverpodBloc
학습 곡선쉬움17중간89어려움18
보일러플레이트적음110적음811많음1110
컴파일 타임 안전성제한적912강력89강력112
의존성 주입위젯 트리 기반10전역 프로바이더910이벤트-스트림 기반813
적합한 프로젝트소-중규모17중-대규모812대규모, 엔터프라이즈18

Provider: 간편함의 대명사

Provider는 Flutter 공식 권장 상태 관리 솔루션으로, InheritedWidget을 기반으로 한다1314.

// ChangeNotifier 기반 상태 클래스
class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  
  void increment() {
    _count++;
    notifyListeners(); // UI 재빌드 트리거
  }
}
 
// 위젯에서 사용
Consumer<CounterModel>(
  builder: (context, counter, child) {
    return Text('Count: ${counter.count}');
  },
)

장점: 간단한 학습 곡선, 최소한의 보일러플레이트, Flutter 공식 지원110 단점: 런타임 에러 가능성, 위젯 트리 의존성10

Riverpod: 타입 안전성의 혁신

Riverpod은 Provider의 진화된 형태로, 컴파일 타임 안전성과 전역 프로바이더를 제공한다89.

// StateNotifier 기반 (Bloc의 Cubit과 유사)
@riverpod
class Counter extends _$Counter {
  @override
  int build() => 0;
  
  void increment() => state++;
}
 
// 위젯에서 사용
final count = ref.watch(counterProvider);
ref.read(counterProvider.notifier).increment();

장점: 컴파일 타임 안전성, BuildContext 불필요, 모듈형 구조812 단점: 상대적으로 새로운 패키지, 코드 생성 필요8

Bloc: 엔터프라이즈급 구조

Bloc은 이벤트-상태 기반의 예측 가능한 상태 관리를 제공한다113.

// 이벤트 정의
abstract class CounterEvent {}
class Increment extends CounterEvent {}
 
// Bloc 구현
class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<Increment>((event, emit) => emit(state + 1));
  }
}
 
// 위젯에서 사용
BlocBuilder<CounterBloc, int>(
  builder: (context, count) => Text('Count: $count'),
)

장점: 엄격한 아키텍처, 뛰어난 테스트 용이성, 복잡한 상태 플로우 관리113 단점: 높은 학습 곡선, 많은 보일러플레이트1110

MVVM과 Clean Architecture 통합

첨부된 문서에 따르면, Flutter 앱은 UI 레이어Data 레이어로 구분되며, MVVM 패턴을 기반으로 한다:

UI 레이어 (Presentation Layer)

  • View: 위젯 구성, 사용자 인터페이스1516
  • ViewModel: 비즈니스 로직, 상태 관리, 데이터 변환1516

Data 레이어 (Model Layer)

  • Repository: 데이터의 단일 진실 공급원(Single Source of Truth)15
  • Service: 외부 API, 로컬 저장소와의 상호작용15

의존성 주입과 테스트 용이성

GetIt + Injectable 조합은 Flutter에서 의존성 주입을 자동화한다171819:

// Injectable을 통한 자동 의존성 등록
@injectable
class UserRepository {
  final ApiService _apiService;
  UserRepository(this._apiService);
}
 
@singleton
class ApiService {}
 
// GetIt 설정
final getIt = GetIt.instance;
 
@InjectableInit()
void configureDependencies() => getIt.init();

의존성 주입의 이점1819:

  • 모듈성: 각 레이어 간 결합도 감소
  • 테스트 용이성: 목 객체(Mock) 주입 가능
  • 확장성: 새로운 구현체 교체 용이

2025년 모범 사례

하이브리드 상태 전략

지역 상태StatefulWidget으로, 전역 상태는 구조화된 라이브러리로 관리2:

// 지역 상태: UI 전용
class _FormPageState extends State<FormPage> {
  bool _isVisible = false; // 모달 표시 여부
}
 
// 전역 상태: 비즈니스 로직
@riverpod
class UserSession extends _$UserSession {
  @override
  User? build() => null;
  
  Future<void> login(String email, String password) async {
    // 인증 로직
  }
}

불변성 우선 원칙

상태 객체는 **불변(immutable)**으로 설계하여 예측 가능성을 높인다2:

@freezed
class UserState with _$UserState {
  const factory UserState({
    required bool isLoading,
    User? user,
    String? error,
  }) = _UserState;
}

성능 최적화 기법

  • Scoped Rebuilds: Consumer, Selector 활용으로 불필요한 리빌드 방지2
  • RepaintBoundary: 독립적인 렌더링 영역 설정
  • const 생성자: 컴파일 타임 최적화5

라이브러리 선택 가이드

프로젝트 특성권장 솔루션이유
소규모, 학습용Provider17간단한 API, 공식 지원
중-대규모, 타입 안전성 중시Riverpod812컴파일 타임 안전성, 모듈성
엔터프라이즈, 복잡한 상태 플로우Bloc18엄격한 아키텍처, 예측 가능성
빠른 프로토타이핑GetX7최소 보일러플레이트

핵심 권장사항: 상태 관리는 프로젝트 규모와 팀 역량에 맞게 선택해야 한다. MVVM 아키텍처의존성 주입을 통해 레이어를 분리하고, 불변 상태 패턴을 적용하여 유지보수성을 확보한다. 특히 하이브리드 전략을 통해 지역 상태와 전역 상태를 적절히 구분하여 관리하는 것이 2025년 Flutter 개발의 핵심이다.

Footnotes

  1. https://www.technaureus.com/blog-detail/state-management-in-flutter-a-comprehensive-guide 2 3 4 5 6 7 8 9 10 11 12 13 14

  2. https://vibe-studio.ai/insights/state-management-in-flutter-best-practices-for-2025 2 3 4 5 6

  3. https://www.infydots.com/flutter-state-management-complete-guide 2 3 4 5

  4. https://solguruz.com/blog/essential-guide-on-flutter-state-management/

  5. https://www.techaheadcorp.com/blog/master-state-management-in-flutter-best-practices-and-patterns/ 2

  6. https://docs.flutter.dev/get-started/fundamentals/state-management 2 3 4

  7. https://vibe-studio.ai/insights/comparing-flutter-state-management-libraries-provider-bloc-riverpod-and-getx 2 3 4 5

  8. https://somniosoftware.com/blog/riverpod-vs-bloc-which-one-is-better-in-2024 2 3 4 5 6 7 8 9 10 11 12

  9. https://tech.appunite.com/posts/a-deep-dive-into-riverpod-vs-bloc 2 3 4 5

  10. https://dev.to/nkusikevin/state-of-the-art-state-management-compare-popular-patterns-provider-riverpod-bloc-35b5 2 3 4 5 6 7

  11. https://www.reddit.com/r/FlutterDev/comments/pjj40p/riverpod_vs_bloc/ 2 3

  12. https://www.creolestudios.com/flutter-state-management-tool-comparison/ 2 3 4 5

  13. https://www.f22labs.com/blogs/flutter-architecture-patterns-bloc-provider-riverpod-and-more/ 2 3 4

  14. https://dev.to/sushan_dristi_ab98c07ea8f/flutter-architecture-patterns-explained-3mp3

  15. https://jecklight.tistory.com/entry/MVVM-Clean-Architecture-Provider 2 3 4

  16. https://dev-yongsu.tistory.com/22 2

  17. https://dispatchersdotplayground.hashnode.dev/a-comparison-between-flutters-injectable-and-dagger-2-in-the-jvm-world

  18. https://www.dhiwise.com/post/exploring-flutter-tools-getit-injectable-and-autoroute 2

  19. https://resocoder.com/2020/02/04/injectable-flutter-dart-equivalent-to-dagger-angular-dependency-injection/ 2