티스토리 뷰

iOS

iOS) Dependency Injection(의존성 주입)

hyun99999 2022. 8. 28. 23:40
728x90
반응형

✅ 의존성 주입(Dependency Injection)

의존성 주입이란 하나의 객체가 다른 객체의 의존성을 제공하는 기술이다.

의존성

그렇다면 의존성이란 무엇일까?

서로 다른 객체 사이에 의존 관계가 있다는 것이다. 이때 의존하는 객체가 수정되면 다른 객체도 영향을 줄 수 있다.

주입

그렇다면 주입은 무엇일까?

주입은 외부에서 객체를 생성하여 넣는 것을 말한다. 외부에서 객체를 주입하기 위해 생성자 등을 사용한다.

이러한 의존성을 만들어주기 위해서 의존성 주입을 사용합니다.

그래서 의존성 주입이 뭔데?

아마 개념에 대해서 들을때 감이 왔을 수 있다. 의존성으로 다른 객체에 영향을 주는 것은 어떤 수정사항이 있을 때 매번 다른 객체를 수정해주어야 하는 것이 아닐까?

짐작한대로 의존성을 가진 코드가 많다면 재활용성이 떨어지고, 의존성을 가지는 객체들과 함께 수정해야 하는 문제가 생긴다. 이러한 점을 해결하기 위해 나온 개념이 바로 의존성 주입이다.

이 외에도 의존성 주입을 통해서

  • Unit Test 가 용이
  • 코드의 재활용성을 높여준다.
  • 객체 간의 의존성을 줄여 유연한 코드를 작성

과 같은 이점이 존재한다.

간단히 말하면 의존성 주입을 통해서 객체를 수정하더라도 알아서 따라오는 의존관계를 만들 수 있다.

단순하게 의존성  주입 하기 전에 의존 관계 역전 법칙에 대해서 알아보자.

✅ 의존 관계 역전 법칙(Dependency Inversion Principle)

DIP 는 OOP(객체 지향 프로그래밍)의 다섯가지 원칙인 SOLID 중 하나입니다.

DIP 는 고수준 모듈이 저수준 모듈에 의존하는 전통적인 의존관계를 반전시킴으로써 고수준 모듈이 저수준 모듈의 구현으로부터 독립될 수 있는 구조를 말합니다.

의존 관계 역전 법칙에는 다음 특징이 있습니다.

A High level modules should not depend upon low level modules. Both should depend upon abstraction. Abstractions should not depend upon details. Details should depend upon abstractions.

고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 됩니다. 둘다 추상화에 의존해야 합니다.

추상화는 세부사항에 의존해서는 안된다. 세부사항은 추상화에 의존해야 한다.

(저수준 모듈이 좀 더 자세하고 좁은 범위의 구현이라고 생각하면 됩니다.)

이것을 아주 쉽게 말하면, "자신보다 변하기 쉬운 것에 의존하지 마라" 입니다.

✅ 일단.. 해볼까요?(눈치🫣)

앞서 언급한대로 단순하게 의존성  주입 해볼까요? 내부에서 만든 객체를 외부에서 넣는 과정을 진행해보겠습니다.

class MyMother {
	var name: String = "Lisa"
}

class YourMother {
	var name: String = "Mia"
}

// ✅ Son 클래스 내부에 MyMother 타입의 mother 프로퍼티를 가짐.
// 기본값으로 MyMother 인스턴스를 가짐. 이는 생성자를 통해서 설정할 수도 있음.
class Son {
	var mother: MyMother = MyMother()
    
    func callMother(){
    	print(self.mother.name)
    }
}

// ✅ Daughter 클래스도 동일하게 내부에 MyMother 인스턴스를 가지는 프로퍼티 mother 가짐.
class Daughter {
	var mother: MyMother = MyMother()
    
    func callMother(){
    	print(self.mother.name)
    }
}

var mySon = Son()
var myDaughter = Daughter()

