๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ Computer Science/Programming

[CS] ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์ด๋ž€? (feat. ์จ์•ผํ•˜๋Š” ์ด์œ )

by Fomagran ๐Ÿ’ป 2021. 8. 26.
728x90
๋ฐ˜์‘ํ˜•

 

 

์•ˆ๋…•ํ•˜์„ธ์š” Foma ๐Ÿ’ป ์ž…๋‹ˆ๋‹ค!

 

์˜ค๋Š˜์€ ์˜์กด์„ฑ ์ฃผ์ž…์ด ๋ฌด์—‡์ด๊ณ  ์จ์•ผํ•˜๋Š” ์ด์œ ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

SOLID์›์น™์˜ ํ•˜๋‚˜์ด๊ธฐ๋„ ํ•˜๊ณ  ์ตœ๊ทผ RIBs ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ณต๋ถ€ํ•˜๊ณ  ์žˆ๋Š”๋ฐ UIViewController๋„ ์ง์ ‘ ์ฑ„ํƒํ•˜์ง€ ์•Š๊ณ 

 

ViewControllable๋กœ ํ”„๋กœํ† ์ฝœ์„ ๋งŒ๋“ค์–ด์„œ ์ฃผ์ž…ํ•˜๋”๋ผ๊ตฌ์š”..

 

๋ญ”๊ฐ€ ์ถ”์ƒ์ ์œผ๋กœ๋Š” ์•Œ๊ฒ ๋Š”๋ฐ ๊ตฌ์ฒด์ ์œผ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ์ด๊ฒŒ ๋ญ๊ณ  ์ด๊ฒŒ ์™œ ํ•„์š”ํ•œ๊ฐ€์— ๋Œ€ํ•ด์„œ ์•Œ์ง€ ๋ชปํ•ด์„œ

 

๊ธ€์„ ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค!

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


์˜์กด์„ฑ์„ ๊ฐ–๋Š”๋‹ค๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ผ๊นŒ? ๐Ÿค”

 

๋งŒ์•ฝ ๋ฐฐํ„ฐ๋ฆฌ๊ฐ€ ์ผ์ฒดํ˜•์ธ ์ž๋™์ฐจ ์žฅ๋‚œ๊ฐ ๐Ÿš— ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ• ๊ฒŒ์š”.

 

์ด ์ž๋™์ฐจ ์žฅ๋‚œ๊ฐ์€ ๋ฐฐํ„ฐ๋ฆฌ๊ฐ€ ๋‹ค ๋‹ณ๊ฒŒ ๋˜๋ฉด ๋” ์ด์ƒ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

์ด ๊ฒฝ์šฐ ์ž๋™์ฐจ ์žฅ๋‚œ๊ฐ์€ ๋ฐฐํ„ฐ๋ฆฌ์— ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ฝ”๋“œ๋กœ ์„ค๋ช…์„ ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

class ToyCar {
    var battery:Battery = Battery()
}

class Battery {
    var energy:Int = 100
}

 

ToyCar ํด๋ž˜์Šค์˜ battery๋Š” ๋ฐฐํ„ฐ๋ฆฌ ํด๋ž˜์Šค๋ฅผ ๋‚ด๋ถ€์—์„œ ์ง์ ‘ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๋‚ด๋ถ€์— ์ƒ์„ฑ๋œ Battery ํด๋ž˜์Šค์˜ energy๊ฐ€ ๋‹ค ๋‹ณ๊ฒŒ ๋˜๋ฉด ToyCar ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—

 

ToyCar ํด๋ž˜์Šค๊ฐ€ Battery ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.


์˜์กด์„ฑ ์ฃผ์ž…์ด๋ž€?

 

