의존성 주입이라고 하면, 필요한 객체를 생성할 객체에 전달하는 방법에 대한 이야기 입니다.
이번에는 의존성 주입에 있어서 "Protocol을 통한 정의" 와 "함수(클로저)를 통한 정의" 에 대해서 알아보려고 합니다.
import UIKit
// MARK: - 프로토콜을 이용한 의존성 주입
// ID를 생성한다.
protocol IDProvider {
func getGameID() -> UUID
}
struct UserID: IDProvider {
let userID: UUID
func getGameID() -> UUID { userID }
}
// 시간을 생성한다.
protocol TimeProvider {
func now() -> Date
}
struct GameStartTime: TimeProvider {
let starteTime: Date
func now() -> Date { starteTime }
}
// 게임을 생성한다.
struct Game {
private let startTime: Date
private let userID: UUID
init(userID: UUID, startTime: Date) {
self.userID = userID
self.startTime = startTime
}
}
// 게임을 담당하는 객체를 생성한다.
class GameService01 {
private let idProvider: IDProvider // ID
private let timeProvider: TimeProvider // Time
init(idProvider: IDProvider, timeProvider: TimeProvider) {
self.idProvider = idProvider
self.timeProvider = timeProvider
}
// 게임을 생성한다.
func createGame() -> Game {
let id = idProvider.getGameID() // ID 생성
let date = timeProvider.now() // 시간 생성
let game = Game(userID: id, startTime: date) // 게임 생성
return game
}
}
// 초기화
let gameService01 = GameService01(
idProvider: UserID(userID: UUID()),
timeProvider: GameStartTime(starteTime: Date()))
// 호출
gameService01.createGame()
장점
단점
// MARK: - 함수를 이용한 의존성 주입
class GameService02 {
private let getID: () -> UUID
private let getTime: () -> Date
init(getID: @escaping () -> UUID, getTime: @escaping () -> Date) {
self.getID = getID
self.getTime = getTime
}
func createGame() -> Game {
let id = getID()
let date = getTime()
let game = Game(userID: id, startTime: date)
// Do something with the game
return game
}
}
let gameService02 = GameService02(
getID: { UUID() }, // getID: UUID.init
getTime: { Date() }) // getTime: Date.init
gameService02.createGame()
장점
단점
getID
나 getTime
처럼 직관적이고 간단한 기능이 아닌 경우엔, 가독성을 오히려 해칠 우려가 있습니다.
그런 예시가 아래 코드에 있습니다.
protocol Logger {
func log(message: String, file: String)
}
let log: (String, String) -> Void
log("게임이 성공적으로 생성되었습니다.", "GameService.swift")
log("GameService.swift", "게임이 성공적으로 생성되었습니다.")
이런 경우에는 오히려 프로토콜을 사용하는 것이 가독성을 올릴 수 있습니다.