개발아 담하자

[Swift] 의존성 주입 (DI) 이란? 본문

📱 iOS

[Swift] 의존성 주입 (DI) 이란?

choidam 2021. 7. 21. 21:05

테스트 코드를 작성하기 위해서는 기존 코드에 의존성을 깨는 것부터 시작해야 합니다. 종속성이 감소하면 수정에 민감하지 않고, 유연성과 확장성이 높아져 테스트에 용이해지는 장점이 있습니다.

 

많은 장점이 있다지만..! 말로만 하면 잘 와닿지 않져 ㅋ 차근차근 정리해 봅시다

 

의존성 (Dependency)

의존성은 쉽게 말해 함수에 필요한 클래스나 참조 변수에 의존하는 것을 의미합니다.

class A{
    var num: Int = 1
}

class B{
    var internalVariable = A()
}

let b = B()
print(b.internalVariable.num) // 1

B클래스는 A클래스를 내부에 변수로 사용하고 있습니다. 이로써 B클래스는 A클래스에 의존성이 생깁니다.

 

객체끼리 의존하는 경우 많은 문제가 야기됩니다. 만일 A클래스에 문제가 생긴다면 이를 의존하고 있는 B클래스에도 문제가 생길 수 있어 재사용성이 낮아집니다. (재사용이 가능한 건 상위 클래스인 A 뿐입니다.)

이를 해결한 게 의존성 주입이죠! 일단 용어부터 천천히 알아봅시다.

 

주입 (Injection)

내부가 아닌 외부에서 객체를 생성해서 넣어주는 것을 주입한다고 표현합니다.

class A{
    var num: Int

    init(num : Int){
        self.num = num
    }

    func setNum(num: Int){
        self.num = num
    }
}

let a = A(Int(3)) // 외부에서 객체 생성
print(a.num)

a.setNum(Int(5)) // 객체 생성

위 예시에서는 외부에서 Int를 생성해 A클래스에 주입했습니다.

 

의존성 주입 (Dependency Injection)

의존성 + 주입 용어가 합쳐졌습니다. 내부에서 만든 객체를 외부에서 넣어 의존성을 주입해 봅시다.

class A{
    var aNum: Int = 1
}
class B{
    var bNum: A
    init(num: A){
        self.bNum = num
    }
}
let b = B(A())

위 코드는 클래스의 생성에서 의존성을 주입했습니다.

하지만..! 이렇게 외부에서 의존성을 주입하는 것 만으로 의존성 주입이라고 부르지 않습니다.

 

여기서 반드시 알고 넘어가야 할 개념이 있습니다.

바로 '의존 관계 역전 법칙(DIP: Dependency Injection Principal)' 입니다.

의존성 주입에서 의존성 분리는 의존 관계 역전 법칙으로 의존 관계를 분리시켜야 합니다.

 

의존 관계 역전 법칙 (DIP)

객체 지향 프로그래밍의 SOLID 원칙 중의 하나입니다. 의존 관계 역전 법칙은 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존관계를 반전시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있는 구조를 말합니다. 이 법칙은 다음 두 가지 특징이 있습니다.

 

  1. 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
  2. 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.

 

말로만 해서는 뭔가 와닿지 않습니다.

 

앞선 예시는 B 클래스가 A 클래스에 의존하는 (B→A) 구조였다면, 의존 관계 역전 법칙에서는 어떤 추상화된 인터페이스(Swift 에서는 프로토콜)에 A, B 객체가 모두 의존(A → 프로토콜 ← B)하고 있는 구조라고 볼 수 있습니다.

protocol DIInterface: AnyObject{
    var num: Int{get set}
}
class A: DIInterface{
    var aNum = 1
}
class B{
    var bNum: DIInterface
    init(num: DIInterface){
        self.bNum = num
    }
}

let b = B(A())

위 구조는 A(상위 모듈), B(하위 모듈) 모두 DIInterface(추상화 프로토콜) 에 의존해있어 의존 관계를 독립 시킨 상태입니다.

이렇게 의존의 방향이 역전되어 제어가 반전되는 상황을 제어의 반전 (IoC: Inversion of Control) 이라고 표현합니다.

 

 

참고한 링크

https://nadarm.tistory.com/117

 

iOS) 프레임워크 없이 의존성 주입 해보기

프레임워크 없이 의존성 주입해보기 시작하기 전에 먼저 이 글은 의존성 주입의 개념을 설명하는 글이 아닙니다. 의존성 주입이란?(위키백과) 의존성 주입을 적용할 때 제가 고민했던 내용과 나

nadarm.tistory.com

https://ko.wikipedia.org/wiki/%EC%9D%98%EC%A1%B4%EA%B4%80%EA%B3%84_%EC%97%AD%EC%A0%84_%EC%9B%90%EC%B9%99

 

의존관계 역전 원칙 - 위키백과, 우리 모두의 백과사전

객체 지향 프로그래밍에서 의존관계 역전 원칙은 소프트웨어 모듈들을 분리하는 특정 형식을 지칭한다. 이 원칙을 따르면, 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인

ko.wikipedia.org