본문 바로가기
JavaScript

[JAVA][Android] Dagger2 익혀보기

by teamnova 2021. 10. 25.

 

Dagger2 

자바와 Android를 위해 완전히 정적으로 컴파일 타임 의존성 주입 프레임 워크입니다.

 

그렇다면 의존성 주입은 뭘까요?

 

의존성 주입 (Dependency-injection)

의존성 주입은 프로그래밍에서 구성요소간의 의존 관계가 내부가 아닌 외부를 통해 정의되게 하는 디자인 패턴 중의 하나.

의존성 주입의 목적은 객체를 생성하고 사용하는 관심사를 분리하는 것.

 

 

 

A내에서 B를 생성하지만, 두번째 그림은 외부에서 B객체가 생성되어 A로 주입된느 모습입니다.

이때 외부에서 객체를 관리하게 되는데 이를 IOC(inversion of Control, 제어의 역전)라 합니다.

 

그렇다면 의존성 주입은 왜 필요한 걸까요?

 

  • 코드가 유연해짐, 클래스간의 결합도를 줄임.
  • 리팩토링이 수월함
  • 유닛테스트를  쉽게 수행   있음
  • 코드의 재사용성 증대
  • 보일러 플레이트 코드 감소
  • 스코프를 이용한 객체 관리

 

 

Dagger 기본개념 이해하기

 

Inject

의존성 주입을 요청합니다. Inject 어노테이션으로 주입을 요청하면 연결된 Component가 Module로부터 객체를 생성하여 넘겨줍니다.

Component

연결된 Module을 이용하여 의존성 객체를 생성하고, Inject로 요청받은 인스턴스에 생성한 객체를 주입합니다. 의존성을 요청받고 주입하는 Dagger의 주된 역할을 수행합니다.

Subcomponent

Component는 계층관계를 만들 수 있습니다. SubComponent는 Inner Class방식의 하위계층 Component입니다. Sub의 Sub도 가능합니다. Subcomponent는 Dagger의 중요한 컨셉인 그래프를 형성합니다. Inject로 주입을 요청받으면 Subcomponent에서 먼저 의존성을 검색하고, 없으면 부모로 올라가면서 검색합니다.

Module

Component에 연결되어 의존성 객체를 생성합니다. 생성 후 Scope에 따라 관리도 합니다.

Scope

생성된 객체의 Lifecycle 범위입니다. 안드로이드에서는 주로 PerActivity, PerFragment 등으로 화면의 생명주기와 맞추어 사용합니다. Module에서 Scope을 보고 객체를 관리합니다.

 

 

 

그러면 셰프에게 요리를 주문하는 간단한 예제를 해보겠습니다. 

 

먼저 셰프 클래스를 만들겠습니다. 

 

 

Chef.java

public class Chef {

    private String firstName;
    private String lastName;

    public Chef(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "Chef [firstName=" + firstName + ", lastName=" + lastName + "]";
    }
}

 

주방 클래스를 만들겠습니다.

 

Kitchen.java

public class Kitchen {

    private Chef chef;
    private String order;

    public Kitchen(Chef chef, String order) {

        this.chef = chef;
        this.order = order;
    }

    public boolean isOrder() {

        if (chef !=null && order!=null && order.length()>0) {
            Log.d("MyTag","Chef: " + chef + " order: "  + order);
            return true;
        }
        return false;
    }
}

 

 

모듈 클래스

 

ChefModule.java

@Module
public class ChefModule {

    @Provides
    Chef provideChef() {
        return new Chef("Black","Jin");
    }
}

 

 

KitchenModule.java

@Module
public class KitchenModule {

    @Provides
    Kitchen provideIsOrder(Chef chef, @Named("course1") String order) {
        return new Kitchen(chef, order);
    }

    @Provides
    @Named("course1")
    String provideCourse1() {
        return "한식";
    }

    @Provides
    @Named("course2")
    String provideCourse2() {
        return "중식";
    }
}

 

 

마지막으로 컴포넌트를 만들어줍니다.

 

Component.java

@Component(modules = {ChefModule.class, KitchenModule.class})
public interface MyComponent {

    void inject(MainActivity activity);
}

 

 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Inject
    Kitchen kitchen;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyComponent myComponent = DaggerMyComponent.builder().build();
        myComponent.inject(this);

        isOrder();

    }
    
    private void isOrder() {
        boolean isOrder = kitchen.isOrder();
        if (isOrder) {
            Log.d("MyTag","order successful. ");
        } else {
            Log.d("MyTag","order failed. ");
        }
    }

}

 

 

여기서 마지막으로 DaggerMyComponent부분이 에러가 뜨는걸 확일할 수 있는데요

 

안드로이드 스튜디오 상단에 Build -> Make Project 를 눌러서 의존성 주입을 해주는 클래스가 자동으로 생성됩니다. 

 

 

 

 

Dagger를 적용한 프로그램의 결과값입니다.