본문 바로가기
IOS - Swift

[iOS/Swift] Dependency Injection, 의존성 주입이란?

by 게게겍 2023. 7. 30.

Dependency.

의존성이란?

객체 지향 프로그래밍에서 Dependency, 의존성은 서로 다른 객체 사이에 의존 관계가 있다는 것을 말한다. 즉, 의존하는 객체가 수정되면, 다른 객체도 영향을 받는다는 것이다

예를들어 아래의 코드의 경우에는

class APart {
    var name: String = "A부품"

class BPart {
    var name: String = "B부품"
}

class CGoods {
    
// CGoods APart에 의존한다.(= 의존성이 생긴다.) 
// APart를 할당한다. (실제로는 네트워크 매니저 같은것들에서 사용됨).
    var a: A부품 = A부품()
    

func printName() {
        print(a.name)
    }

이런식으로 CGoods 는 위의 두개의 part에 의존하는 class입니다. 그러나 이는

class C완성품 {
    
    // C완성품이 A부품에 의존한다
    var a: A부품 = A부품()
이와같이 의존성이 생길 수밖에 없다. 즉 C를 완성하기 위해서 A에 의존할 수밖에 없다.

CGoods 객체는 APart객체를 인스턴스로 사용하고 있으므로, APart객체에 의존성이 생기게 됩니다. 만약 이때, APart 객체에 중요한 수정이나 오류가 발생한다면, CGoods 객체도 영향을 받을 수 있습니다.

의존성을 가지는 코드가 많아진다면, 재활용성이 떨어지고 매번 의존성을 가지는 객체들을 함께 수정해 주어야 한다는 문제가 발생하게 됩니다

이러한 의존성을 해결하기 위해 나온 개념이 바로 Dependency Injection, 의존성 주입입니다.

예시로

class APart {
    var nameString: String = "A부품" // 원래는 name
}
...
func printName() {
        print(a.nameString)
    }

이런식으로 APart 가 변경될 경우에는 하단에 타입의 이름을 출력하는 부분까지 수정해야 됩니다.

(C라는 완성품은 APart에 의존하고 있기 때문)

또한 a 가 BPart 라고 한다면 관련된 모든 코드들을 바꾸어야 합니다. 이를 하나의 객체가 다른 객체에 의존하고 있다 라고 합니다.

**Injection

주입이란?**

Injection, 주입은 외부에서 객체를 생성해서 넣는 것을 의미합니다. (생성자 등을 통해 주입함)

// 주입(Injection)의 개념 ==============

class Person {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

// 외부에서 값을 주입(할당/초기화)해서 인스턴스 생성

let p1 = Person(name: "뉴진스")

생성자를 통해서 저장속성을 외부에서 주입한다 라고 생각하면 됩니다.

실제로 var name: String = “” 이런식으로 데이터를 처음부터 기본값을 할당하는것이 아닌 생성자를 통해서 외부에서 값이 들어오고 외부의 값을 통해서 저장속성에 할당할 수 있도록 하는겁니다.

이 코드에서 저장속성에 할당하고싶은 값을(name에 넣고싶은값) 외부에서 할당할 수 있습니다.

이번에는 생성자를 통해서 할당할 경우입니다.

class CGoods {
    
    // CGoods가 AParts에 의존한다 (= 의존성이 생긴다.)
    var a: APart
    
    init(a: APart) {
        self.a = a
    }
    
    func printName() {
        print(a.name)
    }
}

이런식으로 인스턴스로 만드는게 아니라 생성자를 통해서 저장속성에 저장하는 경우

let coolA: AParts = AParts()
coolA.name = "발전한 A부품"

// 주입 방식만 개선
// 외부에서 주입하도록 만들었으나, 여전히 의존한다.

let c2: CProduct = CProduct(a: coolA)

이런식으로 coolA를 주입할 수 있게 됩니다.

하지만 이런 코드를 의존성 주입이라고 하지는 않습니다.

의존성을 넣는방법

// 의존성 주입
// (개선된) 의존성: 프로토콜을 사용해서 의존성 분리 및 의존관계 역전시킴
// 주입: 쿨한C완성품가 의존성을 가지는 클래스(A, B)를 쿨한C완성품 밖에서 생성자를 통해 주입 (언제든지 교체 가능해져, 확장성이 늘어남)

// 의존성 분리 및 의존관계 역전 (Inversion Of Control)
// ====> 프로토콜(자격증) 사용의 장점 / 추상화의 장점

protocol 모듈화된부품 {
    var name: String { get set }
}

class A부품: 모듈화된부품 {
    var name: String = "A부품"
}

class B부품: 모듈화된부품 {
    var name: String = "B부품"
}

class 쿨한C완성품 {
    
    var a: 모듈화된부품
    
