SOLID ์›์น™, in Swift

๋ฏผ๊ฒฝ์ค€ยท2023๋…„ 3์›” 20์ผ
1

Clean Architecture

๋ชฉ๋ก ๋ณด๊ธฐ
2/2

๐ŸŒŸ SOLID ์›์น™์ด๋ž€?

SOLID๋ผ๋Š” ์šฉ์–ด๋Š” ๊ฐ์ฒด ์„ค๊ณ„์— ํ•„์š”ํ•œ 5๊ฐ€์ง€ ์›์น™์˜ ์•ฝ์ž๋กœ, ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฝ๊ณ , ์œ ์—ฐํ•˜๊ณ , ํ™•์žฅ์ด ์‰ฌ์šด ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๋งŒ๋“œ๋Š”๊ฒƒ์„ ๋ชฉ์ ์œผ๋กœ ํ•œ๋‹ค.
Clean Agile, Clean Achitecture, Clean Code, Clean Software๋“ฑ์˜ ํด๋ฆฐ์ฝ”๋“œ์— ๋Œ€ํ•œ ์ฑ…์„ ๋งŽ์ด ์“ฐ์‹  ๋กœ๋ฒ„ํŠธ C.๋งˆํ‹ด(aka. Uncle Bob)์ด 2000๋…„์— ๋…ผ๋ฌธ "Design Principles and Design Patterns"์—์„œ ๋ฐœํ‘œํ•œ ๋‚ด์šฉ์ด๋‹ค.

์•ž์„œ ์„ค๋ช…ํ•œ๋Œ€๋กœ SOLID๋Š” ์•ฝ์–ด์ธ๋ฐ, ๊ฐ S๋Š” ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(Single Responsibility Principle), O๋Š” ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™(Open-Closed Principle), L์€ ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™(Liscov Substitution Principle), I๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™(Interface Segregation Principle), D๋Š” ์˜์กด์„ฑ ์—ญ์ „ ์›์น™(Dependency Inversion Principle)์„ ์˜๋ฏธํ•œ๋‹ค.

๐Ÿ”ฅ ๋‹จ์ผ ์ฑ…์ž„ ์›์น™, SRP(Single Responsibility Priciple)

๋‹จ์ผ ์ฑ…์ž„ ์›์น™์ด๋ž€?

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

Example

/// Before
class Factory {
	public func excute() {
    	let responseData = self.requestData()
        let parsingData = self.parse(data: responseData)
        self.save(item: parsingData)
    }
    
    private func requestData() -> Data {
    	/// Request Data And Wait Response 
    }
    
    private func parse(data: Data) -> [String] {
    	/// Parsing Responsed Data
    }
    
   	private func save(item: [String]) {
    	/// Save Item at Local DataBase
    }
}
/**
	ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ฑ…์ž„(private์œผ๋กœ ์ ‘๊ทผ์ œํ•œ ๋œ ๋‹ค์–‘ํ•œ ๋ฉ”์†Œ๋“œ๋“ค)์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
*/



/// After
class Factory {
	let requester = Requester()
    let converter = Converter()
    let database = Database()
    
    public func excute() {
    	let responseData = self.requester.getData()
        let parsingData = self.converter.convert(to: responseData)
        self.database.save(item: parsingData)
    }
}

class Requester {
	internal func getData() -> Data {
    	/// Request Data And Wait Response 
    }
}
class Converter {
	private func convert(to data: Data) -> [String] {
    	/// Parsing Responsed Data
    }
}
class Database {
	private func save(item: [String]) {
    	/// Save Item at Local DataBase
    }
}
/**
	ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๊ฐ€ ์ฑ…์ž„์„ ํ•˜๋‚˜์”ฉ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
*/

๐Ÿ”ฅ ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™, OCP(Open-Closed Principle)

๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™์ด๋ž€?

๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™์€ "์†Œํ”„ํŠธ์›จ์–ด ์—”ํ‹ฐํ‹ฐ(ํด๋ž˜์Šค, ๋ชจ๋“ˆ, ๊ธฐ๋Šฅ ๋“ฑ)๋Š” ํ™•์žฅ์—๋Š” ์—ด๋ ค ์žˆ์–ด์•ผ ํ•˜์ง€๋งŒ ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€์žˆ์–ด์•ผ ํ•œ๋‹ค" ๊ณ  ๋งํ•œ๋‹ค.