"์†Œํ”„ํŠธ์›จ์–ด ์—”์ง€๋‹ˆ์–ด๋ง์—์„œ ์˜์กด์„ฑ ์ฃผ์ž…(dependency injection)์€ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด์˜ ์˜์กด์„ฑ์„ ์ œ๊ณตํ•˜๋Š” ํ…Œํฌ๋‹‰์ด๋‹ค. "์˜์กด์„ฑ"์€ ์˜ˆ๋ฅผ ๋“ค์–ด ์„œ๋น„์Šค๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์ด๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์–ด๋–ค ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ์ง€ ์ง€์ •ํ•˜๋Š” ๋Œ€์‹ , ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฌด์Šจ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ์ง€๋ฅผ ๋งํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. "์ฃผ์ž…"์€ ์˜์กด์„ฑ(์„œ๋น„์Šค)์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฐ์ฒด(ํด๋ผ์ด์–ธํŠธ)๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์„œ๋น„์Šค๋Š” ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ์˜ ์ผ๋ถ€์ด๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋น„์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๊ฑฐ๋‚˜ ์ฐพ๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋Š” ๋Œ€์‹  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์„œ๋น„์Šค๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ํŒจํ„ด์˜ ๊ธฐ๋ณธ ์š”๊ฑด์ด๋‹ค." - ์œ„ํ‚ค ๋ฐฑ๊ณผ -

 

์ฆ‰, ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์™ธ๋ถ€์—์„œ ํด๋ž˜์Šค๋ฅผ ์ฃผ์ž…ํ•ด์ฃผ๋Š” ๊ฒƒ์ด์ฃ .

 

์ด๋ ‡๊ฒŒ ๋งํ•˜๋ฉด ์ดํ•ดํ•˜๊ธฐ ํž˜๋“œ์‹ค๊ฑฐ์—์š”.

 

์˜ˆ์ œ๋ฅผ ํ†ตํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


์˜์กด์„ฑ ์ฃผ์ž…ํ•ด๋ณด๊ธฐ

 

์œ„์—์„œ ์„ค๋ช…ํ•œ ์ž๋™์ฐจ ์žฅ๋‚œ๊ฐ์„ ์˜ˆ์‹œ๋กœ ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค.

 

battery๋ฅผ ๋‚ด๋ถ€์—์„œ ์ƒ์„ฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐํ„ฐ๋ฆฌ์— ์˜์กดํ•˜๊ณ  ์žˆ๋Š”๊ฒŒ ๋ฌธ์ œ๋ผ๊ณ  ํ–ˆ์—ˆ์ฃ ?

 

์•„๋ž˜์™€ ๊ฐ™์ด battery๋ฅผ ToyCar ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— battery๋ฅผ ์™ธ๋ถ€์—์„œ ์ ์šฉ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฐฐํ„ฐ๋ฆฌ๋ฅผ ์™ธ๋ถ€์—์„œ ๋ฐ›๊ฒŒ ๋˜๊ณ  ๋ฐฐํ„ฐ๋ฆฌ๊ฐ€ ๋‹ค ๋‹ณ์•„์ ธ๋„

 

๋‹ค๋ฅธ ๋ฐฐํ„ฐ๋ฆฌ๋ฅผ ์™ธ๋ถ€์—์„œ ๋ฐ›์•„์„œ ์ ์šฉํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์˜์กด์„ฑ์ด ๋‚ฎ์•„์ง‘๋‹ˆ๋‹ค.

 

class ToyCar {
    var battery:Battery
    
    init(battery:Battery) {
        self.battery = battery
    }
    
    func setBattery(battery:Battery) {
        self.battery = battery
    }
}
//ToyCar(battery: Battery())

 

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๊ฐ€ ๋˜ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

๋งŒ์•ฝ ๋ฐฐํ„ฐ๋ฆฌ๊ฐ€ ์•„๋‹Œ ์ฝ”๋“œ๋กœ ์ถฉ์ „ํ•˜๋Š” ์ž๋™์ฐจ ์žฅ๋‚œ๊ฐ์ด ์žˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”?

 

์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐฐํ„ฐ๋ฆฌ๋กœ ๋œ ์ž๋™์ฐจ ์žฅ๋‚œ๊ฐ ํด๋ž˜์Šค์™€ ์ฝ”๋“œ๋กœ๋œ ์ž๋™์ฐจ ์žฅ๋‚œ๊ฐ ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์ค˜์•ผ๊ฒ ์ฃ ?

 

