Service는 비즈니스 로직을 처리하는 독립적인 클래스로, ViewModel이나 View와 분리되어 있습니다.
API 호출, 로컬 저장소 접근, 인증 처리 등 다양한 로직을 Service에 분리시켜 앱을 더 구조적이고 유지보수하기 쉽게 만들어줍니다.
class CounterService {
int _counter = 0;
int get counter => _counter;
void incrementCounter() {
_counter++;
}
}
이렇게 하면 로직이 ViewModel에서 분리되어 독립적으로 관리됩니다.
서비스를 사용하려면 앱 시작 시 등록해야 합니다.
final locator = StackedLocator.instance;
void setupLocator() {
locator.registerLazySingleton(() => CounterService());
}
registerLazySingleton: 첫 호출 시 한 번만 생성setupLocator()는 main.dart에서 호출되어야 함void main() {
setupLocator();
runApp(MyApp());
}
final _counterService = locator<CounterService>();
void increase() {
_counterService.incrementCounter();
notifyListeners();
}
이제 ViewModel에서 서비스를 가져와서 사용할 수 있습니다.
상태가 자주 바뀌는 서비스(_counter 등)를 ViewModel에서 실시간 반영하고 싶을 때는 ReactiveViewModel을 사용합니다.
class HomeViewModel extends ReactiveViewModel {
final _counterService = locator<CounterService>();
List<ListenableServiceMixin> get listenableServices => [_counterService];
}
→ 이 경우, 서비스의 값이 바뀌면 ViewModel이 자동으로 감지하고 notifyListeners()를 호출합니다.
※ CounterService는 ListenableServiceMixin을 믹스인해야 합니다.
class CounterService with ListenableServiceMixin {
int _counter = 0;
int get counter => _counter;
void incrementCounter() {
_counter++;
notifyListeners(); // mixin에서 제공
}
}
locator.registerSingleton<CounterService>(FakeCounterService());
→ 기존 서비스를 Fake로 대체하여 테스트에 사용 가능
| 항목 | 설명 |
|---|---|
| Service | 비즈니스 로직 담당 클래스 |
| setupLocator | 서비스 등록 함수 |
| locator() | 서비스 인스턴스를 가져오는 함수 |
| registerLazySingleton | 호출 시 1회만 생성하여 재사용 |
| ReactiveViewModel + ListenableServiceMixin | 상태 변경 자동 감지 & UI 반영 |
| 테스트 | Mock/Fake로 서비스 대체 가능 |
setupLocator를 통해 등록하고, 전역에서 locator<>()로 사용합니다.ListenableServiceMixin을 써서 ViewModel에서 자동 감지할 수 있습니다.