DI (Dependency Injection) 의존성 주입

클래스 내부에서 필요한 객체의 인스턴스를 클래스 내부에서 생성하는 것이 아니라 외부에서 생성한 후 이니셜라이저 또는 setter를 통해 내부로 주입받는 것이다. 이때 이니셜 라이저의 타입은 프로토콜을 활용하여 내부에서는 프로토콜 메서드를 사용한다.

DI는 의존성을 클래스에 주입 시키는 것이고, 의존성 분리의 조건을 만족해야 한다.

  1. 의존성(Dependency) 클래스 A, 클래스 B가 있고, 클래스 B의 값이 바뀔때 클래스 A의 값도 함께 바뀌게 된다면 클래스 A는 B에게 의존성을 갖는다고 말한다.

    // AP 챔피언 클래스
    class ApChamp {
        let name: String
        init(name: String) {
            self.name = name
        }
    }
    
    // AD 챔피언 클래스
    class AdChamp {
        let name: String     // 여기랑 Int로 바꾸게된다면
        init(name: String) { // 여기를 Int로 바꾸게된다면
            self.name = name
        }
    }
    
    // 플레이어 클래스
    class Player {
        let apMost: ApChamp
        let adMost: AdChamp
    
        // 클래스 내부에서 ApChamp, AdChamp 인스턴스를 생성하고 있다.
        init() {
            self.apMost = ApChamp(name: "아칼리")
            self.adMost = AdChamp(name: "요네")  // AdChamp 클래스의 name 타입을 이렇게 Int로 변경한다면, ksw의 init()함수 내부 여기서 타입에러가 난다.
        }
    }
    
    let ksw = Player()
    print(ksw.apMost.name) // 아칼리
    print(ksw.adMost.name) // 요네
    
  2. 주입 (Injection) 위의 Player 코드를 다음과 같이 수정할 수 있다.

    class Player {
        let apMost: ApChamp
        let adMost: AdChamp
    
        // init 함수 수정
        init(apMost: ApChamp, adMost: AdChamp) {
            self.apMost = apMost
            self.adMost = adMost
        }
    }
    
    // 외부에서 클래스 내부에 값을 "주입"
    let apChamp = ApChamp(name: "아칼리")
    let adChamp = AdChamp(name: "요네")
    let ksw = Player(apMost: apChamp, adMost: adChamp)
    
    print(ksw.apMost.name) // 아칼리
    print(ksw.adMost.name) // 요네
    

    객체의 인스턴스를 외부에서 생성한뒤 (let apChamp = ApChamp(name: "아칼리") 넣어주는것을 주입이라고 한다.

    현재 코드에선 AdChamp의 name이 Int 형으로 변경된다고 해도, Player 클래스의 init()에는 문제가 생기지 않게 된다. 그래도 AdChamp의 name value 가 바뀐다면, Player의 adMost 의 name value 도 바뀌므로 의존성은 남아있다. 쉽게 말해서, 클래스 A 내부에서 다른 클래스 B를 사용하고 있다면, A가 B를 의존한다고 생각할 수 있다.

    여튼 이렇게 해서 "의존성"을 "주입"했다.

  3. 의존성 분리 위 내용처럼 의존성을 주입시킨 것 만으로 DI라고 부르지 않는다. 의존성 분리의 조건을 만족시켜야 DI 라고 한다. 그리고 의존성의 분리는 의존 역전의 원칙을 기반으로 분리를 실행한다.

SOLID 5원칙 중 Dependency Inversion Principle을 의미한다. DIP원칙이란?

  1. IOC Container

    여태 설명한 IOC, 의존 역전을 구현하는 프레임워크를 IOC Container 라고 한다.

    제어권을 프레임워크가 가져가게 되는 것.

    이를 위한 프레임워크로 Swinject 가 있다. → 추후 적용해볼것!


    참고

    https://ios-daniel-yang.tistory.com/71#article-2--의존성(dependency)이란? https://80000coding.oopy.io/68ee8d89-5d05-449d-87e2-5fba84d604ca