class BatteryToyCar {
    var battery:Battery
    
    init(battery:Battery) {
        self.battery = battery
    }
}

class CodeToyCar {
    var code:Code
    
    init(code:Code) {
        self.code = code
    }
}

 

๊ณ ๋กœ ๊ณตํ†ต์ ์ธ ๋ถ€๋ถ„์ด ์žˆ๋Š” Charger ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋กœ ์ƒ์„ฑํ•˜์—ฌ ๋ฐฐํ„ฐ๋ฆฌ์™€ ์ฝ”๋“œ ํด๋ž˜์Šค์— ์ฃผ์ž…ํ•ด์ค๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Battery,Code ํด๋ž˜์Šค ๋ชจ๋‘ Charger ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด๋Š” ํด๋ž˜์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ ๋‹ค์Œ ToyCar battery๋ฅผ charger๋กœ ๋ชจ๋‘ ๋ฐ”๊ฟ”์ฃผ๋ฉด ToyCar๋Š” ๋ฐฐํ„ฐ๋ฆฌ๋กœ ์ถฉ์ „ํ•˜๋“  ์ฝ”๋“œ๋กœ ์ถฉ์ „ํ•˜๋“  ์ƒ๊ด€์ด ์—†๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

 

 

protocol Charger {
}

class ToyCar {
    var charger:Charger
    
    init(charger:Charger) {
        self.charger = charger
    }
    
    func setCharger(charger:Charger) {
        self.charger = charger
    }
}


class Battery:Charger {
    var energy:Int = 100
}

class Code:Charger {
    var volt:Int = 220
}

 

๋งŒ์•ฝ ์—ฌ๊ธฐ์„œ ์ถฉ์ „๊ธฐ์— ์ถฉ์ „ํ•˜๋Š” ํ•จ์ˆ˜์™€ ์ถฉ์ „์„ ๋ฉˆ์ถ”๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ๊ตฌํ˜„ํ•ด๋†“์œผ๋ฉด 

 

protocol Charger {
    func charge()
    func stopCharge()
}

 

Charger์— ํ•„์š”ํ•œ ์ฝ”๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์–ด ์ฝ”๋“œ๋ฅผ ์žฌํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

 

class Battery:Charger {

    var energy:Int = 100
    
    func charge() {
    }
    
    func stopCharge() {
    }
}

class Code:Charger {
    
    var volt:Int = 220
    
    func charge() {
    }
    
    func stopCharge() {
    }
}

์˜์กด์„ฑ ์ฃผ์ž…์„ ํ•˜๋ฉด ์™œ ํ…Œ์ŠคํŠธ๊ฐ€ ํŽธํ•ด์งˆ๊นŒ? ๐Ÿง

 

์šฐ์„  ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ๋Š” ํ•„์ˆ˜์ ์œผ๋กœ ๊ฐ€์งœ(Mock) ๋ฐ์ดํ„ฐ,์„œ๋น„์Šค,๋ฐธ๋ฆฌ๋ฐ์ดํ„ฐ ๋“ฑ์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

ํšŒ์›๊ฐ€์ž…์„ ํ•  ๋•Œ ์›น์„œ๋น„์Šค๋ฅผ ์˜์กด์„ฑ ์ฃผ์ž…์—†์ด ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

class SignUpWebService {
    
    private var urlSession:URLSession
    private var urlString:String
    
    init(urlString:String,urlSession:URLSession = .shared) {
        self.urlString = urlString
        self.urlSession = urlSession
    }
    
    func signUp(with requestModel:SignUpRequestModel,completion:@escaping(SignUpResponseModel?,SignUpError?)-> Void) {
        guard let url = URL(string: urlString) else {
            completion(nil,SignUpError.invalidRequestURLString)
            return
        }
        
        ...
}

 

๊ทธ ๋‹ค์Œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ ค๊ณ  ๊ฐ€์งœํšŒ์›๊ฐ€์ž… ์›น์„œ๋น„์Šค๋ฅผ ๋งŒ๋“œ๋ ค๊ณ  ํ•  ๋•Œ ์ง์ ‘ ํšŒ์›๊ฐ€์ž… ์›น์„œ๋น„์Šค์— ์–ด๋–ค ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ๋Š”์ง€ 

 

์–ด๋–ค ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ๋Š”์ง€ ์ง์ ‘ ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

 

๋˜ํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ ๋นผ๋จน์„ ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ๋ฅผ ๋นผ๋จน์„ ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

 

class MockSignUpWebService {
    
