get_it
Check out my new package watch_it the state management addon to get_it There is now a discord support channel for my packages https://discord.gg/ZHYHYCM38h
This is a simple Service Locator for Dart and Flutter projects with some additional goodies highly inspired by Splat. It can be used instead of InheritedWidget or Provider to access objects e.g. from your UI.
Typical usage:
- Accessing service objects like REST API clients or databases so that they easily can be mocked.
- Accessing View/AppModels/Managers/BLoCs from Flutter Views
“get_it”
“Check out my new package watch_it the state management addon to get_it There is now a discord support channel for my packages https://discord.gg/ZHYHYCM38h”
get_it과 함께 사용할 수 있는 watch_it이라는 새 패키지가 나왔다는 안내입니다. get_it 관련 패키지들에 대한 지원을 받을 수 있는 디스코드(Discord) 채널 주소가 제공됩니다.“This is a simple Service Locator for Dart and Flutter projects with some additional goodies highly inspired by Splat. It can be used instead of InheritedWidget or Provider to access objects e.g. from your UI.”
get_it은 Dart와 Flutter 프로젝트에서 쓸 수 있는 간단한 ‘서비스 로케이터(Service Locator)’ 라는 것을 알려줍니다. InheritedWidget이나 Provider로 UI에서 객체를 주고받았던 방식을 대체할 수 있다는 점을 강조합니다.“Typical usage:”
get_it이 주로 어떻게 쓰이는지 예시가 제시됩니다.
“Accessing service objects like REST API clients or databases so that they easily can be mocked.”
“Accessing View/AppModels/Managers/BLoCs from Flutter Views”
Service Locator:
전역적으로 필요한 객체(예: API 연동, DB 연결 등)를 한 곳에 등록해두고, 필요한 곳에서 간단히 불러서 사용하는 패턴입니다.
Splat:
get_it 제작 시 참고한 라이브러리로, 여기서는 ‘영감을 준 소스’ 정도로만 언급됩니다.
InheritedWidget / Provider 대체:
Flutter에서 보통 InheritedWidget이나 Provider를 통해 상태와 데이터를 전달하지만, get_it은 이를 전역 등록 방식으로 간소화하여 사용할 수 있게 해줍니다.
아래 예시에서는
ApiService라는 클래스 하나를 등록해두고, Flutter 앱 어디서나 쉽게 가져다 쓰는 방식을 보여줍니다.
(제공된 내용에서 보여준 “REST API 클라이언트, DB, BLoC 등”을 대신하는 예시입니다.)
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
// 1. get_it을 사용하기 위해 싱글턴 인스턴스를 선언합니다.
final getIt = GetIt.instance;
// 2. 예시로 쓸 서비스 클래스
class ApiService {
// 실제로는 서버 통신(REST API) 등을 처리하는 로직이 들어갈 수 있습니다.
void fetchData() {
print('서버에서 데이터를 가져옵니다...');
}
}
void main() {
// 3. main 함수에서 서비스 등록
// registerSingleton을 사용하면 앱 실행 내내 같은 인스턴스를 재사용합니다.
getIt.registerSingleton<ApiService>(ApiService());
// Flutter 앱 실행
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
// 간단한 예시 화면
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
HomePage({super.key});
// 4. 등록한 ApiService 가져오기
final apiService = getIt<ApiService>();
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('get_it 예시'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 버튼 누르면 fetchData 호출
apiService.fetchData();
},
child: Text('데이터 불러오기'),
),
),
);
}
}
GetIt.instance: 전역에서 사용할 get_it 인스턴스입니다. registerSingleton: 싱글턴으로 등록하여 앱 전체에서 동일 객체를 공유합니다. getIt<ApiService>(): 등록된 ApiService 인스턴스를 가져옵니다. apiService.fetchData()를 호출해 REST API나 DB 조회 등의 로직을 수행할 수 있습니다(여기서는 단순 출력).이상으로 제공된 내용에 대한 한글 번역과 간단한 코드 예시를 마칩니다.
get_it을 사용하면 서비스 로직을 한 곳에 모아두고 어디서나 편리하게 접근할 수 있어, REST API, 데이터베이스, 상태 관리 등을 깔끔하게 사용할 수 있습니다. Provider나 InheritedWidget을 꼭 써야 할 상황이 아니라면 get_it이 더 간편할 수 있습니다.아래는 제공된 영문 텍스트를 모두 빠짐없이 마크다운 인용으로 옮긴 것이며, 각 인용문 뒤에 간단한 한글 설명을 덧붙였습니다. 이후에 전체 흐름을 이해하기 쉽도록 핵심 내용을 정리하고, 초심자도 참고할 수 있는 간단한 코드 예시를 제공합니다.
Why GetIt
As your App grows, at some point you will need to put your app's logic in classes that are separated from your Widgets. Keeping your widgets from having direct dependencies makes your code better organized and easier to test and maintain. But now you need a way to access these objects from your UI code. When I came to Flutter from the .Net world, the only way to do this was the use of InheritedWidgets. I found the way to use them by wrapping them in a StatefulWidget; quite cumbersome and have problems working consistently. Also:
I missed the ability to easily switch the implementation for a mocked version without changing the UI.
The fact that you need a BuildContext to access your objects made it inaccessible from the Business layer.
Accessing an object from anywhere in an App can be done in other ways, but:
If you use a Singleton you can't easily switch the implementation out for a mock version in tests
IoC containers for Dependency Injections offer similar functionality, but with the cost of slow start-up time and less readability because you don't know where the magically injected object comes from. Most IoC libs rely on reflection they cannot be ported to Flutter.
As I was used to using the Service Locator Splat from .Net, I decided to port it to Dart. Since then, more features have been added.
위 부분은 get_it 사용 배경과 기존 방법(InheritedWidgets, Singleton, IoC 등)에서 느낀 문제점을 설명합니다.
InheritedWidgets만으로는 구현이 복잡하고, Singleton이나 기존 IoC 컨테이너는 테스트와 성능(시작 속도) 면에서 한계가 있다는 설명입니다. .Net 세계에서 쓰던 Service Locator 방식(Splat)을 Dart로 가져온 것이 get_it이라는 내용을 담고 있습니다.If you are not familiar with the concept of Service Locators, it's a way to decouple the interface (abstract base class) from a concrete implementation, and at the same time allows to access the concrete implementation from everywhere in your App over the interface. I can only highly recommend reading this classic article by Martin Fowler Inversion of Control Containers and the Dependency Injection pattern.
Service Locator 개념을 간단히 정의하며, 마틴 파울러(Martin Fowler)의 글을 참고하라고 권장하고 있습니다.
GetIt is:
Extremely fast (O(1))
Easy to learn/use
Doesn't clutter your UI tree with special Widgets to access your data like, Provider or Redux does.
get_it의 특징:
1. 매우 빠른 속도(O(1))로 객체를 가져올 수 있음
2. 사용이 쉽고 학습이 간단함
3. 특수한 위젯을 추가로 감싸지 않아도 되므로, UI 트리가 복잡해지지 않음
watch_it
GetIt isn't a state management solution! It's a locator for your objects so you need some other way to notify your UI about changes like Streams or ValueNotifiers. But together with my package watch_it, it gets a full-featured easy to use state management solution that integrates with the Objects registered in get_it.
get_it은 상태 관리 라이브러리가 아니라, 오직 객체를 전역에서 등록하고 불러오는 서비스 로케이터일 뿐이라는 점을 분명히 합니다.
Streams, ValueNotifiers 같은 방식을 사용해야 하고, watch_it 패키지를 함께 사용하면 상태 관리도 손쉽게 결합할 수 있다는 안내입니다.왜 get_it을 사용해야 하는가?
InheritedWidgets, Singleton, IoC 컨테이너 방식은 각각 복잡한 구현, 테스트의 어려움, 느린 시작 속도 등의 문제가 있었습니다. .Net에서 쓰던 Service Locator 개념을 Dart/Flutter에 맞춰 쉽게 쓸 수 있도록 만든 것이 get_it입니다.get_it의 장점
watch_it
get_it 자체는 상태를 자동으로 관찰하고 업데이트하지 않기 때문에, 추가적인 상태 관리 수단(예: Stream, ValueNotifier, 혹은 watch_it 라이브러리)을 함께 사용해야 함.여기서는 get_it의 기본 등록/사용 패턴을 짧게 보여줍니다. (상태 관리는 별도로 진행)
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
// get_it 싱글턴 인스턴스 가져오기
final getIt = GetIt.instance;
// 예시용 서비스 클래스
class ApiService {
void fetchData() {
print('데이터를 서버에서 가져오는 로직이 실행됩니다.');
}
}
void main() {
// 앱 시작 시, ApiService를 등록
getIt.registerSingleton<ApiService>(ApiService());
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
HomePage({super.key});
// 어디서든 getIt으로 등록된 ApiService를 꺼낼 수 있음
final apiService = getIt<ApiService>();
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('get_it 예시'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
apiService.fetchData();
},
child: Text('데이터 가져오기'),
),
),
);
}
}
GetIt.instance를 통해 전역에서 사용할 get_it 객체를 얻습니다. registerSingleton으로 등록해두면, 앱 전체 어디서나 getIt<타입>() 구문으로 같은 인스턴스를 가져올 수 있습니다. watch_it 등)을 적용해야 합니다.위 내용은 전체적으로 UI와 비즈니스 로직의 분리, 테스트 편의성, 빠른 속도, 간결한 구조를 장점으로 하는 get_it을 소개하고 있습니다.
get_it을 선택하는가?”에 대한 답을 기존 방법들(InheritedWidgets, Singleton, IoC)의 불편함과 비교해서 자세히 설명하고 있습니다. watch_it을 언급하며, 상태 관리도 함께 쓰면 더욱 편리할 수 있다는 점을 덧붙이고 있습니다.Getting Started
At your start-up you register all the objects you want to access later like this:
final getIt = GetIt.instance; void setup() { getIt.registerSingleton<AppModel>(AppModel()); // Alternatively you could write it if you don't like global variables GetIt.I.registerSingleton<AppModel>(AppModel()); }After that you can access your AppModel class from anywhere like this:
MaterialButton( child: Text("Update"), onPressed: getIt<AppModel>().update // given that your AppModel has a method update ),You can find here a detailed blog post on how to use GetIt
Getting Started
get_it을 시작하는 방법을 안내하는 제목입니다.“At your start-up you register all the objects you want to access later like this:”
AppModel)를 등록하는 과정을 보여줍니다.final getIt = GetIt.instance;
void setup() {
// AppModel을 싱글턴(Singleton)으로 등록
getIt.registerSingleton<AppModel>(AppModel());
// 전역 변수를 쓰기 싫다면 GetIt.I를 활용해도 동일
GetIt.I.registerSingleton<AppModel>(AppModel());
}
final getIt = GetIt.instance;getIt 인스턴스를 가져옵니다. registerSingleton<AppModel>(AppModel());AppModel을 싱글턴 객체로 등록하여, 앱 전체 어디에서나 동일한 AppModel 인스턴스를 재사용할 수 있게 해줍니다.“After that you can access your AppModel class from anywhere like this:”
AppModel을 어디서든 간단히 가져와 사용할 수 있습니다.MaterialButton(
child: Text("Update"),
onPressed: getIt<AppModel>().update // AppModel에 update 메서드가 있다고 가정
),
getIt<AppModel>() : 등록해둔 AppModel 인스턴스를 가져옵니다. onPressed: getIt<AppModel>().update : 버튼을 누르면 AppModel의 update 메서드를 호출합니다.“You can find here a detailed blog post on how to use GetIt”
AppModel:update라는 메서드를 가진 클래스라고 생각하면 됩니다. 보통 앱 내의 데이터를 관리하거나, 비즈니스 로직을 처리하는 클래스가 될 수 있습니다.setup() 함수:setup()을 호출해 등록 작업을 해두면, 다른 곳에서는 단순히 getIt<AppModel>()로 가져다 쓰면 됩니다.아래는
AppModel클래스를 간단히 만들어, 버튼 클릭 시update()메서드를 호출하는 예시입니다.
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
// 1) get_it 인스턴스 생성 (전역)
final getIt = GetIt.instance;
// 2) 예시로 사용할 AppModel
class AppModel {
// 예: 내부 카운트를 관리
int counter = 0;
void update() {
counter++;
print('AppModel의 counter가 $counter 로 업데이트되었습니다.');
}
}
void main() {
// 3) 앱 시작 시 설정 함수 호출
setup();
runApp(const MyApp());
}
void setup() {
// AppModel을 싱글턴으로 등록
getIt.registerSingleton<AppModel>(AppModel());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
HomePage({super.key});
// 등록된 AppModel 가져오기
final appModel = getIt<AppModel>();
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('get_it 예시'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 버튼 클릭 시 AppModel의 update() 메서드 호출
appModel.update();
},
child: Text('Update'),
),
),
);
}
}
getIt.registerSingleton<AppModel>(AppModel()) AppModel 인스턴스만 사용하게 해줍니다.onPressed: appModel.update() AppModel에 정의된 메서드를 직접 호출하여 카운트를 증가시키고, 콘솔에 메시지를 출력합니다.Provider 위젯이나 InheritedWidget을 감싸지 않아도 getIt<AppModel>()로 동일 인스턴스를 활용 가능하다는 점이 편리합니다.위 내용이 get_it을 시작할 때 필요한 기본적인 설정과 객체 등록 및 사용 방법을 간단히 보여줍니다.