ํ™•์žฅ์— ์—ด๋ ค์žˆ๋‹ค๋Š” ๊ฒƒ์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ™•์žฅํ•  ๋•Œ ์‰ฝ๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋ฉฐ, ๋ณ€๊ฒฝ์— ๋‹ซํ˜€์žˆ๋‹ค๋Š” ๊ฒƒ์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ™•์žฅํ• ๋•Œ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝ ํ•˜์ง€ ์•Š๊ณ ๋„ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค๋Š”๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, ๊ธฐ์กด์˜ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๊ธฐ๋Šฅ์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•ด์•ผ ํ•˜๋Š” ์›์น™์ด๋‹ค.

์–ด๋–ค ๋ชจ๋“ˆ์ด๋‚˜ ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜ ์ˆ˜์ • ํ•  ๋•Œ, ๊ทธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ด์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ ์—ญ์‹œ ์ค„์ค„์ด ๊ณ ์ณ์•ผ ํ•œ๋‹ค๋ฉด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋ณต์žกํ•  ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™์„ ์ž˜ ์ ์šฉํ•˜์—ฌ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๊ธฐ๋Šฅ์„ ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ธ ์œ ์—ฐ์„ฑ, ์žฌ์‚ฌ์šฉ์„ฑ, ์œ ์ง€๋ณด์ˆ˜์„ฑ ๋“ฑ์„ ๋ชจ๋‘ ์žƒ์–ด๋ฒ„๋ฆฌ๋Š” ์…ˆ์ด๊ณ , OOP๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜๋ฏธ๊ฐ€ ์‚ฌ๋ผ์ง€๊ฒŒ ๋œ๋‹ค.

OCP ๋Š” ์ถ”์ƒํ™” (์ธํ„ฐํŽ˜์ด์Šค) ์™€ ์ƒ์† (๋‹คํ˜•์„ฑ) ๋“ฑ์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ์ž์ฃผ ๋ณ€ํ™”ํ•˜๋Š” ๋ถ€๋ถ„์„ ์ถ”์ƒํ™”ํ•จ์œผ๋กœ์จ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ์œผ๋กœ์จ ์œ ์—ฐํ•จ์„ ๋†’์ด๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด๋‹ค.

Example

/**
์บ๋ฆญํ„ฐ๋ฅผ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•œ๋‹ค๊ณ  ํ• ๋•Œ, ๊ฐ๊ฐ์˜ ์บ๋ฆญํ„ฐ๊ฐ€ ์›€์ง์ž„์ด ๋‹ค๋ฅผ ๊ฒฝ์šฐ ์›€์ง์ž„์˜ ํŒจํ„ด ๊ตฌํ˜„์„ ํ•˜์œ„ ํด๋ž˜์Šค์— ๋งก๊ธด๋‹ค๋ฉด 
์บ๋ฆญํ„ฐ ํด๋ž˜์Šค์˜ ์ˆ˜์ •์€ ํ•„์š”๊ฐ€์—†๊ณ (Closed) ์›€์ง์ž„์˜ ํŒจํ„ด๋งŒ ์žฌ์ •์˜ ํ•˜๋ฉด(Open) ๋œ๋‹ค.
*/

/// Before
enum Country {
	case korea
    case japan
    case usa
}

class Flag {
	let country: [Country]
    
    func name(_ country: Country) {
    	switch country {
        	case korea:
            	print("ํ•œ๊ตญ")
            case japan:
            	print("์ผ๋ณธ")
            case usa:
            	print("๋ฏธ๊ตญ")
        }
    }
}

/**
Country ์—ด๊ฑฐํ˜•์— case๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด name(_:) ํ•จ์ˆ˜๋„ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค. 
๊ฒฐํ•ฉ๋„์™€ ์˜์กด์„ฑ์ด ๋†’๊ณ , ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํž˜๋“ค๋‹ค.
*/


/// After
protocol Country {
	var name: String
}

struct Korea: Country {
	var name = "ํ•œ๊ตญ"
}
struct Japan: Country {
	var name = "์ผ๋ณธ"
}
struct USA: Country {
	var name = "๋ฏธ๊ตญ"
}

