dependency injection

μ•±μ—μ„œμ˜ μ˜μ‘΄μ„± μ£Όμž…

사싀 μ—¬κΈ°μ„œ μ˜μ‘΄μ„± μ£Όμž…μ΄λΌλŠ” 단어λ₯Ό 써도 될지 개인적으둜 μ• λ§€ν•˜λ‹€λŠ” 생각은 λ“ λ‹€. μ™œλƒν•˜λ©΄ μ˜μ‘΄μ„± μ£Όμž…μ€ μ‚¬μš©ν•˜λŠ” μͺ½μ—μ„œ ν•„μš”ν•œ 것을 μƒμ„±ν•˜μ—¬ μ‚¬μš©ν•˜λ„λ‘ ν•˜λŠ” 것이 μ•„λ‹ˆλΌ λ°›μ€λŒ€λ‘œ μ‚¬μš©ν•˜κ²Œ λ˜λŠ” 'μ œμ–΄μ˜ μ—­μ „' μ΄λΌλŠ” ν˜„μƒμ„ λ°œμƒμ‹œν‚€λŠ” ν–‰μœ„λΌκ³  μƒκ°ν•œλ‹€. 그리고 이 ν–‰μœ„μ˜ μ „μ œλŠ” μΆ”μƒν™”λœ μΈν„°νŽ˜μ΄μŠ€ μ•„λž˜μ—μ„œ μ—¬λŸ¬ κ΅¬ν˜„μ²΄κ°€ κ²½μš°μ— 따라 λ‹€λ₯Έ κ΅¬ν˜„μ²΄κ°€ ν•„μš”ν•œ μƒν™©μ΄λΌλŠ” 것이닀.

λ¬Όλ‘  이것 외에도 νš¨μœ¨μ„± μΈ‘λ©΄μ—μ„œ 두 개 μ΄μƒμ˜ 객체가 ν•„μš” 없기에 싱글톀 으둜 ν•˜λ‚˜λ§Œ λ§Œλ“€μ–΄λ†“κ³  계속 μž¬μ‚¬μš©μ„ ν•œλ‹€λŠ” κ²½μ œμ„± 츑면도 있긴 ν•˜μ§€λ§Œ, μŠ€ν”„λ§μ—μ„œμ˜ μ˜μ‘΄μ„± μ£Όμž…μ€ μ œμ–΄μ˜ 역전을 ν†΅ν•΄μ„œ ν…ŒμŠ€νŠΈλ„ μš©μ΄ν•˜κ³  섀계상 더 μœ μ—°ν•œ 섀계(κ°μ²΄κ°„μ˜ μœ μ—°ν•œ ν˜‘λ ₯ ꡬ쑰)λ₯Ό λ‹¬μ„±ν•˜κΈ° μœ„ν•¨μΈ 츑면이 더 큰 것 κ°™λ‹€.

그런데 μ•±μ—μ„œμ˜ μ˜μ‘΄μ„± μ£Όμž…μ€ 사싀 μ‹±κΈ€ν†€μœΌλ‘œ λ§Œλ“€μ–΄μ§„ ν•˜λ‚˜μ˜ 객체에 λŒ€ν•œ μˆ˜μ›”ν•œ μ‚¬μš©μ΄ κ°€μž₯ 큰 μ‚¬μš© λͺ©μ μΈ 것 κ°™μ•„μ„œ 사싀 이걸 μ˜μ‘΄μ„± μ£Όμž…μ΄λΌκ³  ν‘œν˜„ν•˜κΈ° λ³΄λ‹€λŠ” 'λˆ„κ΅¬λ‚˜ μ ‘κ·Όν•˜κΈ° μ‰¬μš΄ μ΅œμƒλ‹¨ μœ„μ ―' μ΄λΌλŠ” ν‘œν˜„μ΄ μ μ ˆν•˜μ§€ μ•Šμ„κΉŒ μ‹Άλ‹€.

μ˜μ‘΄μ„± μ£Όμž…μ„ μ‰½κ²Œ ν•  수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” νŒ¨ν‚€μ§€μ΄λ‹€.

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

InheritedWidget κ³Ό Provider λͺ¨λ‘ 핡심 μ›λ¦¬λŠ” context 참쑰둜 μœ„μ ―νŠΈλ¦¬λ₯Ό νƒμƒ‰ν•˜μ—¬ μ­‰ μ˜¬λΌκ°€μ„œ μ›ν•˜λŠ” μœ„μ ―μ— access ν•˜λŠ” 것이며 get_it μ—­μ‹œ λΉ„μŠ·ν•œ μ›λ¦¬λ‘œ λ§Œλ“€μ–΄μ Έ μžˆλ‹€. 곡식 λ¬Έμ„œλ₯Ό 보면 μ•„λž˜μ™€ 같이 μžλž‘ν•˜κ³  μžˆλ‹€.

  • 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.

ν™•μ‹€νžˆ Provider λ³΄λ‹€λŠ” μ°Έμ‘°ν•˜λŠ” μ½”λ“œκ°€ 쑰금 더 κ°„κ²°ν•˜λ‹€κ³  λŠκΌˆλ‹€.

get_it 을 μ΄μš©ν•œ μ˜μ‘΄μ„± μ£Όμž… κ΅¬ν˜„

νŒ¨ν‚€μ§€λ₯Ό 일단 μ„€μΉ˜ν•œλ‹€.

flutter pub add get_it

κΈ€λ‘œλ²Œν•˜κ²Œ μ°Έμ‘°λ˜μ–΄ μ‚¬μš©λ˜λ―€λ‘œ dependency_injection은 application layer 에 μœ„μΉ˜ν•œλ‹€.