// 출처: <https://ios-developer-storage.tistory.com/entry/Swift-Dependency-Injection-의존성-주입-비유로-쉽게-이해하기> [마늘맨의 iOS는 즐거워:티스토리]

만약에 변경사항으로 Son 과 Daughter 클래스의 mother 를 yourMother 로 바꾸어야 한다면 어떻게 해야할까요?

Son 과 Daughter 클래스 하나하나 수정해야 합니다. 만약에 더 많은 클래스에서 mother 에 대한 의존성이 주입되어있다면.. 아찔하네요.

이것이 바로 고수준의 모듈이 저수준의 모듈에 의존하는 전통적인 의존관계였습니다. (고수준의 모듈은 결국 저수준의 모듈을 구현하기 위한 역할이니 자연스러운 부분이죠.)

흠..! 그냥 처음부터 Mother 라는 클래스 하나만 만들고, Son 과 Daughter 가 Mother 에게 의존하니까 Mother 만 수정하면 되는 것 아닐까요?

이것이 바로 의존성의 장점입니다! 그리고 위의 의존관계를 반전시켜 추상화 개념을 수정하게되면 의존하고 있는 세부사항들이 자연스레 따라오는 의존 관계를 주입하는 것이 바로 DIP(의존 관계 역전 법칙) 가 적용된 의존성 주입 의 개념입니다.

✅ 진짜 해보자!(자신감 만땅😤)

Swift 에서는 추상화로 Protocol 을 사용합니다. Protocol 을 활용하여 고/저수준 모듈이 의존할 수 있는 추상화를 만들어보는 예시를 살펴봅시다.

// ✅ DIP 를 모르기전에는 Mammal(포유류)가 더 큰 개념이니까 아래의 Dog 클래스랑 Mammal 클래스를 통해 의존관계를 만들어 관리를 했을것이다.
// 이제는 의존 관계 역전 법칙을 적용해보자.

// ✅ 둘 다 의존할 수 있는 Animal 프로토콜을 생성.
protocol Animal {
    var name: String
    var sound: String
}

// ✅ Animal 프로토콜을 채택한 Mammal(포유류).
class Mammal: Animal {
	  var name = "Mammal"
    var sound = "woofwoof"
}

// ✅ Dog 의 sepcies 프로퍼티가 Animal 프로토콜을 준수하는 어떤 타입이라도 저장할 수 있도록 함.
// 이를 통해 Dog 는 Mammal 에 의존하지 않는 관계.
// 새로운 Dog 의 species 가 필요하다면 Animal 을 채택한 새로운 클래스를 만들면 되는 고수준 모듈이 저수준 모듈의 구현에 의존하지 않는 관계도 형성.
class Dog {
    var species: Animal
    init(species: Animal) {
        self.species = species
    }
}

// 출처: <https://ios-developer-storage.tistory.com/entry/Swift-Dependency-Injection-의존성-주입-비유로-쉽게-이해하기> [마늘맨의 iOS는 즐거워:티스토리]

✅ 정리

의존성 주입 : 한쪽이 수정되면 다른 한쪽이 영향을 받는 의존성을 생성자 등을 활용하여 외부에서 객체를 주입하는 형태.

고수준의 모듈이 저수준의 모듈에 주입되어 사용되면서 만들어지는 의존관계를 반전시켜 저수준 모듈의 구현으로부터 고수준의 모듈이 독립되는 의존관계(DIP)를 가진 의존성 주입.

Swift 에서는 이를 protocol 을 통한 추상화로 구현.

출처

(Swift) Dependency Injection, 의존성 주입이란? (feat. DIP)

의존성 주입 - 위키백과, 우리 모두의 백과사전

DIP(Dependency Inversion Principle)

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

728x90
반응형
댓글
최근에 올라온 글
최근에 달린 댓글
글 보관함
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
링크
Total
Today
Yesterday