class Flag {
	var country: [Country]
    
    func name(_ country: Country) {
    	print(country.name)
    }
}

/**
๋‚˜๋ผ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Country๋ฅผ ์ฑ„ํƒํ•˜๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค. 
๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ๊ณ , ์‘์ง‘๋„๊ฐ€ ๋†’์•„ ์œ ์ง€๋ณด์ˆ˜์— ์šฉ์ดํ•˜๋‹ค
*/

๐Ÿ”ฅ ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™, LSP(Liskov Substitution Principle)

๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™์ด๋ž€?

๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™์€ "์ž์‹ ํด๋ž˜์Šค๋Š” ์–ธ์ œ๋‚˜ ์ž์‹ ์˜ ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค." ๊ณ  ๋งํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด C๋ผ๋Š” ํด๋ž˜์Šค์—์„œ A๋ผ๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ B๋ผ๋Š” A๋ฅผ ์ƒ์†๋ฐ›์€ ์ž์‹ ํด๋ž˜์Šค๋กœ ๋Œ€์ฒดํ•ด๋„ C๋ผ๋Š” ํด๋ž˜์Šค์—์„œ๋Š” ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์—†์ด ์ •์ƒ์ ์œผ๋กœ ๊ฐ™์€ ๋™์ž‘์„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

Example


/// Before
class Rectangle {
    var width: Int
    var height: Int
    
    var area: Int {
    	return width * height
    }

    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}

class Square: Rectangle {
    override var width: Int {
        didSet {
            super.height = width
        }
    }

    override var height: Int {
        didSet {
            super.width = height
        }
    }
}


let sqaure = Sqaure(width: 10, height: 10)
self.checkArea(of: sqaure)

func checkArea(of item: Rectangle) {
	item.width = 9
    item.height = 3
    
    print(item.area)
}

/**
	ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ง์‚ฌ๊ฐํ˜•์˜ ๋ฉด์ ์ด 9*3์„ ์˜ˆ์ƒํ•˜๊ฒ ์ง€๋งŒ, ์‹ค์ œ๋กœ 3*3์ด ์ถœ๋ ฅ๋œ๋‹ค.
    ์ด๋Š” ์ž˜๋ชป๋œ ๋™์ž‘์„ ์‹คํ–‰ํ•œ ๊ฒƒ์ด๊ณ , ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ์Šˆํผํด๋ž˜์Šค ๋Œ€์‹  ์‚ฌ์šฉ๋˜๋„ ๊ฐ™์€ ๋™์ž‘์„ ํ•œ๋‹ค๊ณ  ๋ณด๊ธฐ ์–ด๋ ต๋‹ค.
*/



/// After
protocol Geometrics {
    var area: Int
}

class Rectangle: Geometrics {
	var width: Int
    var height: Int
    var area: Int {
    	return width * height
    }
    
    init(width: Int, height: Int) {
    	self.width = width
        self.height = height
    }
}
class Square: Geometrics {
	var edge: Int
    var area: Int {
    	return edge * edge
    }
    
    init(edge: Int) {
    	self.edge = edge
    }
}


// print -> 50
let geometric1: Geometrics = Rectangle(width: 10, height: 5)
print(geometric1.area)

// print -> 25
let geometric2: Geometrics = Sqaure(edge: 5)
print(geometric2.area)

/**
	์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๋ฐ”๋€Œ์–ด๋„ ๊ฐ™์€ ๋™์ž‘์„ ํ•ด๋‚ธ๋‹ค.
	๋‘ ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•  ๋™์ผํ•œ ๊ฐ’์„ ํ”„๋กœํ† ์ฝœ์„ ์ƒ์†๋ฐ›๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์žฅํ–ˆ๋‹ค.
    ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•„์š”ํ•œ ๊ฐ’์ด๋‚˜ ๋™์ž‘๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—
    ์˜ˆ์ƒ ๊ฐ€๋Šฅํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
*/

๐Ÿ”ฅ ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™, ISP(Interface Segregation Principle)

์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™์ด๋ž€?