import 'package:device_info_plus/device_info_plus.dart';
import 'package:get_it/get_it.dart';

class Injector {
  Injector._();

  static DeviceInfoPlugin get deviceInfoPlugin =>
      GetIt.instance.get<DeviceInfoPlugin>();

  static Future registerDependencies() async {
    _registerUtils();
    _registerNetworks();
    _registerRepositories();
  }

  static _registerUtils() async {
    GetIt.instance
        .registerLazySingleton<DeviceInfoPlugin>(() => DeviceInfoPlugin());
  }

  static _registerNetworks() async {}

  static _registerRepositories() async {}
}
  1. κΈ°λ³Έ μƒμ„±μžλ₯Ό private μ²˜λ¦¬ν•΄μ„œ μ™ΈλΆ€μ—μ„œ Injector λ₯Ό μƒμ„±ν•˜μ§€ λͺ»ν•˜κ²Œ ν–ˆλ‹€.

  2. registerDependencies() ν•¨μˆ˜ λ‚΄μ—μ„œ μš©λ„λ³„λ‘œ κ΅¬λΆ„λœ λ©”μ†Œλ“œλ₯Ό λ‹€μ‹œ ν˜ΈμΆœν•˜κ²Œ ν•΄μ„œ μ½”λ“œ 가독성을 λ†’ν˜”λ‹€. λ‹¨μˆœνžˆ λ‚˜μ—΄μ‹μœΌλ‘œ ν•„μš”ν•œκ±Έ μ­‰ λ“±λ‘ν•˜λŠ”κ²Œ μ•„λ‹ˆλΌ μ–΄λ–€ λ””νŽœλ˜μ‹œκ°€ 무슨 μš©λ„μΈμ§€λ₯Ό μ‰½κ²Œ νŒŒμ•…ν•˜κ²Œ ν–ˆλ‹€λŠ” μ˜λ―Έμ΄λ‹€.

  3. getter λ₯Ό μ„ μ–Έν•΄μ€˜μ•Ό λ‹€λ₯Έ μœ„μ ―μ—μ„œ μ°Έμ‘° ν•  수 μžˆλ‹€.

  4. μœ„ μ½”λ“œλŠ” λ ˆμ΄μ§€λ‘œλ”© λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ ν•œ 것인데 λ ˆμ΄μ§€ν•˜μ§€ μ•Šκ²Œ λ°”λ‘œ μ¦‰μ‹œ λ“±λ‘μ‹œν‚€λŠ” 방법도 μžˆλ‹€. 곡식 λ¬Έμ„œμ— μžμ„Ένžˆ λ‚˜μ™€μžˆκ³  정리할 κ°€μΉ˜κ°€ μžˆμ„ 만큼 λ³΅μž‘ν•˜μ§„ μ•Šμ•„μ„œ μƒλž΅ν•œλ‹€.

  5. 일단 μƒ˜ν”Œ κ΅¬ν˜„μ„ μœ„ν•΄μ„œ μ–΄λ–€ ν”„λ‘œμ νŠΈλ“  λ‚΄κ°€ μ“Έ κ²ƒμœΌλ‘œ μ˜ˆμƒλ˜λŠ” device_info_plusλ₯Ό λ“±λ‘ν–ˆλ‹€.

  run() async {
    await Injector.registerDependencies();
    runApp(const AppName());
  }

environment μ—μ„œ κ΅¬ν˜„ν–ˆλ˜ run() ν•¨μˆ˜μ—μ„œ runApp() 을 ν•˜κΈ° 전에 μœ„μ™€ 같이 μ²˜λ¦¬ν•΄μ€€λ‹€. μ € μ‹œμ μ— νƒ€μž…μ„ 기반으둜 객체λ₯Ό 생성 및 생성 μ€€λΉ„(μ•„λ§ˆλ„ ν”„λ‘μ‹œ νŒ¨ν„΄μœΌλ‘œ 일단 등둝을 해놓고 λ‚΄λΆ€ μ°Έμ‘° λ³€μˆ˜λ₯Ό λΉ„μ›Œλ’€λ‹€κ°€ 졜초 μ°Έμ‘°μ‹œ λ©”λͺ¨λ¦¬μ— ν• λ‹Ήν•΄μ£ΌλŠ” 방식일 것 같은데 더 λ“€μ—¬λ‹€ 보진 μ•Šμ•˜λ‹€)을 해놓을 κ²ƒμœΌλ‘œ 생각 λœλ‹€.(get_it 의 λ‚΄λΆ€ ꡬ동 원리가 μ΄κ²ƒμœΌλ‘œ μΆ”μΈ‘λ˜λŠ”λ° ν•™μŠ΅μ˜ κ°€μ„±λΉ„λ₯Ό μœ„ν•΄ μ—¬κΈ°μ„œ 일단 ν˜ΈκΈ°μ‹¬μ„ λŠλŠ”λ‹€.)

  Future<void> _showPlatformInfo() async {
    final DeviceInfoPlugin deviceInfoPlugin = Injector.deviceInfoPlugin;
    if (Platform.isAndroid) {
      final AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo;
      print(androidInfo.toString());
    }

    if (Platform.isIOS) {
      final IosDeviceInfo iosDeviceInfo = await deviceInfoPlugin.iosInfo;
      print(iosDeviceInfo.toString());
    }
  }

μ‚¬μš©μ€ μœ„μ™€ 같이 μ„ μ–Έν•΄λ‘” getter λ₯Ό ν†΅ν•΄μ„œ access ν•΄μ„œ μ‚¬μš©ν•œλ‹€.

Last updated