[flutter] get_it

향신료·2024년 1월 4일
1
post-thumbnail

get_it

의존성 주입(DI)를 위한 라이브러리로, 객체 간의 의존성을 간단하게 해결할 수 있습니다.

의존성 주입 특유의 장점을 통해 코드 재사용과 테스트를 원활하게 진행할 수 있습니다.



제공 의존성 유형

Singleton, Factory, Lazy Singleton 3가지의 유형을 지원합니다.

  • Singleton : 하나의 객체만 생성, 객체를 최초 한 번만 생성하고 이후에 호출마다 동일한 객체를 사용합니다.
  • Factory: 객체를 생성하는 팩토리 함수를 제공합니다, 의존성 주입할 때마다 새로운 객체를 생성합니다.
  • Lazy Singleton : Singleton과 같지만, 객체를 필요할 때까지 생성하지 않고 첫 객체 호출 시에 생성합니다.
    • Singleton의 경우 의존성 등록 시 생성합니다.




📍의존성 주입(DI)이 뭐죠?

디자인 패턴 중 하나로, 클래스나 모듈 간의 의존성을 외부에서 주입하는 것을 의미합니다.

이때 의존성이란, 하나의 객체가 다른 객체의 의존하여 동작하는 것을 이야기합니다.


  • 예시 코드

아래 코드에서 예를 들면 Person 객체는 Mouth 객체에 의존합니다, 이때 생성자를 통해 의존성을 주입해 주고 있습니다.

 class Mouth {
      void eat() {
        print('yummy');
      }
    }
    
    // Person 클래스는 Mouth에 의존하며 생성자 주입.
    class Person {
      final Mouth mouth;
    
      // 생성자 주입을 통해 Mouth 객체를 받음
      Person(this.mouth);
    
      void hungry() {
        mouth.eat();
        print('Person is hungry');
      }
    }



더 쉽게 이야기하면 배가 고파 밥을 먹으려 한다면, 밥이 있어야겠죠? 하지만 밥을 만드려면 시간이 오래 걸리고 요리를 못한다면 아무것도 먹지 못할 수 있습니다.


이때 밥을 직접 만들지 않고 레트로트 식품을 먹거나 배달을 시키면 요리를 못하더라도 확정적으로 맛있는 밥을 먹을 수 있게 됩니다.


의존성 주입은 이와 비슷합니다. 의존성 주입을 사용하면 객체가 스스로 의존성을 생성하지 않고, 이미 만들어진 의존성을 사용하기 때문에 서로 덜 의존하게 됩니다. 한 객체의 변경이 다른 객체에 미치는 영향이 줄어 코드가 더 유연하고 분리되어 테스트하기에도 쉬워집니다.







get_it 패키지 사용법



패키지 가져오기


dependencies:
  flutter:
    sdk: flutter
  get_it: ^x.x.x  # x.x.x는 패키지 버전입니다.

pubspec.yaml 파일에 get_it 패키지를 추가한 후 flutter pub get 명령를 통해 패키지를 가져옵니다.



객체 생성 및 등록하기


공유 대상의 객체를 준비합니다, 저는 3가지 유형의 의존성 주입 제공 방안들을 사용하기 위해 아래와 같은 Model들을 사용할 예정입니다.



Singleton 유형에 사용할 모델.

class Mouth {
  Mouth(){
    print('Mouth가 생성되었습니다.');
  }

  void eat() {
    print('yummy');
  }
}

Lazy Singleton 유형에 사용할 모델.

class Person {
  late Mouth mouth;

  Person(){
		// 해당 Mouth는 Person 이전에 GetIt에 등록이 되어있어야만 합니다.
		// 이러한 형태로 생성자내에서 객체를 가져와 적용하는 것 또한 가능합니다.
    mouth = GetIt.I<Mouth>();
    print('Person이 생성되었습니다.');
  }

  void hungry() {
    print('Person is hungry');
    mouth.eat();
  }
}