์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™์€ "ํด๋ผ์ด์–ธํŠธ๋Š” ๋ถˆํ•„์š”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค. ์ฆ‰, ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌํ˜„ํ•˜์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค." ๊ณ  ๋งํ•œ๋‹ค. Uncle Bob์ด ๋…ผ๋ฌธ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์šฉ์–ด๋กœ Fat Interface๊ฐ€ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค(Swift - Protocol)๋Š” ์‘์ง‘๋ ฅ์ด ์—†๋‹ค๊ณ  ๊ฐ„์ฃผ๋œ๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์€ ๋ฉ”์„œ๋“œ/๊ธฐ๋Šฅ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ  ๊ธฐ๋ณธ์ ์œผ๋กœ ๋šฑ๋šฑํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ISP ์›์น™์„ ๋”ฐ๋ฅด์ง€ ์•Š๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

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

Example

/// Before
protocol Animal {
	func run()
    func swim()
    func fly()
}

class Dolphin: Animal {
	func swim()
    
    /// NOT USED
    func run() { }
    func fly() { }
}
class Dog: Animal {
	func run() { }
    func swim() { }
    
    /// NOT USED
    func fly() { }
}
class Duck: Animal {
	func fly() { }
    func run() { }
    func swim() { }
}

/**
	Duck์€ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜์ง€๋งŒ Dog, Dolphin์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜๋“ค์ด ์กด์žฌํ•œ๋‹ค.
*/


/// After
protocol Runable {
	func run()
}
protocol Swimable {
	func swim()
}
protocol Flyable {
	func fly()
}

class Dolphin: Swimable {
	func swim() { }
}
class Dog: Runable, Swimable {
	func run() { }
    func swim() { }
}
class Duck: Runable, Swimable, Flyable {
	func fly() { }
    func run() { }
    func swim() { } 
}
/**
	ํ”„๋กœํ† ์ฝœ์„ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ํ•„์š”ํ•œ ํ”„๋กœํ† ์ฝœ๋งŒ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜๋Š” ์ œ๊ฑฐํ•˜๋„๋ก ํ–ˆ๋‹ค.
*/

๐Ÿ”ฅ ์˜์กด ์—ญ์ „ ์›์น™, DIP(Dependency Inversion Principle)

์˜์กด ์—ญ์ „ ์›์น™์ด๋ž€?

์˜์กด ์—ญ์ „ ์›์น™์€ "์ƒ์œ„ ๋ ˆ๋ฒจ ๋ชจ๋“ˆ์€ ํ•˜์œ„ ๋ ˆ๋ฒจ ๋ชจ๋“ˆ์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค. ๋‘˜ ๋‹ค ์ถ”์ƒํ™”์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค." ๋ผ๊ณ  ๋งํ•œ๋‹ค. ์ฆ‰, ๊ตฌ์ฒดํ™”๋œ ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ธฐ ๋ณด๋‹จ ์ถ”์ƒ์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋‚˜ ์ถ”์ƒํด๋ž˜์Šค์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋ง์ด๋‹ค. ์ €์ˆ˜์ค€์˜ ๋ชจ๋“ˆ์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ๊ณ ์ˆ˜์ค€์˜ ๋ชจ๋“ˆ์€ ๋ณ€๊ฒฝ์ด ํ•„์š”์—†๋Š” ํ˜•ํƒœ๊ฐ€ ๊ฐ€์žฅ ์ด์ƒ์ ์ด๋‹ค.

๋ถˆ๋Ÿ‰ ์„ค๊ณ„

DIP์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ธฐ ์ „์— ๊ฐœ๋ฐœ์ž ์„ธ๊ณ„์—์„œ ํ”ํžˆ ๋“ค์„ ์ˆ˜ ์žˆ๋Š” Bad Design์— ๋Œ€ํ•ด ๊ฐ„๋‹จํžˆ ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž.
* Design Smells๋ผ๊ณ  ๋ถˆ๋ฆฌ๊ธฐ๋„ ํ•œ๋‹ค.

