HIT해

[Swift 기초문법 - 32] 의존성 주입 Dependency Injection 본문

Swift/Swift 기초문법

[Swift 기초문법 - 32] 의존성 주입 Dependency Injection

힛해 2024. 8. 14. 06:40
728x90

 

import UIKit

// 프로토콜은 약속
// 뭔가를 강제
protocol Talking {
    func sayHi()
}

class BestTalk : Talking {
    func sayHi() {
        print("최고의 대화였어")
    }
}

class OldTalk : Talking {
    func sayHi() {
        print("오랜만의 대화였어")
    }
}

 

두 클래스 모두 sayHi라는 함수를 가지고 있어야만한다.

 

의존성 주입을 해보자

import UIKit


// 프로토콜은 약속
// 뭔가를 강제
protocol Talking {
    
    var saying : String { get set }
    func sayHi()
    
}

class BestTalk : Talking {
    var saying: String = "베스트 토크"
    
    func sayHi() {
        print("최고의 대화였어")
    }
}

class OldTalk : Talking {
    var saying: String = "올드 토크"
    
    func sayHi() {
        print("오랜만의 대화였어")
    }
}

class Friend{
    
    // Dependency
    var talkProvider : Talking
    
    init(_ talkProvider : Talking){
        self.talkProvider = talkProvider
    }
    
    func sayHi(){
        talkProvider.sayHi()
    }
}


let myBestFriend = Friend(BestTalk())

 

Friend의 init에 BestTalk()가 들어올 수 있는 이유는 BestTalk는 Talking이기 떄문이다.

그럼 이때 myBestFriend.sayHi()는 "최고의 대화였어" 가 출력될 것이다

 

변수도 받아올 수 있다

class Friend{
    
    // Dependency
    var talkProvider : Talking
    
    var saying : String {
        get {
            talkProvider.saying
        }
    }
    
    init(_ talkProvider : Talking){
        self.talkProvider = talkProvider
    }
    
    func sayHi(){
        talkProvider.sayHi()
    }
}


let myBestFriend = Friend(BestTalk())

myBestFriend.sayHi() // 최고의 대화였소
myBestFriend.saying // 베스트토크

let myBestFriend = Friend(OldTalk())

myBestFriend.sayHi() // 오랜만의 대화였소
myBestFriend.saying // 올드토크

 

보통은 implement라는 이름으로 만들어 특정 프로토콜을 준수하고 있다고 나타내기도 한다. ( 가독성 향상! )

 

또는 새로운 인스턴스 생성없이 새로운 프로바이더를 교체하기도 한다.

class Friend{
    
    // Dependency
    var talkProvider : Talking
    
    var saying : String {
        get {
            talkProvider.saying
        }
    }
    
    init(_ talkProvider : Talking){
        self.talkProvider = talkProvider
    }
    
    func setTalkProvider(_ newProvider : Talking){
        self.talkProvider = newProvider
    }
    
    func sayHi(){
        talkProvider.sayHi()
    }
}


let myBestFriend = Friend(BestTalk())

myBestFriend.sayHi() // 최고의 대화였소
myBestFriend.saying // 베스트토크
myBestFriend.setTalkProvider(OldTalk())
myBestFriend.sayHi() // 오랜만의 대화였소
myBestFriend.saying // 올드토크

 

메모리적으로 더 효율적이겠죠?

 

프로젝트 사용예시

이전에 플러터에서 API 통신 상태를 나타낼때 

  1. 통신 완료
  2. 통신 중
  3. 새로고침
  4. 더 받아오기
  5. 에러

의 상태들을 빈 클래스를 상속받게 하고 통신 로직에서 해당 빈 클래스를 상속하고 있는 제네릭 형태의 모든 값들이 유연하게 할당되게 만든 경험이 있다.

 

Swift에서는 이름은 다르지만 이러한 의존성 주입 과정을 통해 코드를 보다 가독성있고 유연하게 만들 수 있을 것 같다.