    init(a: 모듈화된부품) {    // 프로토콜 타입으로 선언
        self.a = a
    }

즉 이런식으로 프로토콜로 분리해서 의존성을 주입할 수 있게 됩니다.

let moduledA = A부품()
let moduledB = B부품()

// (개선된) 의존성 주입을 통해 완성품을 만드는 방법
// 외부에서 언제든지 새로운 객체로 교체 가능, 확장 용이

let developedC = 쿨한C완성품(a: moduledA)

 

이런식으로 moduledA나 moduledB 아무거나 주입할 수 있게 생성됩니다. 

또한, 코드 자체에서 프로토콜타입으로 뜨게 됩니다. 그로인해 동일한 프로토콜 타입인 moduledA나 moduledB 아무거나 주입할 수 있다. (모듈화가 되어있기 때문에 확장성 용이)

정리

의존성 주입: 프로그램 디자인이 결합도를 느슨하게 되도록 하고 의존관계 역전 원칙과 단일책임원칙을 따르도록 클라이언트 생성에 대한 의존성을 클라이언트의 행위로부터 분리하는것

  • 기존의 의존성을 개선하여 “(개선된) 의존성을 외부에서 주입할 수있는 방식” 으로 바꾸는것

(개선된)의존성: 프로토콜을 사용해서 의존성을 분리시키고 의존관계를 역전(Inversion of Control)시킴

주입: 생성자를 통해서 외부에서 값을 주입한다 (생성시 값 할당가능 / 언제든지 교체 가능해져 확장성이 늘어남)

 

의존성 주입의 사용이유:

1. 객체간의 의존성을 줄여서 코드의 재활용성, 확장성이 높아진다.
2. 객체간의 결합도가 낮아져서 유연한 코드, 유연한 프로그램 작성이 가능해집니다.

3. 유지보수가 용이해집니다.

4. Unit Tset가 가능해집니다(특정 개체의 의존성을 없애 test 객체 주입이 가능합니다.)

 


Reference

[DI] Dependency Injection이란 무엇일까?Dependency Injection, 객체지향 프로그래밍을 하다보면 한번 쯤 듣게 되는 용어중 하나인데요. 이번 글에서는 의존성 주입이 무엇이고 어떤 배경으로 생겨난 개념인지, 왜 필요한지에 대해 간단히 정리해보려고 합니다. 개발을 하다보면 코드에 의존성 이 생기기 마련입니다. 그럼 의존성은 무엇이고, 왜 생겨나는 걸까요? 아래의 코드를 봐주세요. 위 코드와 같이 Programmer 클래스에서 startProgramming 함수가 호출되기 위해서는 Coffee 클래스를 필요로 합니다.https://velog.io/@wlsdud2194/what-is-di

https://oopy.lazyrockets.com/api/v2/notion/image?src=https%3A%2F%2Fmedia.vlpt.us%2Fimages%2Fwlsdud2194%2Fpost%2F4aa1b83b-327b-42a1-8411-9bfed8e35a4e%2Fbanner-image.png%3Fw%3D768&blockId=39a57a7a-fa04-4d48-a452-2c7b53b8f153&width=512

[Swift] 의존성 주입 (DI) 이란?테스트 코드를 작성하기 위해서는 기존 코드에 의존성을 깨는 것부터 시작해야 합니다. 종속성이 감소하면 수정에 민감하지 않고, 유연성과 확장성이 높아져 테스트에 용이해지는 장점이 있습니다. 많은 장점이 있다지만..! 말로만 하면 잘 와닿지 않져 ㅋ 차근차근 정리해 봅시다 의존성은 쉽게 말해 함수에 필요한 클래스나 참조 변수에 의존하는 것을 의미합니다.https://silver-g-0114.tistory.com/143

https://oopy.lazyrockets.com/api/v2/notion/image?src=https%3A%2F%2Ft1.daumcdn.net%2Ftistory_admin%2Fstatic%2Fimages%2FopenGraph%2Fopengraph.png&blockId=398d2a87-3fe6-4d66-af10-402c53e15050&width=512

OOP ) DIP - 의존관계 역전법칙(Dependency inversion Principle)추상화 된 것은 구체적인 것에 의존하면 안되고 구체적인 것이 추상화된 것에 의존해야 한다 위에서는 변할수 있는것 과 변하지 않을 것 을 나누는 게 중요했다. 그리고 구체적일 수록 잘 변했고 , 구제적이지 않을 수록 잘 변하지 않았다. 객체사이의 서로 도움을 주고 받으면서 협력을 하게 되면 어쩔수 없이 의존관계가 생길 수밖에 없다.https://o-o-wl.tistory.com/30

https://www.youtube.com/watch?v=05HzQXFE720

https://80000coding.oopy.io/68ee8d89-5d05-449d-87e2-5fba84d604ca