๋ถˆ๋Ÿ‰ ์„ค๊ณ„๋ž€ ์†Œํ”„ํŠธ์›จ์–ด๋‚˜ ํ”„๋กœ์ ํŠธ ์ „์ฒด๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๊ณ„๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•˜๋Š” ์ƒํƒœ๋ฅผ ๋œปํ•œ๋‹ค. ๋•Œ๋กœ๋Š” ์ข‹์€ ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„๊ฐ€ ๋˜์—ˆ์ง€๋งŒ ์‹œ๊ฐ„์ด ์ง€๋‚˜๊ณ  ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์„ ๊ฑฐ์น˜๋ฉด์„œ ์ž˜๋ชป ์„ค๊ณ„๋œ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๋˜๋Š” ์ผ๋„ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๊ณ„๋œ ์†Œํ”„ํŠธ์›จ์–ด์ธ์ง€ ์•„๋‹Œ์ง€ ๊ตฌ๋ถ„์€ ์–ด๋–ป๊ฒŒ ํ• ๊นŒ? ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋”๋ผ๋„ ๋‹ค์Œ ํŠน์„ฑ ์ค‘ ์ผ๋ถ€๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ์ž˜๋ชป ์„ค๊ณ„๋œ ๊ฒƒ์œผ๋กœ ๋ถ„๋ฅ˜ ๋  ์ˆ˜ ์žˆ๋‹ค.

  1. ๊ฒฝ์ง์„ฑ: ์‹œ์Šคํ…œ ๋ณ€๊ฒฝ์ด ์–ด๋ ต๋‹ค. ํ•˜๋‚˜๋ฅผ ๋ฐ”๊พธ๋ ค๊ณ  ํ•  ๋•Œ๋งˆ๋‹ค, ๋‹ค๋ฅธ ๊ฒƒ๋“ค๋„ ๋์—†์ด ๋ฐ”๊พธ์–ด์•ผ ํ•œ๋‹ค.
  2. ์ทจ์•ฝ์„ฑ: ํ•œ ๋ถ€๋ถ„์˜ ์ˆ˜์ •์ด ๋‹ค๋ฅธ ๋งŽ์€ ๋ถ€๋ถ„๋“ค, ์—ฐ๊ด€์ด ์—†๋Š” ๋ถ€๋ถ„์— ๊นŒ์ง€ ์˜ํ–ฅ์„ ์ค€๋‹ค.
  3. ๋†’์€ ๊ฒฐํ•ฉ๋„: ๋ชจ๋“ˆ๊ฐ„์˜ ์˜์กดํ•˜๋Š” ์ •๋„๊ฐ€ ํฌ๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ์šฐ๋ฆฌ๋„ ๋ชจ๋ฅด๊ฒŒ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์— ์˜ํ–ฅ(Side Effect)์„ ๋ผ์น  ์ˆ˜ ์žˆ๋‹ค.
    ๋˜ํ•œ, ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ ํ–ˆ์„ ๋•Œ๋„ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—๋„ ์˜ํ–ฅ์„ ๋ผ์น  ์ˆ˜ ์žˆ๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ ์˜ํ–ฅ์„ ๋ฐ›์•„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ์ˆ˜๋„ ์žˆ๊ฒŒ ๋œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ฝ๋‹ค๋ณด๋‹ˆ ์™œ ์ด๊ฒƒ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ ํ•˜๊ณ  ์žˆ๋Š”์ง€ DIP์™€ ๋ฌด์Šจ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ์˜๋ฌธ์ด ๋“ค๊ฒƒ์ด๊ณ  ๊ทธ๊ฒŒ ๋‹น์—ฐํ•˜๋‹ค. ๋‹ต์€ ๊ฐ„๋‹จํ•˜๋‹ค DIP๋Š” ์ข‹์€ ๋””์ž์ธ์— ์ •๋น„๋ก€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ‰, ์ด ์›์น™์„ ์ค€์ˆ˜ํ•  ๋•Œ ๊ฐœ๋ฐœ๋œ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ์ทจ์•ฝํ•˜์ง€ ์•Š๊ณ , ๊ฒฝ์ง๋˜์ง€ ์•Š์•˜์œผ๋ฉฐ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์€ ๊ฒฝํ–ฅ์ด ์žˆ๋‹ค. DIP๋ฅผ ์ค€์ˆ˜ํ•˜๋ฉด ๋ถˆ๋Ÿ‰์„ค๊ณ„๋ฅผ ํ•˜๊ฒŒ๋  ํ™•๋ฅ ์ด ์ค„์–ด๋“ ๋‹ค๋Š” ๋œป์ด๋‹ค.

๋ถˆ๋Ÿ‰ ์„ค๊ณ„์˜ ์ด์œ 

