한창 Android를 공부할 당시 DI 라이브러리로 Hilt와 Koin 중에 무엇을 쓸지 고민했던 기억이 납니다.
제 사견으로 iOS에서는 보편적으로 쓰이고 유명한 DI라이브러리는 잘 못들어본 것 같습니다.
안드로이드가 상대적으로 자료가 더 많아서 그럴수도 있겠지만요.
그동안 싱글톤으로 DI Provider를 만들어서 처리해왔는데 이참에 알아보려합니다.
나름대로 주변 개발자 or 팔로우한 개발자 or 검색을 통해 알바본 바로는 Swinject가 많이 보이더군요.
https://github.com/Swinject/Swinject
GitHub - Swinject/Swinject: Dependency injection framework for Swift with iOS/macOS/Linux
Dependency injection framework for Swift with iOS/macOS/Linux - GitHub - Swinject/Swinject: Dependency injection framework for Swift with iOS/macOS/Linux
github.com
Swinject에 대해 알아보기 전에
라이브러리 사용법 정리에 앞서서 DI관련 개념부터 짚고 넘어갈 생각입니다.
이걸 왜써야할까요?
의존관계 역전 원칙(Dependency Inversion Principle)은 추상화된 것에 의존하게 만들고 구상클래스에 의존하지 않도록 하는 것이죠.
예를 들어 로그인 ViewModel은 LoginService로 의존성을 가지게 될 수 있을 것 같습니다.
의존성을 가지고 있다는 말은 KakaoService가 변화한다면 LoginViewModel도 영향을 받는다는 의미입니다.
다시말해 HighLevel 모듈인 LoginViewModel은 Low Level 모듈인 KakaoService와 GoogleService의 Dependency가 존재하는 상태입니다.
하지만 요즘 로그인을 할 수 있는 방법이 다양하죠? 카카오 로그인, 구글 로그인, 애플로그인 등 다양한 Service가 존재할 것입니다.
여기서 AppleService를 추가하게되면
High level 모듈에 dependency가 증가하게 되며 (코드 수정 등 필요) 추가될 때마다 번거로워질 것입니다.
이때 AuthService Protocol을 제공하므로서
HigiLevel 모듈이 Low Level 모듈인
KakaoService와 GooglService에 의존하도록 만드는 것이 아닌
추상화 모듈을 하나 만들어서 의존하도록 만들어줍니다.
이때 화살표 방향이 바뀌는 것을 볼 수 있는데 이것이 바로 의존성 역전 원칙입니다.
그 결과 결합도가 느슨해지는 것을 느낄 수 있죠.
이러한 의존관계 역전원칙을 따를 수 있도록 Dependencty Injection을 사용합니다.
의존성 주입에 대한 이해는 아래 영상이 가장 쉽고 빠르게 이해할 수 있을 것 같습니다.
https://www.youtube.com/watch?v=1vdeIL2iCcM&t=141s
위 영상을 정리하자면 아래와 같습니다.
위 사진을 보시면 A 안에서 B를 직접 생성하고 참조하기 때문에 A는 완전히 B에게 의존성을 가지고 있죠.
이러한 제어 흐름을 바꾸기 위해 중간에 매개체를 두어 직접적으로 생성하고 참조하지 않도록 제어 흐름을 바꾼다는 것입니다.
이때 이 매개체를 IOC(Inversion Of Control) Container라고 한다고 해요.
Swinject를 처음 사용해보기 위해 주목할 것은 두가지 인 것 같습니다.
1. IOC Container에게 필요한 모듈을 등록
2. 사용하는 주체에서 직접 생성하는 것이 아닌 필요할 때 IOC Container가 의존성이 있는 모듈들을 주입.
IOC Container는 제어권을 사용하여 의존성을 관리, 인스턴스 생성 및 주입, 메모리 해제를 담당합니다.
의존하는 모듈들의 생성과 해제, 주입등의 제어과정을 IOC Container가 수행하게 되면서 의존성 역전이 일어난다고 합니다.
Swinject 사용법
설치 방법은 cocoaPod과 SPM 편한 방법으로 설치하시면되고 생략하겠습니다.
swinject git의 예제를 보면서 이해해보겠습니다.
우선 아래와 같은 클래스와 프로토콜이 정의됩니다.
protocol Animal {
var name: String? { get }
}
class Cat: Animal {
let name: String?
init(name: String?) {
self.name = name
}
}
protocol Person {
func play()
}
class PetOwner: Person {
let pet: Animal
init(pet: Animal) {
self.pet = pet
}
func play() {
let name = pet.name ?? "someone"
print("I'm playing with \(name).")
}
}
class PersonViewController: UIViewController {
var person: Person?
}
1. IOC Container에게 필요한 모듈을 등록
-> register
let container = Container()
container.register(Animal.self) { _ in Cat(name: "Mimi") }
2. 사용하는 주체에서 직접 생성하는 것이 아닌 필요할 때 IOC Container가 의존성이 있는 모듈들을 주입.
-> resolve
container.register(Person.self) { r in
PetOwner(pet: r.resolve(Animal.self)!)
}
container.register(PersonViewController.self) { r in
let controller = PersonViewController()
controller.person = r.resolve(Person.self)
return controller
}
전체 코드
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let container: Container = {
let container = Container()
container.register(Animal.self) { _ in Cat(name: "Mimi") }
container.register(Person.self) { r in
PetOwner(pet: r.resolve(Animal.self)!)
}
container.register(PersonViewController.self) { r in
let controller = PersonViewController()
controller.person = r.resolve(Person.self)
return controller
}
return container
}()
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
// Instantiate a window.
let window = UIWindow(frame: UIScreen.main.bounds)
window.makeKeyAndVisible()
self.window = window
// Instantiate the root view controller with dependencies injected by the container.
window.rootViewController = container.resolve(PersonViewController.self)
return true
}
}
'IOS' 카테고리의 다른 글
[iOS] Compositional Layout & Sticky Header를 적용하면서(UIKit) (0) | 2023.03.10 |
---|---|
[Error] Compiling for iOS 8.0, but module 'RxTest' has a minimum deployment target of iOS 9.0 (0) | 2023.03.07 |
[iOS] Swift retain Cycle 순환참조, weak, strong, unowned (0) | 2023.01.12 |
[iOS] CoreData로 꼼꼬미 단어장 앱 만들기 (0) | 2022.12.23 |
[iOS] Rx 다시 정복(1) feat. Rx Study발표 - 에이젠 (0) | 2022.12.19 |
댓글