Dependency Injection - ehrldyd15/Swift_Skills GitHub Wiki

Dependency Injection

์˜์กด์„ฑ์ด๋ž€(Dependency)?

์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด ์‚ฌ์ด์— ์˜์กด ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, ์˜์กดํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์ˆ˜์ •๋˜๋ฉด, ๋‹ค๋ฅธ ๊ฐ์ฒด๋„ ์˜ํ–ฅ์„ ๋ฐ›์Œ

import UIKit

struct Eat {
    func coffee() {
        print("์•„๋ฉ”๋ฆฌ์นด๋…ธ")
    }

    func meal() {
        print("ํ”ผ์ž")
    }
}

struct Person {
    var todayEat: Eat // Eat์— ๋Œ€ํ•œ ์˜์กด์„ฑ์ด ์ƒ๊ธด๋‹ค.
    
    func coffee() {
        todayEat.coffee()
    }
    
    func meal() {
        todayEat.meal()
    }
}

Person๊ฐ์ฒด๋Š” Eat๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šค๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, Eat๊ฐ์ฒด์— ์˜์กด์„ฑ์ด ์ƒ๊ธด๋‹ค.

๋งŒ์•ฝ ์ด๋•Œ, Eat ๊ฐ์ฒด์— ์ค‘์š”ํ•œ ์ˆ˜์ •์ด๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, Person ๊ฐ์ฒด๋„ ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

์˜์กด์„ฑ์„ ๊ฐ€์ง€๋Š” ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„์ง„๋‹ค๋ฉด, ์žฌํ™œ์šฉ์„ฑ์ด ๋–จ์–ด์ง€๊ณ  ๋งค๋ฒˆ ์˜์กด์„ฑ์„ ๊ฐ€์ง€๋Š” ๊ฐ์ฒด๋“ค์„ ํ•จ๊ป˜ ์ˆ˜์ •ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๋Ÿฌํ•œ ์˜์กด์„ฑ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ ๊ฐœ๋…์ด ๋ฐ”๋กœ Dependency Injection, ์˜์กด์„ฑ ์ฃผ์ž…์ด๋‹ค.

์ฃผ์ž…์ด๋ž€?(Injection)

Injection, ์ฃผ์ž…์€ ์™ธ๋ถ€์—์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋„ฃ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

class Eat:Menu {
    var coffee: String
    var meal: String
    
    init(coffee: String, meal: String) {
        self.coffee = coffee
        self.meal = meal
    }
    
    func printCoffee() {
        print("์•„๋ฉ”๋ฆฌ์นด๋…ธ")
    }
    
    func printMeal() {
        print("ํ”ผ์ž")
    }
}

let menu = Eat(coffee: "์•„๋ฉ”๋ฆฌ์นด๋…ธ", meal: "ํ”ผ์ž")

์ƒ์„ฑ์ž๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)

์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๋Š” ์ด์œ ๋Š”?

  • Unit Test๊ฐ€ ์šฉ์ดํ•˜๋‹ค.
  • ์ฝ”๋“œ์˜ ์žฌํ™œ์šฉ์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.
  • ๊ฐ์ฒด ๊ฐ„์˜ ์˜์กด์„ฑ(์ข…์†์„ฑ)์„ ์ค„์ด๊ฑฐ๋‚˜ ์—†์•จ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ์ฒด ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋ฉด์„œ ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‚ด๋ถ€์—์„œ ๋งŒ๋“  ๊ฐ์ฒด๋ฅผ ์™ธ๋ถ€์—์„œ ๋„ฃ์–ด์„œ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๊ธฐ ์ „์— '์˜์กด ๊ด€๊ณ„ ์—ญ์ „ ๋ฒ•์น™'์„ ์•Œ์•„๋ณด์ž

์˜์กด ๊ด€๊ณ„ ์—ญ์ „ ๋ฒ•์น™(Dependency Inversion Principle)

