Stacked는 Flutter 애플리케이션에서 UI(View), 비즈니스 로직(ViewModel), 그리고 **서비스(Service)**를 분리하여 MVVM(MVVM + 의존성 주입) 구조를 구성합니다.
이로 인해 다음과 같은 이점을 얻을 수 있어요:
class HomeView extends StackedView<HomeViewModel> {
Widget builder(BuildContext context, HomeViewModel viewModel, Widget? child) {
return Scaffold(
body: Center(
child: Text(viewModel.title),
),
);
}
HomeViewModel viewModelBuilder(BuildContext context) => HomeViewModel();
}
여기서:
HomeView는 화면(UI)을 담당하는 View입니다.HomeViewModel은 상태와 로직을 담당합니다.builder는 UI를 렌더링하고 viewModelBuilder는 ViewModel을 연결합니다.View는 단순히 ViewModel이 주는 값을 받아서 화면만 구성하면 돼요. 예:
Text(viewModel.title)
ViewModel은 상태를 갖고, View에게 알려줄 뿐 View가 어떻게 렌더링되는지는 모릅니다.
→ 양방향 의존성 없이 느슨하게 연결됨.
Stacked에서 ViewModel은 notifyListeners()를 통해 View에 상태 변경을 알립니다.
→ View는 자동으로 리빌드됨.
또한 BaseViewModel에서 다음 상태들도 제공:
isBusyhasErrorhasDataService는 ViewModel에서 실제 데이터 작업을 담당합니다. 예: API 호출, 로컬 저장소 등
final _counterService = locator<CounterService>();
void incrementCounter() {
_counterService.increment();
notifyListeners();
}
→ 서비스는 ViewModel에 주입되고, ViewModel은 그 상태를 View에 전달합니다.
Stacked는 get_it을 기반으로 한 의존성 주입 컨테이너를 제공합니다.
final locator = StackedLocator.instance;
void setupLocator() {
locator.registerLazySingleton(() => CounterService());
}
이걸 통해 ViewModel, View, 서비스가 서로 독립적으로 동작할 수 있게 됩니다.
| 역할 | 설명 |
|---|---|
| View | UI 담당. ViewModel의 데이터를 UI에 표현 |
| ViewModel | 상태, 로직 처리 담당. View와 Service 중간 다리 역할 |
| Service | 외부 기능/API 수행. ViewModel에 주입됨 |
| Locator | 의존성 주입. 필요한 객체를 전역에서 관리 |
이 구조 덕분에 앱을 테스트하기 쉽고, 유지보수가 편하며, 팀 간 협업도 수월해져요.