의존성 주입(Dependency Injection, DI)은 소프트웨어 디자인 패턴 중 하나로, 의존 관계를 갖는 객체 사이의 결합도를 낮추기 위해 사용됩니다. Flutter 애플리케이션에서 의존성 주입을 구현하려면 보통 get_it
과 같은 라이브러리를 사용합니다. 이번 예시에서는 get_it
을 사용하여 DI를 구현하고, injectable
이라는 패키지를 사용하여 의존성 주입을 관리하는 방법에 대해 알아보겠습니다.
1. 프로젝트 설정
먼저, Flutter 프로젝트를 생성하고 get_it
및 injectable
패키지를 추가해야 합니다. pubspec.yaml
파일에 아래와 같이 의존성을 추가합니다:
dependencies:
flutter:
sdk: flutter
get_it: ^4.0.4
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.10.4
injectable_generator: ^1.2.0
의존성을 추가한 후, pub get
명령어를 실행하여 패키지를 다운로드합니다.
2. 의존성 주입 설정
이제 의존성 주입을 설정하는 단계입니다. main.dart
파일을 열고 아래와 같이 작성합니다:
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart';
void setupInjection() {
configureInjection(Environment.prod);
}
void main() {
setupInjection();
runApp(MyApp());
}
setupInjection
함수는 의존성 주입을 설정하는 역할을 합니다. configureInjection
함수를 호출하고 환경을 Environment.prod
로 설정했습니다. Environment.prod
는 development
, staging
, production
등의 환경에 따라 의존성을 설정하는 데 사용되는 값입니다.
3. 의존성 주입 및 사용
이제 의존성 주입을 사용하여 객체를 생성하고 이를 사용하는 방법에 대해 알아보겠습니다.
먼저, 예시로 UserService
클래스를 만들어보겠습니다. services/user_service.dart
파일을 생성하고 아래의 코드를 작성합니다:
abstract class UserService {
void login(String email, String password);
}
@lazySingleton
@Injectable(as: UserService)
class UserServiceImpl implements UserService {
@override
void login(String email, String password) {
// 로그인 로직 구현
}
}
UserService
는 추상 클래스로, 다양한 프로토콜을 가진 애플리케이션의 다른 부분과의 통신을 위한 인터페이스 역할을 합니다. UserServiceImpl
은 UserService
를 구현한 클래스로 실제로 로그인 로직을 구현하고 있습니다. @lazySingleton
은 한 번 생성된 객체를 계속 사용하도록 하는 주석입니다.
다음으로, 위에서 작성한 UserService
의 의존성을 주입받아 사용하기 위해 화면에 버튼을 추가해보겠습니다. main.dart
파일을 열고 아래와 같이 수정합니다:
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart';
import 'services/user_service.dart';
void setupInjection() {
configureInjection(Environment.prod);
GetIt.instance.registerLazySingleton<UserService>(() => UserServiceImpl());
}
void main() {
setupInjection();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final UserService userService = GetIt.instance<UserService>();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dependency Injection Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Dependency Injection Example'),
),
body: Center(
child: FlatButton(
child: Text('Login'),
onPressed: () {
userService.login('example@email.com', 'password');
},
),
),
),
);
}
}
MyApp
클래스에서 UserService
의 인스턴스를 받아오기 위해 GetIt.instance<UserService>()
를 사용합니다. 버튼을 누르면 UserService
의 login
메서드가 호출되도록 구현했습니다. 이제 앱을 실행하고, 버튼을 클릭하면 UserService
의 login
메서드가 호출되는지 확인해보세요.
4. 의존성 주입 설정 파일 생성
마지막으로, injectable
패키지를 사용하여 의존성 주입 설정 파일을 생성하는 방법에 대해 알아보겠습니다.
먼저 프로젝트 루트 디렉토리에서 injection.dart
파일을 생성하고 아래와 같이 작성합니다:
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'services/user_service.dart';
final GetIt getIt = GetIt.instance;
@injectableInit
void configureInjection(String environment) => $initGetIt(getIt, environment: environment);
@module
abstract class InjectableModule {
@lazySingleton
UserService get userService => UserServiceImpl();
}
이제 프로젝트 루트 디렉토리에서 터미널을 열고 아래 명령어를 실행하여 의존성 주입 설정 파일을 생성합니다:
flutter pub run build_runner build
이 명령어는 build_runner
를 실행하여 injectable
으로 정의된 클래스들을 분석하고, 의존성 주입 설정 파일을 생성합니다. 생성된 injection.config.dart
파일에는 의존성 주입 설정이 기록됩니다. 이제 main.dart
파일에서 import 'injection.config.dart';
를 추가하여 설정 파일을 불러와 사용할 수 있습니다.
이제 예시 프로젝트에서 의존성 주입 및 Injectable
의 관계에 대한 정보를 알게 되었습니다. 이를 활용하여 본인의 플러터 프로젝트에 의존성 주입을 구현해보세요!
참고 문서: