티스토리 뷰

의존성 주입 (Dependency Injection)

 

안녕하세요 토니입니다:)

 

오늘은 의존성 주입이라는 글로 찾아 뵙게 되었어요.

 

의존성 주입... 말로만 들어도 어려운데요..

 

저도 진짜진짜진짜 잘 모르는 개념이라서 정리를 해보고자 블로그를 열었어요

 

우리 같이 이해해보자구요! 🤔

 

 

 

우선 의존성 주입이 무엇인지 알아야 겠죠?

 

결론부터 한번 살펴보고 갈까요???

 

한마디로 A라는 객체의 속성을 A가 아닌 다른 객체가 초기화 해주는 것을 말해요!!

 

 

어렵네요.. 그쵸?

 

그렇다면 여기서 궁금한 것이 생기지않나요?🧐

 

왜 내가 안하고 다른 객체를 통해서 초기화를 해야만 할까요??

 

이렇게 해주게 된다면...

 

 

 

객체간 결합을 느슨하게 만들수 있다고 합니다.

 

 

그렇다면 객체간 결합이 느슨해지면 뭐가좋냐??

 

재사용성이 높고, 테스트에 용이하고, 코드도 단순화 시키고, 결합도를 낮출수 있고, 유지보수에 용이하고... 등등 ......... 

 

뭐 장점이 많아서 다 나열도 못하겠네요?

 

 

뭔가 정리가 하나도 안되는 것 같으니, 

 

우선 하나씩 차근차근 진도를 밟아볼까요? 

 

 

의존성?

 

Dependency InjectionDependency의존성을 말하는데요!

 

클래스 다이어그램의 의존관계를 예로 들어서 생각해봐도 좋을 것 같아요!

 

의존 관계는 언제 발생하냐!!!

 

바로 한 클래스가 다른 클래스에서 제공하는 기능을 사용할 때 발생해여!!!

 

예를 들어 프로그래머 클래스가 컴퓨터에서 제공하는 기능(메서드)을 사용한다면 A와 B는 의존관계가 있으며, 의존성이 생겼

 

다고 볼 수 있는 거겠죠??

 

 

그러면 다시! 다시

 

의존성은 서로 다른 객체 사이에 의존 관계가 있다는 것을 말하고 있죠??

 

즉, 의존하는 객체가 수정되면, 다른 객체도 영향을 받는다라는 말인데요?? 

 

이해를 도울 수 있도록 코드를 작성해봤어요!

 

struct Eat {
    func chicken() {
        print("Fried Chicken")
    }

    func water() {
        print("Water")
    }
}

struct Person {
    var dinner: Eat
    
    func eatChicken() {
        dinner.chicken()
    }
    
    func drinkWater() {
        dinner.water()
    }
}

 

Person 구조체는 Eat 구조체를 인스턴스로 사용하고 있으므로, 의존성이 생기게 되는 걸 볼 수가 있죠??

 

이때, Chicken이 양념으로 변한다던지와 같은 중요한 수정이나 오류가 발생한다면, 당연히 Person 또한 영향을 받을 수가

 

있겠죠?? 🍗

 

만약 이렇게 의존성을 가지는 코드가 많아진다면, 재사용성이 떨어짐은 물론이고 매번 의존성을 가지는 객체들을 수정해주어야 겠죠?ㅠ

 

 

이제 의존성에 관한 이해가 좀 되시나요?? 

 

 

그렇다면 이렇게 의존성을 지니게 되면 의존성 주입이라고 볼 수 있구나!!!!

 

라고 하신다면..절반만 맞춘걸로 하죠ㅎㅎ 

 

 

의존성이 생기는 것과 의존성을 주입하는 것은 다르다는 것을 명심해주셨으면 해요!!

 

의존성 주입은 위와 같은 문제를 해결하기 위해 나온 개념이거든요!!

 

그렇다면 주입이 뭐냐? 하고 궁금해하시는 분들을 위해서

 

간단하게 주입이 뭔지 살펴볼게요!

 

injection을 구글에 치면 이렇게 주사기가 제일 먼저 뜨는데요! 

 

주사는 약품(?)을 우리 몸속에다가 주입하죠

 

그럼 이걸 토대로 한번 생각해 볼까요?

 

저기 주사기 안쪽에 외부에서 만든 객체가 있다고 생각을 해봅시다.

 

그리고 주사를 놓게 된다면????

 

외부에서 만든 객체를 생성해서 놓아주게된다고 생각할 수 있겠죠??

 

클래스 생성에서 주입을 하던, 함수를 이용해서 외부에서 넣든, 외부에서 넣어주는 상황!

 

 

 

 

 

그렇다면 의존성 주입!

 

너는 대체 어떻게 하는 것이냐!!! 를 알아보기전에 

 