์šฐ๋ฆฌ๋Š” ๋ฐฉ๊ธˆ ๋ถˆ๋Ÿ‰ ์„ค๊ณ„์˜ ํŠน์ง•๋“ค์— ๋Œ€ํ•ด์„œ ์–˜๊ธฐํ–ˆ๋‹ค. ์ด์ œ๋Š” ๊ฐ ์›์ธ๋“ค์ด ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด์ž.

๊ฒฝ์ง์„ฑ์ด ์˜ฌ๋ผ๊ฐ€๋Š” ์ด์œ 

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

์ทจ์•ฝ์„ฑ์ด ์˜ฌ๋ผ๊ฐ€๋Š” ์ด์œ 

  • ๋˜, OCP ์›์น™์„ ๋ฌด์‹œํ•˜๋Š” ๊ฒฝ์šฐ ์†Œํ”„ํŠธ์›จ์–ด์—์„œ ํ™•์žฅ์ด ํ•„์š”ํ•  ๋•Œ ์ˆ˜์ •์ด ์š”๊ตฌ๋˜๋Š”๋ฐ ๊ฐ€๋” ๋นŒ๋“œ ํƒ€์ด๋ฐ์—๋Š” ์ด๊ฒƒ์„ ์•Œ์•„์ฑ„์ง€ ๋ชปํ•˜๊ณ  ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ์ฆ‰, ํ•„์š”ํ•œ ์ˆ˜์ •์ด ์ด๋ค„์ง€์ง€ ์•Š๊ฒŒ๋˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์œ„ํ—˜์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ทจ์•ฝ์„ฑ์ด ์˜ฌ๋ผ๊ฐ„๋‹ค.
  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ถ”์ƒํ™”์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ๊ตฌ์กฐ์— ์˜์กดํ•˜๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋‹ค. ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ• ๋•Œ ๋‹ค๋ฅธ๊ณณ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๊ณ  ์ด๊ฒƒ์ด ํ˜„์žฌ ๊ธฐ๋Šฅ์„ ์ค‘๋‹จ์‹œํ‚ฌ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ทจ์•ฝ์„ฑ์ด ์˜ฌ๋ผ๊ฐ€๊ฒŒ ๋œ๋‹ค.

๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ง€๋Š” ์ด์œ 

  • ์—ญ์‹œ๋‚˜ ์ถ”์ƒํ™”์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ๊ตฌ์กฐ์— ์˜์กดํ•˜๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋‹ค. ์ด๋Š” ๊ตฌ์กฐ๊ฐ€ ๋‹ค๋ฅธ ๊ตฌ์กฐ์— ์˜์กดํ•˜๊ฒŒ ๋˜๋ฉด์„œ ์žฌ์‚ฌ์šฉ์ด ๋งค์šฐ ์–ด๋ ค์›Œ์ง€๋ฉด์„œ ์ฝ”๋“œ๊ฐ€ ๊ฒฐํ•ฉ๋˜์–ด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ง€๊ฒŒ ๋œ๋‹ค.

WA! ๋‹ค์‹œ DIP ์ •์˜๋กœ ๋Œ์•„๊ฐ€๋ณด์ž. ์ง€๊ธˆ๊นŒ์ง€ ๋ถˆ๋Ÿ‰ ์„ค๊ณ„์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ์ด ๋ฌธ๊ตฌ๋Š” DIP๋ฅผ ์—ญ์œผ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ๊ตฌ์ด๋‹ค.

์ถ”์ƒํ™”์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ๊ตฌ์กฐ์— ์˜์กดํ•˜๋Š” ๊ฒฝ์šฐ.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด ์›์น™์ด ์ข‹์€ ์„ค๊ณ„์™€ ์ •๋น„๋ก€ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ์ด ์›์น™์„ ๋”ฐ๋ฅด์ง€ ์•Š์œผ๋ฉด ๊ฒฝ์ง์„ฑ, ์ทจ์•ฝ์„ฑ์ด ์˜ฌ๋ผ๊ฐ€๊ณ  ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์€ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์„ค๊ณ„ํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๊ฒƒ์€ ๋งค์šฐ ์ž˜๋ชป ์„ค๊ณ„๋œ ์†Œํ”„ํŠธ์›จ์–ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค๋ฅธ ์›์น™๋“ค๊ณผ์˜ ๊ด€๊ณ„