DIP, ์˜์กด ๊ด€๊ณ„ ์—ญ์ „ ๋ฒ•์น™์€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์„ค๊ณ„์˜ ๋‹ค์„ฏ๊ฐ€์ง€ ๊ธฐ๋ณธ ์›์น™(SOLID) ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

์ถ”์ƒํ™” ๋œ ๊ฒƒ์€ ๊ตฌ์ฒด์ ์ธ ๊ฒƒ์— ์˜์กดํ•˜๋ฉด ์•ˆ๋˜๊ณ , ๊ตฌ์ฒด์ ์ธ ๊ฒƒ์ด ์ถ”์ƒํ™”๋œ ๊ฒƒ์— ์˜์กด ํ•ด์•ผํ•œ๋‹ค.

์ฆ‰, ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด๋Š” ์ถ”์ƒํ™”๋œ ๊ฐ์ฒด์— ์˜์กด ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด๋‹ค.

Swift์—์„œ ์ถ”์ƒํ™”๋œ ๊ฐ์ฒด๋Š” Protocol์ด ์žˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด Protocol์„ ํ™œ์šฉํ•ด์„œ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

์šฐ์„  Protocol์„ ํ™œ์šฉํ•ด์„œ ์ถ”์ƒ์ ์ธ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

Menu๋ผ๋Š” Protocol์€ printCoffee()์™€ printMeal()ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

protocol Menu {
    func printCoffee()
    func printMeal()
}

์ดํ›„ Eatํด๋ž˜์Šค๋Š” Menu Protocol์„ ์ฑ„ํƒํ•œ ํ›„,

Protocol์— ์ •์˜ํ•œ ํ•จ์ˆ˜๋ฅผ ์‹ค์ฒดํ™” ์‹œ์ผœ์ค€๋‹ค.

class Eat: Menu {
    var coffee: String
    var meal: String
    
    init(coffee: String, meal: String) {
        self.coffee = coffee
        self.meal = meal
    }
    
    func printCoffee() {
        print(coffee)
    }
    
    func printMeal() {
        print(meal)
    }
}

๊ธฐ์กด์˜ ๋ฐฉ์‹๊ณผ ๋‹ค๋ฅด๊ฒŒ todayEat๋ณ€์ˆ˜๋Š” ์ถ”์ƒ์ ์ธ ๊ฐ์ฒด์ธ Menuํƒ€์ž…์— ์˜์กดํ•˜๊ฒŒ ๋œ๋‹ค.

์—ฌ๊ธฐ์„œ changeMenuํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด์„œ ์˜์กด์„ฑ ์ฃผ์ž…์„ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

struct Person {
    var todayEat: Menu
    
    func printCoffee() {
        todayEat.printCoffee()
    }
    
    func printMeal() {
        todayEat.printMeal()
    }
    
    mutating func changeMenu(menu: Menu) {
        self.todayEat = menu
    }
}

์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด Eat๊ฐ์ฒด์™€ Person๊ฐ์ฒด๋Š” ๊ฑฐ์˜ ๋…๋ฆฝ์ ์ธ ๊ฐ์ฒด๊ฐ€ ๋œ๋‹ค.

Eat ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ Person์„ ์ˆ˜์ •ํ•œ๋‹ค๊ณ  ํ•ด์„œ ์ƒ๋Œ€ ๊ฐ์ฒด๋ฅผ ํ•จ๊ป˜ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

let menu = Eat(coffee: "์•„๋ฉ”๋ฆฌ์นด๋…ธ", meal: "ํ”ผ์ž")
let anotherMenu = Eat(coffee: "๋ผ๋–ผ", meal: "ํ–„๋ฒ„๊ฑฐ")

var suhshin = Person(todayEat: menu)

suhshin.printCoffee() // print ์•„๋ฉ”๋ฆฌ์นด๋…ธ
suhshin.changeMenu(menu: anotherMenu)
suhshin.printCoffee() // print ๋ผ๋–ผ

์ž๋ฃŒ์ถœ์ฒ˜

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