객체 지향 프로그래밍 설계의 다섯가지 기본 원칙 중 하나인 DIP를 잠깐 볼까요??

 

Dependency Inversion Principle 로 말 그대로 직역하면 의존관계 역전 법칙인데요!

 

추상화된 것은 구체적인 것에 의존하면 안되고 구체적인 것이 추상화 된 것에 의존해야한다... 라네요..

 

뭔 말인지 어렵죠ㅠ

 

다시 한번 살펴보자면

 

구체적인 객체는 추상화된 객체에 의존해야한다.. 라는 말 같아요

 

그럼 스위프트에서 추상화된 객체는 바로....Protocol이 있답니다.

 

이제 이말을 다시한번 번역해보자면

 

객체들 사이의 의존이 아니라 각 객체들이 추상적인 개념, 즉 프로토콜에 의존해야 의존성을 낮출 수 있다

는 것으로 이해를 하면 좋을 것 같아요!!!

 

 

 

 

 

다음예시는 흔히들 쓰는 3가지 방법에 대해 알아볼 것 이에요!!

 

 

1. 생성자 주입 (initializer injection)

 

외부에서 생성자(initializer)를 통해 의존성을 주입하는 방식을 의미해요!!

protocol Menu {
    var price: Int { get }
}

struct Chicken: Menu {
    var price: Int {
        return 10000
    }
}

class HungryMan {
    let dinner: Menu
    
    init(dinner: Menu) {
        self.dinner = dinner
    }
}

let hungryMan = HungryMan(dinner: Chicken())

 

위 코드를 보면 HungryMan과 Chicken은 모두 Menu라는 프로토콜에 의존하고 있는걸 볼 수 있죠??

 

그리고 HungryMan의 인스턴스를 만들어주기 위해 initializer에 또 다른 Menu 프로토콜을 채택하고 있는 인스턴스를 넣

 

 생성자를 통해 의존성을 주입하고 있는 것을 확인할 수가 있어요!! 

 

 

2. 프로퍼티 주입 (property injection)

 

프로퍼티 주입이란, 의존성 주입이 필요한 객체의 프로퍼티를 직접 불러서, 직접 주입해주는 행위를 말해요

protocol Menu {
    var price: Int { get }
}

struct Chicken: Menu {
    var price: Int {
        return 10000
    }
}

class HungryMan {
    var dinner: Menu?
}

let hungryMan = HungryMan()
hungryMan.dinner = Chicken()

생성자 주입과는 달리, HugryMan 타입에는 이니셜라이저가 없는 걸 볼수가 있죠?

 

이 때문에 HugryMan 의 인스턴스를 만들고,  dinner에 직접적으로 인스턴스를 넣어 주는 것을 볼 수가 있어요!!

 

이렇게 프로퍼티에 직접 접근하여 주입해주는 경우 문제가 몇개 있다고 하네요ㅎㅎ

  1. 해당하는 프로퍼티가 외부에 공개
  2. 해당하는 프로퍼티의 타입이 옵셔널이거나 불필요한 기본값을 갖게됨

 

3. 메서드 주입 (method injection)

 

메서드 주입이란, 메서드를 통해 의존성 주입이 필요한 곳에 주입을 하는 행위를 말해요!!!

 

즉, 이전과 달리 이니셜라이저에서 주입하거나, 프로퍼티를 직접 불러 주입하는 것이 아닌, 메서드 내에 주입하는 행위를 정의

 

하여 메서드를 호출해주는 방식이에요!

protocol Menu {
    var price: Int { get }
}

struct Chicken: Menu {
    var price: Int {
        return 10000
    }
}

class HungryMan {
    var dinner: Menu?
    
    func setDinner(dinner: Menu) {
        self.dinner = dinner
    }
}

let hungryMan = HungryMan()
hungryMan.setDinner(dinner: Chicken())

이렇게 메서드 주입방식을 사용해준다면 메서드를 사용하는 시점만 일시적으로 의존관계가 생기는 특징이 있어요!!

 

 

 

 

이렇게 지금까지 의존성 주입을 알아보았어요!!!

 

이제 우리는

 

책임이 좀 더 명확해진 클래스를 얻을 수 있게 되었구요!

 


Test가 용이한 클래스를 얻게 되었어요!!

 


또한 프로토콜을 사용하여 결합도를 줄이고, 주입된 객체의 책임을 명확히 할 수 있게 되었죠?

 

 

 

질문 및 잘못된 정보에 대한 지적은 언제든 환영입니다!!!

'Swift' 카테고리의 다른 글

Swift - 스토리보드를 분할하고 화면 이동하기!!!  (0) 2021.12.19
Swift - Codable..?  (1) 2021.12.07
Swift - Table View - DataSource, Delegate  (0) 2021.12.07
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
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
글 보관함