    var isSignUpMethodCalled:Bool  = false
    var shouldReturnError:Bool = false
    
   ...
}

 

ํ•˜์ง€๋งŒ ์•„๋ž˜์™€ ๊ฐ™์ด ํšŒ์›๊ฐ€์ž…์›น์„œ๋น„์Šค ํ”„๋กœํ† ์ฝœ์œผ๋กœ ํ•„์š”ํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ ๋ฏธ๋ฆฌ ์ •์˜ํ•ด๋‘๊ณ 

 

protocol SignUpWebServiceProtocol {
    func signUp(with requestModel:SignUpRequestModel,completion:@escaping(SignUpResponseModel?,SignUpError?)-> Void)
}

 

๊ฐ€์งœ ์›น์„œ๋น„์Šค์— ์ฑ„ํƒํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ค ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•„์š”ํ•œ์ง€ ์ž๋™์œผ๋กœ ์„ธํŒ…๋˜์–ด ๋นผ๋จน์„ ๊ฐ€๋Šฅ์„ฑ์ด ์—†๊ณ  ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

 

class MockSignUpWebService:SignUpWebServiceProtocol {
    
    var isSignUpMethodCalled:Bool  = false
    var shouldReturnError:Bool = false
    
    func signUp(with requestModel: SignUpRequestModel, completion: @escaping (SignUpResponseModel?, SignUpError?) -> Void) {
        isSignUpMethodCalled = true
        
        if shouldReturnError {
            completion(nil,SignUpError.failedRequest(description: "SignUp request was not successful"))
        }else {
            let response = SignUpResponseModel(status: "ok")
            completion(response,nil)
        }
    
    }
}

์ •๋ฆฌ

 

์˜์กด์„ฑ ์ฃผ์ž…์€ ํด๋ž˜์Šค ๋‚ด๋ถ€์— ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ์™ธ๋ถ€์—์„œ ์ฃผ์ž…๋ฐ›๋Š” ๊ฒƒ์ด๋‹ค.

 

์˜์กด์„ฑ ์ฃผ์ž…์„ ํ•ด์•ผํ•˜๋Š” ์ด์œ ๋Š” ๊ฐ ํด๋ž˜์Šค๊ฐ„ ์˜์กดํ•˜์ง€ ์•Š๊ฒŒ ํ•˜์—ฌ ํ•œ ํด๋ž˜์Šค์—์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋”๋ผ๋„ 

 

ํ•ด๋‹น ํด๋ž˜์Šค๋งŒ ๊ณ ์น˜๋ฉด ๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.

 

๊ณตํ†ต์ ์ธ ๋ถ€๋ถ„์„ ํ”„๋กœํ† ์ฝœ๋กœ ๋ฏธ๋ฆฌ ์ •์˜ํ•ด๋‘๊ณ  ๊ฐ ํด๋ž˜์Šค์— ์ฑ„ํƒํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ 

 

๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๋”๋ผ๋„ ํ”„ํ† ์ฝ”์ฝœ๋งŒ ์ฑ„ํƒํ•ด์ฃผ๋ฉด ๊ฐ„ํŽธํ•˜๊ฒŒ ์ฃผ์ž…ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

 

๋˜ํ•œ ํ…Œ์ŠคํŠธ ์‹œ Mock ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ์‹ค์ˆ˜์—†์ด ์ž‘์„ฑํ•˜๊ฒŒ ํ•˜์—ฌ 

 

ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ„ํŽธํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.


Reference

 

https://devlog-wjdrbs96.tistory.com/165

 

https://lsh424.tistory.com/86

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€