๋จผ์ € ์งง๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด DIP๋Š” OCP์™€ LSP์˜ ๊ฒฐ๊ณผ์ด๋‹ค. OCP์™€ LSP๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋“ค์€ ๋ชจ๋‘ ์ถ”์ƒํ™”๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์œ„์—์„œ OCP์™€ LSP๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ๋ชจ๋‘ ์ถ”์ƒํ™”๋กœ ํ•ด๊ฒฐํ–ˆ๋‹ค. ํด๋ž˜์Šค๋Š” ๋‹ค๋ฅธ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ์ถ”์ƒํ™”(ํ”„๋กœํ† ์ฝœ)์— ์˜์กดํ•˜๊ฒŒ ํ–ˆ๊ณ , ์ด๋ฅผ ์œ„ํ•ด ์„ธ๋ถ€ํ™”(ํด๋ž˜์Šค) ๋˜ํ•œ ์ถ”์ƒํ™”์— ์˜์กดํ•˜๊ฒŒ ํ–ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ OCP์™€ LSP๋ฅผ ๋”ฐ๋ฅด๊ธฐ ์œ„ํ•ด DIP๋ฅผ ๋”ฐ๋ผ์•ผ ํ•œ๋‹ค.

Example

class Order {
	let menu = Menu(price: 5000)
}
class Menu {
	var price: Int
    init(price: Int) {
    	self.price = price
    }
}

let order = Order()
print(order.menu.price) // 5000

/**
	์ด๋ ‡๊ฒŒ ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ํ•ด๋‹น ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ฒŒ ๋˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์ƒ๊ธด๋‹ค.
*/


/// ์˜์กด์„ฑ ์ฃผ์ž…, Dependency Injection
class Order {
	let menu: Menu
    init(menu: Menu) {
    	self.menu = menu
    }
}
class Menu {
	var price: Int
    init(price: Int) {
    	self.price = price
    }
}

let menu = Menu(price: 7000)
let order = Order(menu: menu)
print(order.menu.price) // 7000

/**
	์ด๋ ‡๊ฒŒ ์™ธ๋ถ€์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ ํ›„ ๋„ฃ์–ด์ฃผ๋Š”๊ฒƒ์„ ์˜์กด์„ฑ ์ฃผ์ž…์ด๋ผ๊ณ  ํ•œ๋‹ค.
    ํ•˜์ง€๋งŒ, ์•„์ง ์ถ”์ƒํ™”์— ์˜์กดํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ํ•˜๋Š”๋ฐ ๋ถˆ๋ฆฌํ•˜๋‹ค.
*/



/// ์˜์กด์„ฑ ์—ญ์ „ ์›์น™, Dependency Iversion Principle
protocol Menu {
	var price: Int
}
class Order {
	let menu: Menu
    init(menu: Menu) {
    	self.menu = menu
    }
}
class Toast: Menu {
	var price: Int
    init(price: Int) {
    	self.price = price
    }
}

let toast = Toast(price: 3000)
let order = Order(menu: toast)
print(order.menu.price) // 3000

/**
	๋‘ ํด๋ž˜์Šค ๋ชจ๋‘ ์ถ”์ƒํ™”๋œ ํ”„๋กœํ† ์ฝœ์— ์˜์กดํ•˜๊ฒŒ ๋˜๋ฉด์„œ ์„œ๋กœ๊ฐ„์˜ ์˜์กด์„ฑ์€ ๋…๋ฆฝ์ ์ด๊ฒŒ ๋๋‹ค.
    ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ ธ Toast์˜ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ Order์—๋Š” ์˜ํ–ฅ์ด ์—†์–ด ์œ ์ง€๋ณด์ˆ˜์— ์œ ๋ฆฌํ•˜๋‹ค.
*/



๐ŸŒŸ ๊ธ€์„ ๋งˆ์น˜๋ฉฐ

์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ๋“ค์„ ์ •๋ฆฌํ•ด๋ณด์ž.

