
4.3 상태 관리 - 확장 가이드
개요
Flutter에서 상태 관리는 앱의 데이터와 UI 상태를 체계적으로 관리하는 핵심 개념이다12. 상태는 앱의 ‘기억’으로, 사용자 로그인 정보, 화면 전환, 폼 입력 데이터 등 시간에 따라 변화하는 모든 정보를 포함한다34. 효과적인 상태 관리는 확장성, 유지보수성, 테스트 용이성을 보장하는 핵심 요소이다15.
상태 유형 분류
상태 유형 | 특성 | 관리 방법 | 예시 |
---|---|---|---|
Ephemeral State | 지역적, 임시적63 | StatefulWidget , setState() 62 | 텍스트 필드 입력, 체크박스 상태3 |
App State | 전역적, 지속적63 | Provider, Riverpod, Bloc 등17 | 사용자 인증, 테마 설정, 장바구니3 |
주요 상태 관리 라이브러리 비교
Provider vs Riverpod vs Bloc
구분 | Provider | Riverpod | Bloc |
---|---|---|---|
학습 곡선 | 쉬움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)
Data 레이어 (Model Layer)
의존성 주입과 테스트 용이성
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();
- 모듈성: 각 레이어 간 결합도 감소
- 테스트 용이성: 목 객체(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
-
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
-
https://vibe-studio.ai/insights/state-management-in-flutter-best-practices-for-2025 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
https://www.infydots.com/flutter-state-management-complete-guide ↩ ↩2 ↩3 ↩4 ↩5
-
https://solguruz.com/blog/essential-guide-on-flutter-state-management/ ↩
-
https://www.techaheadcorp.com/blog/master-state-management-in-flutter-best-practices-and-patterns/ ↩ ↩2
-
https://docs.flutter.dev/get-started/fundamentals/state-management ↩ ↩2 ↩3 ↩4
-
https://vibe-studio.ai/insights/comparing-flutter-state-management-libraries-provider-bloc-riverpod-and-getx ↩ ↩2 ↩3 ↩4 ↩5
-
https://somniosoftware.com/blog/riverpod-vs-bloc-which-one-is-better-in-2024 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
https://tech.appunite.com/posts/a-deep-dive-into-riverpod-vs-bloc ↩ ↩2 ↩3 ↩4 ↩5
-
https://dev.to/nkusikevin/state-of-the-art-state-management-compare-popular-patterns-provider-riverpod-bloc-35b5 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
https://www.reddit.com/r/FlutterDev/comments/pjj40p/riverpod_vs_bloc/ ↩ ↩2 ↩3
-
https://www.creolestudios.com/flutter-state-management-tool-comparison/ ↩ ↩2 ↩3 ↩4 ↩5
-
https://www.f22labs.com/blogs/flutter-architecture-patterns-bloc-provider-riverpod-and-more/ ↩ ↩2 ↩3 ↩4
-
https://dev.to/sushan_dristi_ab98c07ea8f/flutter-architecture-patterns-explained-3mp3 ↩
-
https://jecklight.tistory.com/entry/MVVM-Clean-Architecture-Provider ↩ ↩2 ↩3 ↩4
-
https://dispatchersdotplayground.hashnode.dev/a-comparison-between-flutters-injectable-and-dagger-2-in-the-jvm-world ↩
-
https://www.dhiwise.com/post/exploring-flutter-tools-getit-injectable-and-autoroute ↩ ↩2
-
https://resocoder.com/2020/02/04/injectable-flutter-dart-equivalent-to-dagger-angular-dependency-injection/ ↩ ↩2