Factory 유형에 사용할 모델.

class Group{
  String name;
  int id;

  Group({required this.name,required this.id}){
    print('새 그룹 생성');
  }
}



객체 등록

class GetItLocator{
  static GetItLocator locator = GetItLocator();

  // GetIt 싱긆톤 형식.
  void setupSingleton() {
    if(!GetIt.instance.isRegistered<Mouth>()){
      GetIt.instance.registerSingleton(Mouth());
    }
  }

  // GetIt 팩토리 형식.
  void setUpFactory(){
    if(!GetIt.instance.isRegistered<Group>()){
			// registerFactory의 경우 FactoryFunc 형태로 되어 있어 () => 반환객체를 매개변수로 넘겨야합니다.
      GetIt.instance.registerFactory<User>(()=> Group(name: 'get_it', id: 99));
    }
  }

  // GetIt lazy 싱글톤 형식.
  void setUpLazySingleton(){
    if(!GetIt.instance.isRegistered<Person>()){
      GetIt.instance.registerLazySingleton(() => Person());
    }
  }
}

본 예시의 경우 runApp 이후 GetIt을 통해 적용하므로 중복 등록의 문제 GetIt.instance.isRegistered 을 통해 등록이 되어있는지를 확인 후 등록하도록 적용된 코드입니다.


➕ 이때 GetIt.instance의 경우 코드를 줄인 GetIt.I 로도 호출이 가능합니다.





Singleton 유형


GetItLocator.locator.setupSingleton();

// 첫 객체 생성
Mouth mouth1 = GetIt.I<Mouth>();

// 두 번째 객체 생성
Mouth mouth2 = GetIt.I<Mouth>();

// mouth1과 mouth2는 같은 객체인지 확인
print(mouth1 == mouth2); // true

싱글톤으로 적용한 객체를 2번 가져와 비교하면 처음 요청될 때 객체를 생성하고, 그 이후에는 항상 같은 객체를 반환합니다.


코드 진행 후 터미널을 살펴본다면 생성자 문구가 한 번만 진행되었음을 통해 위 사실을 확인할 수 있습니다.



Factory 유형


GetItLocator.locator.setUpFactory();

// 첫 객체 생성
Group group1 = GetIt.I<Group>();
// 생성자를 통해 객체 생성 print가 진행됩니다.

// 두 번째 객체 생성
Group group2 = GetIt.I<Group>();
// 생성자를 통해 객체 생성 print가 진행됩니다.

// group1과 group2는 같은 객체인지 확인
print(group1 == group2); // false

매번 새로운 객체를 생성하여 반환하는 팩토리 형식을 Group 객체를 적용합니다.


코드 진행 후 터미널을 살펴본다면 생성자 문구가 두 번 찍힘과 동시에, 두 객체를 비교하는 Print를 통해 같은 객체가 아님을 확인할 수 있습니다.



LazySingleton 유형


GetItLocator.locator.setUpFactory();

// 첫 객체 생성
Person person1 = GetIt.I<Person>();
// 첫 생성시 생성자의 Print 문이 출력됩니다.

// 두 번째 객체 생성
Person person2 = GetIt.I<Person>();

// person1과 person2는 같은 객체인지 확인
print(person1 == person2); // false

코드 진행 후 터미널을 살펴본다면 생성자 문구가 첫 생성 시 한 번만 찍힘과 동시에, 두 객체를 비교하는 Print를 통해 같은 객체가 같음을 확인할 수 있습니다.


이때 객체 생성 코드들을 주석 처리 하고 GetItLocator.locator.setUpFactory(); 코드로 등록만 진행한다면 생성자 print가 출력되지 않음으로 필요시에만 객체를 생성함을 확인할 수 있습니다.





Get_It에 관한 별도의 코드를 Github 레파지토리에서 확인 가능합니다!

profile
드문드문 기초 정보를 올리는 블로그

0개의 댓글