SRP์™€ ISP๋Š” ๊ฐ์ฒด๊ฐ€ ์ปค์ง€๋Š”๊ฒƒ์„ ๋ฐฉ์ง€ํ•ด์ค€๋‹ค. SRP๋Š” ๋‹จ์ผ ์ฑ…์ž„์„ ๋ถ€์—ฌํ•ด ๊ฐ์ฒด๊ฐ€ ๋‚˜๋‰˜๋„๋ก ํ–ˆ๊ณ  ISP๋Š” ํด๋ผ์ด์–ธํŠธ๋งˆ๋‹ค ํŠนํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ฒŒ ํ•จ์œผ๋กœ์จ ํ•œ ๊ธฐ๋Šฅ์˜ ๋ณ€๊ฒฝ์ด ๋‹ค๋ฅธ๊ณณ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ์ตœ์†Œํ™” ํ•˜๊ณ , ์ด๋Š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๋ฐ ๋ณ€๊ฒฝ์— ์šฉ์ดํ•˜๋„๋ก ํ•œ๋‹ค.

LSP์™€ DIP๋Š” OCP๋ฅผ ์„œํฌํŠธํ•œ๋‹ค. OCP ๋Š” ์ž์ฃผ ๋ณ€ํ™”๋˜๋Š” ๋ถ€๋ถ„์„ ์ถ”์ƒํ™”ํ•˜๊ณ  ๋‹คํ˜•์„ฑ์„ ์ด์šฉํ•จ์œผ๋กœ์จ ๊ธฐ๋Šฅ ํ™•์žฅ์—๋Š” ์šฉ์ดํ•˜๋˜ ๊ธฐ์กด ์ฝ”๋“œ์˜ ๋ณ€ํ™”์—๋Š” ๋ณด์ˆ˜์ ์ด๋„๋ก ๋งŒ๋“ค์–ด ์ค€๋‹ค. ์—ฌ๊ธฐ์„œ ๋ณ€ํ™”๋˜๋Š” ๋ถ€๋ถ„์„ ์ถ”์ƒํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์›์น™์ด DIP ์ด๊ณ , ๋‹คํ˜•์„ฑ ๊ตฌํ˜„์„ ๋„์™€์ฃผ๋Š” ์›์น™์ด LSP ์ธ ๊ฒƒ์ด๋‹ค.

Clean Architecture์— ์ด์–ด์„œ SOLID 5์›์น™์— ๋Œ€ํ•ด์„œ๋„ ๊ณต๋ถ€๋ฅผ ํ•˜๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ์ฒ˜์Œ์—๋Š” Clean Architecture๋งŒ์œผ๋กœ๋„ ๋จธ๋ฆฟ์†์— ์ •๋ฆฌํ•˜๋ ค๋‹ˆ ์•ž์ด ๊นœ๊นœํ–ˆ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ Clean Architecture๋ฅผ ๋ฐฐ์šฐ๋‹ˆ ๋” ๊นŠ๊ฒŒ ๊ณต๋ถ€ํ•˜๊ณ  ์‹ถ์–ด์กŒ๊ณ  ๊ทธ๋ž˜์„œ SOLID 5์›์น™ ๊นŒ์ง€ ๊ณต๋ถ€ํ•˜๊ฒŒ ๋๋‹ค.

์ด๊ฒƒ๋“ค์„ ๋จธ๋ฆฟ์†์— ์ •๋ฆฌํ•˜๊ณ  ๋‚ด ํ”„๋กœ์ ํŠธ์— ์ง์ ‘ ์ ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์ž์—ฐ์Šค๋ ˆ ์ข‹์€ ํ’ˆ์งˆ์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์„๊ฑฐ๋ผ ์ƒ๊ฐ์ด ๋“ ๋‹ค. ๋˜, ์ข‹์€ ํ’ˆ์งˆ์˜ ์ฝ”๋“œ๋ฅผ ๊พธ์ค€ํžˆ ์ž‘์„ฑํ•˜๋Š”๊ฒƒ์€ ์ข‹์€ ๊ฐœ๋ฐœ์ž๋กœ ๊ฑฐ๋“ญ๋‚˜๊ธฐ ์œ„ํ•œ ๊ณผ์ •์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋งŽ์€ ํ•™์Šต์„ ํ†ตํ•ด ์ข‹์€ ํ’ˆ์งˆ์˜ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ๊ฒ ๋‹ค.





Reference

profile
iOS Developer ๐Ÿ’ป

0๊ฐœ์˜ ๋Œ“๊ธ€