-
Notifications
You must be signed in to change notification settings - Fork 1
❗ DI Container 에서 생성한 인스턴스가 동시에 존재 하는 이슈
DI Container 도입을 하며 하나의 Main Repository를 만들게 되고,
다른 서브 Repo(Player, Roominfo 등등) 들은 Main Repo를 의존하도록 등록하였다.
하지만 정상적으로 데이터가 뷰모델까지 흐르지 않았다. 왜 VM까지 데이터가 흐르지 않는가에 대한 원인을 발견했다.
디버깅을 통해 ViewModel이 갖고있는 MainRepo의 주소는 같으나,
서브 Repo 가 갖고있는 MainRepo의 주소가 다른 것을 확인하였다.
따라서 send()
를 호출하는 MainRepository
와 구독하는 MainRepository
가 서로 다른 인스턴스였다.
MainRepository
의 인스턴스가 여러 개 존재 한다는 뜻인데 왜 이렇게 발생했을까 ?
import ASContainer
import ASNetworkKit
public struct RepsotioryAssembly: Assembly {
public init() {}
public func assemble(container: Registerable) {
container.register(MainRepositoryProtocol.self) { r in
let databaseManager = r.resolve(ASFirebaseDatabaseProtocol.self)
return MainRepository(
databaseManager: databaseManager
)
}
container.register(PlayersRepositoryProtocol.self) { r in
let mainRepository = r.resolve(MainRepositoryProtocol.self)
return PlayersRepository(
mainRepository: mainRepository
)
}
...
}
}
여기서 container에 등록할때 MainRepository를 생성하는 Closure를 저장하고 있었다. (현재 DI Container는 메모리 누수를 방지하기 위해 Resolve할 때마다 생성하는 방식으로, Closure로 저장하고 있음)
문제는 하나여야만 하는 객체인 MainRepository를 resolve 할때마다 항상 새로 생성해주고 있었던 것.
이를 해결하기 위해 싱글톤인 객체에 대해 하나의 객체만 만들어줄 필요가 있었다.
이를 기존 DIContainer 에서 조금 수정해서
싱글톤을 등록할 수 있는 함수를 작성했다. 그리고 resolve 할때는 싱글톤객체인지 확인하는 코드까지 추가하여 문제를 해결했다.
public protocol Registerable {
func register<T>(_ type: T.Type, factory: @escaping (Resolvable) -> T)
func register<T>(_ type: T.Type, _ object: T)
func registerSingleton<T>(_ type: T.Type, factory: @escaping (Resolvable) -> T)
func registerSingleton<T>(_ type: T.Type, _ object: T)
}
이로써 싱글톤 객체에 대해 전부 동일한 인스턴스를 가지게되었다 !!
-
전체코드
public protocol Registerable { func register<T>(_ type: T.Type, factory: @escaping (Resolvable) -> T) func register<T>(_ type: T.Type, _ object: T) func registerSingleton<T>(_ type: T.Type, factory: @escaping (Resolvable) -> T) func registerSingleton<T>(_ type: T.Type, _ object: T) } public protocol Resolvable { func resolve<T>(_ type: T.Type) -> T } public protocol Assembly { func assemble(container: Registerable) } public final class DIContainer: Registerable, Resolvable { public nonisolated(unsafe) static let shared = DIContainer() private init() {} private var factories = [String: (Resolvable) -> Any]() private var singletons = [String: Any]() public func register<T>(_ type: T.Type, factory: @escaping (Resolvable) -> T) { let key = "\(type)" factories[key] = factory } public func register<T>(_ type: T.Type, _ object: T) { let key = "\(type)" factories[key] = { _ in object } } public func registerSingleton<T>(_ type: T.Type, factory: @escaping (Resolvable) -> T) { let key = "\(type)" factories[key] = { [weak self] resolver in if let instance = self?.singletons[key] as? T { return instance } else { let instance = factory(resolver) self?.singletons[key] = instance return instance } } } public func registerSingleton<T>(_ type: T.Type, _ object: T) { let key = "\(type)" singletons[key] = object } public func resolve<T>(_ type: T.Type) -> T { let key = "\(type)" if let instance = singletons[key] as? T { return instance } guard let factory = factories[key] else { fatalError("등록되지 않은 의존성 타입: \(type)") } guard let dependency = factory(self) as? T else { fatalError("의존성 팩토리가 \(type) 타입의 인스턴스를 반환하지 않았습니다") } return dependency } public func addAssemblies(_ assemblies: [Assembly]) { assemblies.forEach { $0.assemble(container: self) } } }
- 📒 기획의 과정과 의도
- 📒 swift6 도입기 ‐ @unchecked Sendable을 사용해야만 했던 이유
- 📒 WaveForm(파형) 제작기
- 📒 프로젝트 구조와 이유
- 📒 화면 전환(Game NavigationController)
- 📒 DIContainer를 사용한 계기
- 📒 AudioHelper 제작기
- 📒 음악 플레이어의 compact 버전 제작기
- 📒 Combine을 이용한 데이터 전달
- 📒 파이어베이스를 쓰며 있었던 일
- 📒 캐싱 모듈 구현과 문제점
- 📒 로그 시스템 제작기
- ❗ Data 끼리의 비교
- ❗ 프레임워크 Reference 안잡히는 문제
- ❗ actor 안에서 timer가 실행되지 않는 문제
- ❗ NSLayoutConstraint 옵셔널 문제
- ❗ 테이블 뷰가 보고 있는 배열과 bind하고 있는 배열 간의 race condition 문제
- ❗ 테스트끼리의 독립성
- ❗ 네트워크 테스팅 시 Error 핸들링
- ❗ 여러 클라이언트가 서버에 동시 요청시, 데이터가 반영이 안되는 이슈 해결
- ❗ 의존성 framework 추가시 불러오지 못하는 문제
- ❗ Timer를 6초 설정해도 더 실행되는 문제
- ❗ Music Kit Data Request 에러
- ❗ DI Container 에서 생성한 인스턴스가 동시에 존재 하는 이슈