본문 바로가기
Android개발/Dagger2

DI : Dependency Injection

by 궝테스트 2020. 5. 25.
'아키텍처를 알아야 앱 개발이 보인다' 책을 보며 정리 및 간단 리뷰를 남긴다
어느정도 아키텍처, dagger, rxJava, Jetpack 등의 선행학습 후 복습 차원에서 보면 좋을 것 같다

 

DI 개념을 훑어보면 간단해보이지만, 변경의 전이/제어의 역전 같은 단어는 정말 머리에 안들어온다,,
아 인터페이스 기반으로 주입하면 되는구나 싶지만 실제로 이미 많이 구현되어있는 프로젝트에 적용하려고 하면 이미 구조가 잘 잡혀있는데 변화를 준다는게 쉽지 않은 것 같다.
(오히려 프로젝트 초기 단계부터 시작한다면 구조 잡기가 훨씬 수월할듯)
어쨋든 dagger2 를 사용하기 전 간단하게 DI 개념을 읽고 간다!

1. 의존성 주입 (DI : Dependency Injection)
: 하나의 객체에 다른 객체의 의존성을 제공하는 기술

의존성(Dependency) : 객체 지향에서 두 클래스 간의 관계로 둘 중 하나가 다른 하나를 필요로 한다

// ex.1

class CPU {}

class Computer {
    private val cpu:CPU = CPU()
}

CPU 는 Computer 가 생성될 때부터 단단히 결합되어있으며, 다른 CPU 로 변경할 수도 없다.
이를 'Computer 가 CPU 에 의존성을 갖는다' 라고 한다.

주입(Injection) : 생성자, 메서드 등을 통해 외부로부터 생성된 객체를 전달받는 것이다

// ex.2

class Computer {
    private lateinit var cpu:CPU
    
    fun setCPU(cpu: CPU) {
        this.cpu = cpu
    }
}

setCPU() 를 통해 외부로부터 생성된 객체를 전달받아 멤버 변수에 넣는다.

따라서 '의존성+주입 = 의존 관계에 있는 클래스의 객체를 외부로부터 생성하여 주입받는다' 라고 정의 할 수 있다.

2. 의존성 주입의 필요성

변경의 전이
위 코드를 다시 보면, Computer 는 CPU 라는 한가지 타입에 의존하지만 사용자는 다른 타입의 CPU 를 원할 수 있다.
A_CPU 라는 타입을 사용하려면 새로운 A_CPU 라는 클래스를 변경 또는 생성하고,
ex.1 에서는 CPU 클래스에 의존하던 Computer 클래스의 cpu 변수 타입과 생성까지 모두 변경해야한다.
하나의 클래스를 변경하면 의존 관계까지 변경사항이 전이된다.

-> 해결방법
: Computer 가 의존하는 CPU 를 Interface 로 만든다.

// ex.3

interface CPU { }

class A_CPU : CPU { }

class Computer {
	private val cpu: CPU = A_CPU()
}

CPU 가 Interface 로 변경되면서 변경의 전이가 최소화됐지만, 다른 타입의 CPU 를 사용한다면 Computer 클래스에 변경이 일어난다.

제어의 역전 (IoC : Inversion of Control)
어떤 일을 수행하는 프레임워크에 제어권을 위임함으로써 관심사를 분리하는 것이다.

// ex.4

class Computer {
    private lateinit var cpu:CPU

    constructor() {}
    
    constructor(cpu: CPU) {
        this.cpu = cpu
    }
    
    fun setCPU(cpu: CPU) {
        this.cpu = cpu
    }
}

Computer 클래스 생성 시 CPU 객체를 생성하지 않고, 외부로부터 CPU 객체를 생성한 뒤 메서드의 매개변수로 객체를 제공한다.
여기서는 CPU 객체의 생성 및 관리를 외부에 위임했기 때문에 제어의 역전이라고 한다.
결합도도 약해졌고 CPU 가 변경이 되어도 Computer 내부 필드나 메서드 등을 변경하지 않아도 된다.

3. 의존성 주입의 장단점

장점
- 인터페이스를 기반으로 설계하며 코드를 유연하게 한다 (여러 개발자가 독립적으로 개발할 수 있다)
- 주입하는 코드만 변경하기 쉬워 리팩토링이 수월하다
- stub, mock 객체를 사용하여 단위 테스트가 쉬워진다
- 클래스 간 결합도를 느슨하게 한다

단점
- 간단한 코딩 시 번거롭다
- 동작과 구성을 분리해 코드를 추적하기 어려워 가독성을 떨어뜨린다
- Dagger2 와 같은 DI 프레임워크는 컴파일 타임에 애노테이션 프로세서를 이용하여 파일을 생성함으로 빌드 시간이 좀 더 소요된다

'Android개발 > Dagger2' 카테고리의 다른 글

Dagger2 기본 #5 - Binding  (0) 2020.05.29
Dagger2 기본 #4 - Component 의존 관계  (0) 2020.05.29
Dagger2 기본 #3 - Component  (0) 2020.05.29
Dagger2 기본 #2 - Module  (0) 2020.05.28
Dagger2 기본 #1 - 시작  (0) 2020.05.27

댓글