본문 바로가기
Dart/Dart Programming language

[고급] Dart고급 객체지향 프로그래밍/ DI(Dependency Injection)와 서비스 로케이터 패턴

by Maccrey Coding 2024. 9. 10.
반응형

 

소프트웨어 개발에서 의존성 관리와 객체 생성은 중요한 문제입니다.

이를 효과적으로 해결하기 위해 DI(Dependency Injection)와 서비스 로케이터 패턴이 사용됩니다.

Dart에서 이 두 가지 패턴을 어떻게 구현하고 사용하는지 초보자도 이해할 수 있도록 자세히 설명하겠습니다.

1. DI(Dependency Injection)란?

DI(Dependency Injection)는 객체의 의존성을 외부에서 주입하여 객체 간의 결합도를 낮추는 방법입니다.

즉, 객체가 필요한 의존성을 스스로 생성하지 않고, 외부에서 제공받는 방식입니다. 이는 코드의 유연성, 재사용성, 테스트 용이성을 높여줍니다.

DI의 기본 개념

  1. 의존성: 객체가 다른 객체를 필요로 하는 관계를 말합니다.
  2. 주입: 의존성을 외부에서 제공받는 과정을 말합니다.
// 의존성을 가진 클래스
class UserService {
  final ApiService _apiService;

  UserService(this._apiService);

  void fetchData() {
    _apiService.getData();
  }
}

// 의존성 주입 클래스
class ApiService {
  void getData() {
    print("데이터를 가져왔습니다.");
  }
}

// 의존성을 주입하여 객체 생성
void main() {
  ApiService apiService = ApiService();
  UserService userService = UserService(apiService);

  userService.fetchData(); // 데이터 가져오기
}
  • UserService 클래스는 ApiService를 의존성으로 가집니다. ApiService의 인스턴스를 생성자에서 주입받습니다.
  • ApiService 클래스는 데이터를 가져오는 기능을 제공합니다.
  • main 함수에서 ApiService 인스턴스를 생성하고 UserService에 주입합니다. 이를 통해 UserService는 ApiService의 기능을 사용할 수 있습니다.

2. 서비스 로케이터 패턴이란?

서비스 로케이터 패턴은 객체가 필요로 하는 의존성을 제공하는 역할을 하는 로케이터 클래스를 사용하는 방법입니다.

로케이터 클래스는 필요한 서비스 객체를 반환하는 메서드를 제공합니다. 이를 통해 의존성 관리와 객체 생성의 책임을 로케이터가 맡게 됩니다.

// 서비스 로케이터
class ServiceLocator {
  static final ServiceLocator _instance = ServiceLocator._internal();
  final Map<Type, Object> _services = {};

  ServiceLocator._internal();

  factory ServiceLocator() => _instance;

  void register<T>(T service) {
    _services[T] = service;
  }

  T get<T>() {
    return _services[T] as T;
  }
}

// 서비스 정의
class ApiService {
  void getData() {
    print("데이터를 가져왔습니다.");
  }
}

class UserService {
  final ApiService _apiService;

  UserService(this._apiService);

  void fetchData() {
    _apiService.getData();
  }
}

// 서비스 로케이터를 사용하여 객체 생성
void main() {
  // 서비스 등록
  ServiceLocator().register<ApiService>(ApiService());

  // 서비스 조회 및 사용
  ApiService apiService = ServiceLocator().get<ApiService>();
  UserService userService = UserService(apiService);

  userService.fetchData(); // 데이터 가져오기
}
  • ServiceLocator 클래스는 서비스를 등록하고 조회할 수 있는 메서드를 제공합니다. register 메서드는 서비스를 등록하고, get 메서드는 등록된 서비스를 반환합니다.
  • ApiService와 UserService는 앞서 설명한 대로 정의됩니다.
  • main 함수에서는 ServiceLocator를 사용하여 ApiService를 등록하고, 이후에 이 서비스를 조회하여 UserService를 생성합니다.

3. DI와 서비스 로케이터 패턴의 비교

  • DI (Dependency Injection)
    • 의존성을 외부에서 주입받음으로써 객체 간의 결합도를 낮추고, 코드의 유연성과 테스트 용이성을 높입니다.
    • 객체 생성 시 의존성을 주입받으므로 명시적인 의존성 관리가 가능합니다.
  • 서비스 로케이터 패턴
    • 서비스 로케이터가 의존성을 제공하며, 객체는 로케이터를 통해 필요한 서비스를 요청합니다.
    • 의존성 관리가 중앙 집중화되어 있지만, 로케이터를 사용함으로써 코드의 의존성을 추적하기 어려울 수 있습니다.

DI(Dependency Injection)와 서비스 로케이터 패턴은 객체의 의존성을 관리하고 객체 생성의 책임을 분리하는 데 도움을 줍니다.

DI는 객체 간의 결합도를 낮추고 유연성을 높이며, 서비스 로케이터 패턴은 의존성을 중앙에서 관리할 수 있는 방법을 제공합니다.

두 패턴 모두 코드의 유지보수성과 확장성을 향상시킬 수 있습니다.

 

이 블로그가 Dart에서 DI와 서비스 로케이터 패턴을 이해하는 데 도움이 되었기를 바랍니다. 추가적인 질문이나 도움이 필요하시면 언제든지 말씀해 주세요!

 

구독!! 공감과 댓글은 저에게 큰 힘이 됩니다.

Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.

 

Tester Share [테스터쉐어] - Google Play 앱

Tester Share로 Google Play 앱 등록을 단순화하세요.

play.google.com

 

 

반응형