Skip to content

모듈 팩토리 - 고급 의존성 조직화

WeaveDI의 모듈 팩토리 시스템에 대한 포괄적인 가이드입니다. 엔터프라이즈급 애플리케이션에서 의존성을 조직화, 관리, 확장하는 가장 강력한 방법을 제공합니다. 이 시스템은 복잡한 의존성 그래프를 위한 체계적인 모듈 생성, 등록, 관리를 가능하게 합니다.

개요

WeaveDI의 모듈 팩토리 패턴은 대규모 의존성 관리 방식을 변화시킵니다. 분산된 등록 대신, 구성 가능하고 테스트 가능하며 유지보수 가능한 의존성 모듈을 체계적으로 관리할 수 있는 조직화된 시스템을 만들 수 있습니다.

주요 장점

  • 🏗️ 체계적 조직화: 관련 의존성들을 논리적 모듈로 그룹화
  • 🔧 팩토리 패턴: 의존성 생성을 위한 검증된 팩토리 디자인 패턴 활용
  • 🎯 타입 안전성: 모듈 의존성의 컴파일 타임 검증
  • 🧪 테스팅 지원: 쉬운 목 주입과 테스트 격리
  • ⚡ 성능: 지연 로딩과 최적화된 모듈 등록
  • 📦 모듈화: 대규모 팀과 복잡한 애플리케이션에 완벽

아키텍처 장점

┌─────────────────────────────────────┐
│        Application Layer            │
│   ┌─────────────────────────────┐   │
│   │     ModuleFactoryManager    │   │
│   └─────────────────────────────┘   │
└─────────────────┬───────────────────┘

      ┌───────────┼───────────┐
      │           │           │
┌─────▼─────┐ ┌───▼────┐ ┌───▼────────┐
│Repository │ │UseCase │ │  Service   │
│  Factory  │ │Factory │ │  Factory   │
└───────────┘ └────────┘ └────────────┘
      │           │           │
      └───────────┼───────────┘

┌─────────────────▼───────────────────┐
│         WeaveDI Container           │
│        (Registered Modules)         │
└─────────────────────────────────────┘

핵심 구성 요소

ModuleFactory 프로토콜

실제 구현을 기반으로 한 모듈 시스템의 기초:

swift
public protocol ModuleFactory {
    var registerModule: RegisterModule { get }    // 모듈 생성 유틸리티
    var definitions: [@Sendable () -> Module] { get set }  // 모듈 정의들
    func makeAllModules() -> [Module]  // 모든 모듈을 한 번에 생성
}

프로토콜 책임:

  • 모듈 정의 저장: 모듈 생성 클로저들의 목록 유지
  • 배치 생성: 팩토리의 모든 모듈을 동시에 생성
  • 타입 안전성: 모든 모듈이 적절히 타입 지정되고 Sendable함을 보장
  • 지연 평가: makeAllModules()가 호출될 때만 모듈이 생성됨

RegisterModule - 모듈 생성 엔진

모든 모듈 생성을 담당하는 핵심 유틸리티:

swift
public struct RegisterModule: Sendable {
    // 기본 모듈 생성 - 단순한 의존성용
    public func makeModule<T>(
        _ type: T.Type,
        factory: @Sendable @escaping () -> T
    ) -> Module where T: Sendable

    // UseCase-Repository 패턴과 자동 의존성 주입을 위한 고급 기능
    public func makeUseCaseWithRepository<UseCase, Repo>(
        _ useCaseProtocol: UseCase.Type,      // 등록할 UseCase 프로토콜
        repositoryProtocol: Repo.Type,        // 필요한 리포지토리 의존성
        repositoryFallback: @Sendable @autoclosure @escaping () -> Repo,  // 리포지토리를 찾지 못할 때 폴백
        factory: @Sendable @escaping (Repo) -> UseCase  // 주입된 리포지토리로 UseCase 생성
    ) -> @Sendable () -> Module where UseCase: Sendable

    // 여러 의존성을 가진 의존성 주입
    public func makeDependency<T>(
        _ type: T.Type,
        dependencies: [Any.Type] = [],
        factory: @Sendable @escaping () throws -> T
    ) -> Module where T: Sendable
}

RegisterModule 기능:

  • 🎯 타입 안전성: 모든 모듈의 컴파일 타임 타입 검사
  • 🔄 의존성 주입: 모듈 의존성의 자동 해결
  • 🛡️ 폴백 지원: 누락된 의존성의 우아한 처리
  • ⚡ 성능: 최적화된 모듈 생성과 등록
  • 🧵 동시성: 완전한 Swift 6 sendable 준수

기본 사용법

단순한 모듈 팩토리

관련 의존성들을 위한 기본 팩토리로 시작:

swift
struct RepositoryModuleFactory: ModuleFactory {
    var registerModule = RegisterModule()
    var definitions: [@Sendable () -> Module] = []

    mutating func setup() {
        // 데이터베이스 의존성을 가진 사용자 리포지토리
        definitions.append {
            registerModule.makeModule(UserRepository.self) {
                UserRepositoryImpl(
                    database: WeaveDI.Container.shared.resolve(DatabaseService.self)!,
                    logger: WeaveDI.Container.shared.resolve(Logger.self)
                )
            }
        }

        // 캐싱을 가진 도서 리포지토리
        definitions.append {
            registerModule.makeModule(BookRepository.self) {
                CachedBookRepository(
                    baseRepository: BookRepositoryImpl(),
                    cache: WeaveDI.Container.shared.resolve(CacheService.self)!
                )
            }
        }

        // 복잡한 의존성을 가진 주문 리포지토리
        definitions.append {
            registerModule.makeModule(OrderRepository.self) {
                OrderRepositoryImpl(
                    database: WeaveDI.Container.shared.resolve(DatabaseService.self)!,
                    paymentGateway: WeaveDI.Container.shared.resolve(PaymentGateway.self)!,
                    notificationService: WeaveDI.Container.shared.resolve(NotificationService.self)!
                )
            }
        }
    }

    func makeAllModules() -> [Module] {
        definitions.map { $0() }
    }
}

오류 처리가 강화된 팩토리

swift
struct SafeRepositoryModuleFactory: ModuleFactory {
    var registerModule = RegisterModule()
    var definitions: [@Sendable () -> Module] = []

    mutating func setup() {
        definitions.append {
            registerModule.makeModule(UserRepository.self) {
                do {
                    // 원격 데이터베이스로 생성 시도
                    let remoteDB = try RemoteDatabaseService.connect()
                    return RemoteUserRepository(database: remoteDB)
                } catch {
                    // 로컬 데이터베이스로 폴백
                    print("⚠️ 원격 DB를 사용할 수 없어 로컬 사용: \(error)")
                    let localDB = LocalDatabaseService()
                    return LocalUserRepository(database: localDB)
                }
            }
        }
    }

    func makeAllModules() -> [Module] {
        definitions.map { $0() }
    }
}

팩토리 등록과 사용

기본 등록

swift
// 앱 초기화
func initializeRepositories() async {
    var repositoryFactory = RepositoryModuleFactory()
    repositoryFactory.setup()

    let modules = repositoryFactory.makeAllModules()

    await WeaveDI.Container.bootstrap { container in
        for module in modules {
            await container.register(module)
        }
    }

    print("✅ \(modules.count)개 리포지토리 모듈이 등록되었습니다")
}

검증이 포함된 고급 등록

swift
func initializeWithValidation() async throws {
    var repositoryFactory = RepositoryModuleFactory()
    repositoryFactory.setup()

    let modules = repositoryFactory.makeAllModules()

    // 등록 전 모듈 검증
    try validateModules(modules)

    await WeaveDI.Container.bootstrap { container in
        await withTaskGroup(of: Void.self) { group in
            for module in modules {
                group.addTask {
                    await container.register(module)
                    print("📦 등록됨: \(module.description)")
                }
            }
        }
    }
}

func validateModules(_ modules: [Module]) throws {
    guard !modules.isEmpty else {
        throw ModuleError.noModulesFound
    }

    for module in modules {
        guard module.isValid else {
            throw ModuleError.invalidModule(module.description)
        }
    }
}

고급 패턴

1. 다중 모듈 팩토리 시스템

다양한 모듈 타입을 관리하는 포괄적인 시스템:

swift
struct ApplicationModuleFactory {
    // 서로 다른 관심사를 위한 다양한 팩토리 타입
    var infrastructureFactory = InfrastructureModuleFactory()
    var repositoryFactory = RepositoryModuleFactory()
    var useCaseFactory = UseCaseModuleFactory()
    var serviceFactory = ServiceModuleFactory()
    var presentationFactory = PresentationModuleFactory()

    let environment: Environment
    let configuration: AppConfiguration

    init(environment: Environment, configuration: AppConfiguration) {
        self.environment = environment
        self.configuration = configuration
    }

    mutating func setupAll() async {
        // 의존성 순서대로 설정
        await setupInfrastructure()
        await setupRepositories()
        await setupUseCases()
        await setupServices()
        await setupPresentation()
    }

    private mutating func setupInfrastructure() async {
        infrastructureFactory.setup(for: environment, config: configuration)
    }

    private mutating func setupRepositories() async {
        // 리포지토리는 인프라에 의존
        repositoryFactory.setup()
    }

    private mutating func setupUseCases() async {
        // UseCase는 리포지토리에 의존
        useCaseFactory.setup()
    }

    private mutating func setupServices() async {
        // 서비스는 Use Case에 의존
        serviceFactory.setup()
    }

    private mutating func setupPresentation() async {
        // 프레젠테이션은 서비스에 의존
        presentationFactory.setup()
    }

    func getAllModules() -> [Module] {
        var allModules: [Module] = []

        // 의존성 순서대로 모듈 추가
        allModules.append(contentsOf: infrastructureFactory.makeAllModules())
        allModules.append(contentsOf: repositoryFactory.makeAllModules())
        allModules.append(contentsOf: useCaseFactory.makeAllModules())
        allModules.append(contentsOf: serviceFactory.makeAllModules())
        allModules.append(contentsOf: presentationFactory.makeAllModules())

        return allModules
    }

    func getModulesStatistics() -> ModuleStatistics {
        return ModuleStatistics(
            infrastructureCount: infrastructureFactory.makeAllModules().count,
            repositoryCount: repositoryFactory.makeAllModules().count,
            useCaseCount: useCaseFactory.makeAllModules().count,
            serviceCount: serviceFactory.makeAllModules().count,
            presentationCount: presentationFactory.makeAllModules().count
        )
    }
}

struct ModuleStatistics {
    let infrastructureCount: Int
    let repositoryCount: Int
    let useCaseCount: Int
    let serviceCount: Int
    let presentationCount: Int

    var totalCount: Int {
        infrastructureCount + repositoryCount + useCaseCount + serviceCount + presentationCount
    }
}

2. 리포지토리 의존성을 가진 UseCase 팩토리

자동 의존성 주입을 위한 내장 UseCase-Repository 패턴 활용:

swift
struct UseCaseModuleFactory: ModuleFactory {
    var registerModule = RegisterModule()
    var definitions: [@Sendable () -> Module] = []

    mutating func setup() {
        // 리포지토리 의존성을 가진 인증 UseCase
        definitions.append(
            registerModule.makeUseCaseWithRepository(
                LoginUseCase.self,
                repositoryProtocol: AuthRepository.self,
                repositoryFallback: DefaultAuthRepository(),
                factory: { repository in
                    LoginUseCaseImpl(
                        repository: repository,
                        validator: AuthValidator(),
                        logger: WeaveDI.Container.shared.resolve(Logger.self)
                    )
                }
            )
        )

        // 사용자 관리 UseCase
        definitions.append(
            registerModule.makeUseCaseWithRepository(
                UserProfileUseCase.self,
                repositoryProtocol: UserRepository.self,
                repositoryFallback: DefaultUserRepository(),
                factory: { repository in
                    UserProfileUseCaseImpl(
                        repository: repository,
                        imageService: WeaveDI.Container.shared.resolve(ImageService.self)!,
                        analyticsService: WeaveDI.Container.shared.resolve(AnalyticsService.self)
                    )
                }
            )
        )

        // 여러 리포지토리를 가진 주문 관리 UseCase
        definitions.append(
            registerModule.makeUseCaseWithRepository(
                OrderManagementUseCase.self,
                repositoryProtocol: OrderRepository.self,
                repositoryFallback: DefaultOrderRepository(),
                factory: { orderRepository in
                    OrderManagementUseCaseImpl(
                        orderRepository: orderRepository,
                        userRepository: WeaveDI.Container.shared.resolve(UserRepository.self)!,
                        paymentRepository: WeaveDI.Container.shared.resolve(PaymentRepository.self)!,
                        notificationService: WeaveDI.Container.shared.resolve(NotificationService.self)
                    )
                }
            )
        )

        // 캐싱이 있는 검색 UseCase
        definitions.append {
            registerModule.makeModule(SearchUseCase.self) {
                CachedSearchUseCaseImpl(
                    searchRepository: WeaveDI.Container.shared.resolve(SearchRepository.self)!,
                    cacheService: WeaveDI.Container.shared.resolve(CacheService.self)!,
                    analyticsService: WeaveDI.Container.shared.resolve(AnalyticsService.self)
                )
            }
        }
    }

    func makeAllModules() -> [Module] {
        definitions.map { $0() }
    }
}

3. 특화된 팩토리 타입

WeaveDI는 일반적인 패턴을 위한 사전 구축된 팩토리 타입을 제공:

swift
// 내장 특화 팩토리들
public struct RepositoryModuleFactory: ModuleFactory, Sendable {
    // 데이터 레이어 의존성에 최적화
    // - 데이터베이스 연결
    // - API 클라이언트
    // - 데이터 매퍼
    // - 캐싱 레이어
}

public struct UseCaseModuleFactory: ModuleFactory, Sendable {
    // 비즈니스 로직에 최적화
    // - 도메인 Use Case
    // - 비즈니스 규칙
    // - 워크플로 오케스트레이션
    // - 횡단 관심사
}

public struct ScopeModuleFactory: ModuleFactory, Sendable {
    // 스코프가 있는 의존성에 최적화
    // - 요청 스코프 서비스
    // - 세션 스코프 데이터
    // - 사용자 스코프 설정
    // - 임시 컨텍스트
}

사용자 정의 특화 팩토리

swift
// 인프라 팩토리
struct InfrastructureModuleFactory: ModuleFactory {
    var registerModule = RegisterModule()
    var definitions: [@Sendable () -> Module] = []

    mutating func setup(for environment: Environment, config: AppConfiguration) {
        // 데이터베이스 설정
        definitions.append {
            registerModule.makeModule(DatabaseService.self) {
                switch environment {
                case .development:
                    return InMemoryDatabaseService()
                case .staging:
                    return SQLiteDatabaseService(path: config.stagingDBPath)
                case .production:
                    return PostgreSQLDatabaseService(config: config.productionDBConfig)
                }
            }
        }

        // 네트워크 설정
        definitions.append {
            registerModule.makeModule(NetworkService.self) {
                HTTPNetworkService(
                    baseURL: config.apiBaseURL,
                    timeout: config.networkTimeout,
                    interceptors: createInterceptors(for: environment)
                )
            }
        }

        // 로깅 설정
        definitions.append {
            registerModule.makeModule(Logger.self) {
                switch environment {
                case .development:
                    return ConsoleLogger(level: .debug)
                case .staging:
                    return FileLogger(level: .info, path: config.logPath)
                case .production:
                    return RemoteLogger(level: .error, endpoint: config.logEndpoint)
                }
            }
        }
    }

    private func createInterceptors(for environment: Environment) -> [NetworkInterceptor] {
        var interceptors: [NetworkInterceptor] = []

        // 인증 인터셉터 추가
        interceptors.append(AuthInterceptor())

        // 비프로덕션에서 로깅 추가
        if environment != .production {
            interceptors.append(LoggingInterceptor())
        }

        // 재시도 인터셉터 추가
        interceptors.append(RetryInterceptor(maxRetries: 3))

        return interceptors
    }

    func makeAllModules() -> [Module] {
        definitions.map { $0() }
    }
}

4. ModuleFactoryManager - 엔터프라이즈급 관리

모니터링과 검증을 포함한 모든 팩토리의 중앙화된 엔터프라이즈급 관리:

swift
public struct ModuleFactoryManager: Sendable {
    public var repositoryFactory: RepositoryModuleFactory
    public var useCaseFactory: UseCaseModuleFactory
    public var scopeFactory: ScopeModuleFactory
    public var infrastructureFactory: InfrastructureModuleFactory
    public var presentationFactory: PresentationModuleFactory

    private let logger: Logger?
    private let environment: Environment
    private let configuration: AppConfiguration

    public init(
        environment: Environment,
        configuration: AppConfiguration,
        logger: Logger? = nil
    ) {
        self.environment = environment
        self.configuration = configuration
        self.logger = logger

        // 환경 컨텍스트로 팩토리 초기화
        self.repositoryFactory = RepositoryModuleFactory()
        self.useCaseFactory = UseCaseModuleFactory()
        self.scopeFactory = ScopeModuleFactory()
        self.infrastructureFactory = InfrastructureModuleFactory()
        self.presentationFactory = PresentationModuleFactory()
    }

    public mutating func setupAllFactories() async {
        logger?.info("🏭 \(environment) 환경을 위한 모듈 팩토리 설정 중")

        // 의존성 순서대로 설정
        infrastructureFactory.setup(for: environment, config: configuration)
        repositoryFactory.setup()
        useCaseFactory.setup()
        scopeFactory.setup()
        presentationFactory.setup()

        logger?.info("✅ 모든 팩토리가 구성되었습니다")
    }

    public func registerAll() async throws {
        logger?.info("📦 모듈 등록 프로세스 시작")

        // 모든 모듈 가져오기
        let allModules = getAllModulesInOrder()

        logger?.info("📊 등록할 \(allModules.count)개 모듈을 찾았습니다")

        // 등록 전 모듈 검증
        try validateModules(allModules)

        // 성능 향상을 위해 배치로 모듈 등록
        await registerModulesInBatches(allModules)

        logger?.info("🎉 모듈 등록이 성공적으로 완료되었습니다")
    }

    private func getAllModulesInOrder() -> [Module] {
        var allModules: [Module] = []

        // 의존성 순서대로 등록
        allModules.append(contentsOf: infrastructureFactory.makeAllModules())
        allModules.append(contentsOf: repositoryFactory.makeAllModules())
        allModules.append(contentsOf: useCaseFactory.makeAllModules())
        allModules.append(contentsOf: scopeFactory.makeAllModules())
        allModules.append(contentsOf: presentationFactory.makeAllModules())

        return allModules
    }

    private func validateModules(_ modules: [Module]) throws {
        guard !modules.isEmpty else {
            throw ModuleFactoryError.noModulesFound
        }

        // 중복 등록 확인
        var typeNames: Set<String> = []
        for module in modules {
            let typeName = String(describing: module.type)
            if typeNames.contains(typeName) {
                throw ModuleFactoryError.duplicateModule(typeName)
            }
            typeNames.insert(typeName)
        }

        logger?.info("✅ 모듈 검증 통과")
    }

    private func registerModulesInBatches(_ modules: [Module]) async {
        let batchSize = 10 // 한 번에 10개 모듈 등록
        let batches = modules.chunked(into: batchSize)

        for (index, batch) in batches.enumerated() {
            logger?.info("📦 배치 \(index + 1)/\(batches.count) 등록 중")

            await withTaskGroup(of: Void.self) { group in
                for module in batch {
                    group.addTask {
                        await WeaveDI.Container.shared.register(module)
                        self.logger?.debug("✅ 등록됨: \(module.description)")
                    }
                }
            }
        }
    }

    public func getRegistrationStatistics() -> RegistrationStatistics {
        return RegistrationStatistics(
            infrastructureModules: infrastructureFactory.makeAllModules().count,
            repositoryModules: repositoryFactory.makeAllModules().count,
            useCaseModules: useCaseFactory.makeAllModules().count,
            scopeModules: scopeFactory.makeAllModules().count,
            presentationModules: presentationFactory.makeAllModules().count
        )
    }
}

// 지원 타입
enum ModuleFactoryError: LocalizedError {
    case noModulesFound
    case duplicateModule(String)
    case invalidConfiguration

    var errorDescription: String? {
        switch self {
        case .noModulesFound:
            return "어떤 팩토리에서도 모듈을 찾을 수 없습니다"
        case .duplicateModule(let typeName):
            return "타입 \(typeName)에 대한 중복 모듈 등록"
        case .invalidConfiguration:
            return "유효하지 않은 팩토리 구성"
        }
    }
}

struct RegistrationStatistics {
    let infrastructureModules: Int
    let repositoryModules: Int
    let useCaseModules: Int
    let scopeModules: Int
    let presentationModules: Int

    var totalModules: Int {
        infrastructureModules + repositoryModules + useCaseModules + scopeModules + presentationModules
    }
}

// 사용법
func setupApplication() async throws {
    var manager = ModuleFactoryManager(
        environment: .production,
        configuration: AppConfiguration.load(),
        logger: ConsoleLogger()
    )

    await manager.setupAllFactories()
    try await manager.registerAll()

    let stats = manager.getRegistrationStatistics()
    print("🎯 \(5)개 팩토리에 걸쳐 \(stats.totalModules)개 모듈이 등록되었습니다")
}

실제 구현 사례

대규모 애플리케이션 설정

포괄적 모듈 시스템을 가진 SwiftUI 애플리케이션

swift
@main
struct EnterpriseWeaveDIApp: App {
    @State private var isInitialized = false
    @State private var initializationError: Error?

    init() {
        // 초기화를 시작하되 메인 스레드를 차단하지 않음
        Task {
            await initializeApplication()
        }
    }

    var body: some Scene {
        WindowGroup {
            if isInitialized {
                ContentView()
            } else if let error = initializationError {
                ErrorView(error: error) {
                    Task {
                        await retryInitialization()
                    }
                }
            } else {
                LoadingView()
                    .task {
                        await initializeApplication()
                    }
            }
        }
    }

    @MainActor
    private func initializeApplication() async {
        do {
            let startTime = Date()
            print("🚀 애플리케이션 초기화 시작...")

            // 모듈 팩토리 매니저 설정
            var manager = ModuleFactoryManager(
                environment: AppEnvironment.current,
                configuration: try AppConfiguration.load(),
                logger: AppLogger.shared
            )

            // 모든 팩토리 설정
            await manager.setupAllFactories()

            // 모든 모듈 등록
            try await manager.registerAll()

            // 중요한 의존성 검증
            try await verifyCriticalDependencies()

            let initTime = Date().timeIntervalSince(startTime)
            print("✅ 애플리케이션이 \(String(format: "%.2f", initTime))초에 초기화되었습니다")

            // 통계 표시
            let stats = manager.getRegistrationStatistics()
            print("📊 등록된 모듈: \(stats.totalModules)")

            isInitialized = true

        } catch {
            print("❌ 애플리케이션 초기화 실패: \(error)")
            initializationError = error
        }
    }

    private func retryInitialization() async {
        initializationError = nil
        await initializeApplication()
    }

    private func verifyCriticalDependencies() async throws {
        // 필수 서비스가 사용 가능한지 검증
        let criticalServices: [Any.Type] = [
            DatabaseService.self,
            NetworkService.self,
            Logger.self,
            UserRepository.self,
            AuthenticationService.self
        ]

        for serviceType in criticalServices {
            let resolved = WeaveDI.Container.shared.resolve(serviceType)
            guard resolved != nil else {
                throw InitializationError.criticalServiceMissing(String(describing: serviceType))
            }
        }

        print("✅ 모든 중요한 의존성이 검증되었습니다")
    }
}

enum InitializationError: LocalizedError {
    case criticalServiceMissing(String)
    case configurationLoadFailed
    case moduleRegistrationFailed(String)

    var errorDescription: String? {
        switch self {
        case .criticalServiceMissing(let service):
            return "중요한 서비스가 누락됨: \(service)"
        case .configurationLoadFailed:
            return "애플리케이션 구성 로드 실패"
        case .moduleRegistrationFailed(let details):
            return "모듈 등록 실패: \(details)"
        }
    }
}

팩토리 시스템을 가진 UIKit 애플리케이션

swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    private var moduleManager: ModuleFactoryManager?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }

        // 윈도우 설정
        window = UIWindow(windowScene: windowScene)

        // 로딩 화면 표시
        window?.rootViewController = LoadingViewController()
        window?.makeKeyAndVisible()

        // 비동기로 초기화
        Task {
            await initializeModuleSystem()
        }
    }

    private func initializeModuleSystem() async {
        do {
            print("🏭 모듈 팩토리 시스템 초기화 중...")

            // 모듈 매니저 생성 및 설정
            var manager = ModuleFactoryManager(
                environment: AppEnvironment.current,
                configuration: try AppConfiguration.load(),
                logger: AppLogger.shared
            )
            self.moduleManager = manager

            // 팩토리 설정
            await manager.setupAllFactories()

            // 모든 모듈 등록
            try await manager.registerAll()

            // 메인 앱으로 전환
            await transitionToMainApp()

        } catch {
            await showInitializationError(error)
        }
    }

    @MainActor
    private func transitionToMainApp() {
        // 주입된 의존성으로 메인 코디네이터 생성
        let mainCoordinator = MainCoordinator()
        let mainViewController = mainCoordinator.start()

        // 부드러운 전환
        UIView.transition(with: window!, duration: 0.3, options: .transitionCrossDissolve) {
            self.window?.rootViewController = mainViewController
        }

        print("🎉 메인 애플리케이션으로 성공적으로 전환되었습니다")
    }

    @MainActor
    private func showInitializationError(_ error: Error) {
        let errorViewController = ErrorViewController(error: error) { [weak self] in
            Task {
                await self?.initializeModuleSystem()
            }
        }

        window?.rootViewController = errorViewController
    }
}

환경별 팩토리

포괄적인 환경 인식 팩토리 시스템:

swift
struct EnvironmentModuleFactory: ModuleFactory {
    var registerModule = RegisterModule()
    var definitions: [@Sendable () -> Module] = []
    let environment: Environment
    let configuration: AppConfiguration

    init(environment: Environment, configuration: AppConfiguration) {
        self.environment = environment
        self.configuration = configuration
    }

    mutating func setup() {
        switch environment {
        case .development:
            setupDevelopmentModules()
        case .staging:
            setupStagingModules()
        case .production:
            setupProductionModules()
        case .testing:
            setupTestingModules()
        }
    }

    private mutating func setupDevelopmentModules() {
        print("🛠️ 개발 모듈 설정 중")

        // 자세한 로깅이 있는 목 API
        definitions.append {
            registerModule.makeModule(APIClient.self) {
                MockAPIClient(
                    baseURL: "https://dev-api.example.com",
                    enableNetworkLogs: true,
                    simulateLatency: true,
                    failureRate: 0.1 // 테스트를 위한 10% 실패율
                )
            }
        }

        // 디버깅을 위한 상세 로깅
        definitions.append {
            registerModule.makeModule(Logger.self) {
                CompositeLogger([
                    ConsoleLogger(level: .debug),
                    FileLogger(level: .info, path: configuration.devLogPath),
                    OSLogger(subsystem: "com.app.dev", category: "general")
                ])
            }
        }

        // 빠른 개발을 위한 인메모리 데이터베이스
        definitions.append {
            registerModule.makeModule(DatabaseService.self) {
                InMemoryDatabaseService(preloadTestData: true)
            }
        }

        // 콘솔에 로그를 남기는 목 분석
        definitions.append {
            registerModule.makeModule(AnalyticsService.self) {
                ConsoleAnalyticsService(verbose: true)
            }
        }

        // 캐싱이 비활성화된 디버그 이미지 로더
        definitions.append {
            registerModule.makeModule(ImageLoader.self) {
                DebugImageLoader(cacheEnabled: false)
            }
        }
    }

    private mutating func setupStagingModules() {
        print("🎭 스테이징 모듈 설정 중")

        // 스테이징 엔드포인트가 있는 실제 API
        definitions.append {
            registerModule.makeModule(APIClient.self) {
                HTTPAPIClient(
                    baseURL: "https://staging-api.example.com",
                    timeout: 30,
                    retryPolicy: RetryPolicy(maxRetries: 3),
                    certificatePinner: nil, // 스테이징에서는 덜 엄격
                    interceptors: [
                        AuthInterceptor(),
                        LoggingInterceptor(level: .info),
                        MetricsInterceptor()
                    ]
                )
            }
        }

        // 원격 보고를 포함한 구조화된 로깅
        definitions.append {
            registerModule.makeModule(Logger.self) {
                CompositeLogger([
                    ConsoleLogger(level: .info),
                    RemoteLogger(
                        endpoint: "https://logs-staging.example.com",
                        level: .warning
                    )
                ])
            }
        }

        // 스테이징 데이터가 있는 실제 데이터베이스
        definitions.append {
            registerModule.makeModule(DatabaseService.self) {
                PostgreSQLDatabaseService(
                    connectionString: configuration.stagingDBConnectionString,
                    poolSize: 5,
                    enableMigrations: true
                )
            }
        }

        // 테스트 분석 서비스
        definitions.append {
            registerModule.makeModule(AnalyticsService.self) {
                TestAnalyticsService(
                    endpoint: "https://analytics-staging.example.com",
                    flushInterval: 10 // 초
                )
            }
        }
    }

    private mutating func setupProductionModules() {
        print("🚀 프로덕션 모듈 설정 중")

        // 모든 보안 조치가 포함된 프로덕션 API
        definitions.append {
            registerModule.makeModule(APIClient.self) {
                SecureHTTPAPIClient(
                    baseURL: "https://api.example.com",
                    timeout: 15,
                    retryPolicy: RetryPolicy(maxRetries: 2),
                    certificatePinner: SSLCertificatePinner(
                        certificates: configuration.trustedCertificates
                    ),
                    interceptors: [
                        AuthInterceptor(),
                        RateLimitInterceptor(),
                        SecurityHeadersInterceptor(),
                        MetricsInterceptor()
                    ]
                )
            }
        }

        // 프로덕션 로깅 - 오류만
        definitions.append {
            registerModule.makeModule(Logger.self) {
                ProductionLogger(
                    remoteEndpoint: "https://logs.example.com",
                    level: .error,
                    encryptionKey: configuration.logEncryptionKey
                )
            }
        }

        // 커넥션 풀링이 있는 프로덕션 데이터베이스
        definitions.append {
            registerModule.makeModule(DatabaseService.self) {
                ProductionDatabaseService(
                    primaryConnectionString: configuration.primaryDBConnectionString,
                    readReplicaConnectionString: configuration.readReplicaConnectionString,
                    poolSize: 20,
                    enableConnectionPooling: true,
                    enableReadWriteSplit: true
                )
            }
        }

        // 개인정보 보호 규정 준수가 있는 전체 분석
        definitions.append {
            registerModule.makeModule(AnalyticsService.self) {
                PrivacyCompliantAnalyticsService(
                    providers: [
                        FirebaseAnalyticsProvider(),
                        MixpanelAnalyticsProvider(),
                        CustomAnalyticsProvider(endpoint: configuration.analyticsEndpoint)
                    ],
                    privacySettings: configuration.privacySettings
                )
            }
        }

        // 성능 최적화된 이미지 로더
        definitions.append {
            registerModule.makeModule(ImageLoader.self) {
                OptimizedImageLoader(
                    cacheSize: 100_000_000, // 100MB
                    compressionQuality: 0.8,
                    enableWebP: true
                )
            }
        }
    }

    private mutating func setupTestingModules() {
        print("🧪 테스팅 모듈 설정 중")

        // 테스트를 위한 결정론적 목 서비스
        definitions.append {
            registerModule.makeModule(APIClient.self) {
                DeterministicMockAPIClient()
            }
        }

        definitions.append {
            registerModule.makeModule(Logger.self) {
                SilentLogger() // 테스트 중 출력 없음
            }
        }

        definitions.append {
            registerModule.makeModule(DatabaseService.self) {
                InMemoryDatabaseService(preloadTestData: false)
            }
        }
    }

    func makeAllModules() -> [Module] {
        definitions.map { $0() }
    }
}

// 지원 구성
struct AppConfiguration {
    let devLogPath: String
    let stagingDBConnectionString: String
    let primaryDBConnectionString: String
    let readReplicaConnectionString: String
    let trustedCertificates: [Certificate]
    let logEncryptionKey: String
    let analyticsEndpoint: String
    let privacySettings: PrivacySettings

    static func load() throws -> AppConfiguration {
        // 번들, 환경 변수 또는 원격 구성에서 로드
        // 구현은 앱의 구성 전략에 따라 다름
        fatalError("구성 로딩 구현")
    }
}

비동기 모듈 팩토리

복잡한 초기화 시나리오를 위한 고급 비동기 모듈 팩토리:

swift
struct AsyncModuleFactory {
    private let logger: Logger?
    private let configuration: AppConfiguration
    private let timeout: TimeInterval

    init(configuration: AppConfiguration, logger: Logger? = nil, timeout: TimeInterval = 30) {
        self.configuration = configuration
        self.logger = logger
        self.timeout = timeout
    }

    func makeConfigurationModule() async throws -> Module {
        logger?.info("🔧 원격 구성 로딩 중...")

        do {
            // 타임아웃과 함께 원격 구성 가져오기
            let remoteConfig = try await withTimeout(timeout) {
                try await RemoteConfigService.fetchConfiguration(
                    endpoint: configuration.configEndpoint,
                    apiKey: configuration.configAPIKey
                )
            }

            logger?.info("✅ 원격 구성이 성공적으로 로드되었습니다")

            return Module(RemoteConfiguration.self) {
                remoteConfig
            }
        } catch {
            logger?.warning("⚠️ 원격 구성 로드 실패, 기본값 사용: \(error)")

            // 로컬 구성으로 폴백
            return Module(RemoteConfiguration.self) {
                RemoteConfiguration.defaultConfiguration()
            }
        }
    }

    func makeDatabaseModule() async throws -> Module {
        logger?.info("🗄️ 데이터베이스 연결 초기화 중...")

        do {
            // 재시도 로직으로 데이터베이스 초기화
            let database = try await withRetry(maxAttempts: 3, delay: 1.0) {
                try await DatabaseManager.initialize(
                    connectionString: configuration.primaryDBConnectionString,
                    poolSize: 10,
                    enableSSL: true
                )
            }

            // 데이터베이스 상태 검증
            try await database.healthCheck()

            logger?.info("✅ 데이터베이스가 초기화되고 정상입니다")

            return Module(DatabaseService.self) {
                database
            }
        } catch {
            logger?.error("❌ 데이터베이스 초기화 실패: \(error)")
            throw AsyncModuleError.databaseInitializationFailed(error)
        }
    }

    func makeAuthenticationModule() async throws -> Module {
        logger?.info("🔐 인증 서비스 설정 중...")

        // 인증 구성 로드
        let authConfig = try await AuthConfiguration.load()

        // 인증 공급자 초기화
        let providers = try await initializeAuthProviders(authConfig)

        logger?.info("✅ \(providers.count)개 공급자로 인증 서비스가 구성되었습니다")

        return Module(AuthenticationService.self) {
            MultiProviderAuthenticationService(
                providers: providers,
                defaultProvider: authConfig.defaultProvider
            )
        }
    }

    func makeAnalyticsModule() async throws -> Module {
        logger?.info("📊 분석 서비스 초기화 중...")

        // 분석에 대한 사용자 동의 얻기
        let consentStatus = await AnalyticsConsentManager.getConsentStatus()

        guard consentStatus.analyticsAllowed else {
            logger?.info("📊 사용자 동의로 인해 분석이 비활성화됨")
            return Module(AnalyticsService.self) {
                NoOpAnalyticsService()
            }
        }

        // 동의와 함께 분석 초기화
        let analyticsService = try await AnalyticsService.initialize(
            configuration: configuration.analyticsConfig,
            consentSettings: consentStatus
        )

        logger?.info("✅ 분석 서비스가 초기화되었습니다")

        return Module(AnalyticsService.self) {
            analyticsService
        }
    }

    private func initializeAuthProviders(_ config: AuthConfiguration) async throws -> [AuthProvider] {
        var providers: [AuthProvider] = []

        // OAuth 공급자를 동시에 초기화
        await withTaskGroup(of: AuthProvider?.self) { group in
            for providerConfig in config.providers {
                group.addTask {
                    do {
                        return try await AuthProviderFactory.create(providerConfig)
                    } catch {
                        self.logger?.error("인증 공급자 \(providerConfig.type) 초기화 실패: \(error)")
                        return nil
                    }
                }
            }

            for await provider in group {
                if let provider = provider {
                    providers.append(provider)
                }
            }
        }

        guard !providers.isEmpty else {
            throw AsyncModuleError.noAuthProvidersAvailable
        }

        return providers
    }

    // 배치 비동기 모듈 생성
    func makeAllAsyncModules() async throws -> [Module] {
        logger?.info("⚡ 모든 비동기 모듈을 동시에 생성 중...")

        return try await withThrowingTaskGroup(of: Module.self) { group in
            // 모든 비동기 모듈 생성 작업 추가
            group.addTask { try await self.makeConfigurationModule() }
            group.addTask { try await self.makeDatabaseModule() }
            group.addTask { try await self.makeAuthenticationModule() }
            group.addTask { try await self.makeAnalyticsModule() }

            var modules: [Module] = []
            for try await module in group {
                modules.append(module)
            }
            return modules
        }
    }
}

// 오류 타입
enum AsyncModuleError: LocalizedError {
    case databaseInitializationFailed(Error)
    case configurationLoadFailed(Error)
    case noAuthProvidersAvailable
    case timeoutExceeded

    var errorDescription: String? {
        switch self {
        case .databaseInitializationFailed(let error):
            return "데이터베이스 초기화 실패: \(error.localizedDescription)"
        case .configurationLoadFailed(let error):
            return "구성 로드 실패: \(error.localizedDescription)"
        case .noAuthProvidersAvailable:
            return "초기화할 수 있는 인증 공급자가 없습니다"
        case .timeoutExceeded:
            return "비동기 모듈 초기화 시간 초과"
        }
    }
}

// 유틸리티 함수
func withTimeout<T>(_ timeout: TimeInterval, operation: @escaping () async throws -> T) async throws -> T {
    try await withThrowingTaskGroup(of: T.self) { group in
        group.addTask {
            try await operation()
        }

        group.addTask {
            try await Task.sleep(nanoseconds: UInt64(timeout * 1_000_000_000))
            throw AsyncModuleError.timeoutExceeded
        }

        guard let result = try await group.next() else {
            throw AsyncModuleError.timeoutExceeded
        }

        group.cancelAll()
        return result
    }
}

func withRetry<T>(maxAttempts: Int, delay: TimeInterval, operation: @escaping () async throws -> T) async throws -> T {
    var lastError: Error?

    for attempt in 1...maxAttempts {
        do {
            return try await operation()
        } catch {
            lastError = error
            if attempt < maxAttempts {
                try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
            }
        }
    }

    throw lastError ?? AsyncModuleError.timeoutExceeded
}

// 애플리케이션에서의 사용
func setupAsyncModules() async throws {
    let asyncFactory = AsyncModuleFactory(
        configuration: AppConfiguration.load(),
        logger: AppLogger.shared
    )

    await WeaveDI.Container.bootstrap { container in
        // 먼저 동기 모듈 등록
        var syncFactory = ApplicationModuleFactory()
        await syncFactory.setupAll()

        for module in syncFactory.getAllModules() {
            await container.register(module)
        }

        // 그 다음 비동기 모듈 등록
        do {
            let asyncModules = try await asyncFactory.makeAllAsyncModules()
            for module in asyncModules {
                await container.register(module)
            }
        } catch {
            print("⚠️ 일부 비동기 모듈 초기화 실패: \(error)")
            // 부분 초기화 또는 폴백 전략 처리
        }
    }
}

모범 사례

1. 순서대로 모듈 등록

swift
struct OrderedModuleRegistration {
    static func registerInOrder() async {
        await WeaveDI.Container.bootstrap { container in
            // 1. 인프라 레이어
            let infraModules = InfrastructureModuleFactory().makeAllModules()
            for module in infraModules {
                await container.register(module)
            }

            // 2. 데이터 레이어
            let dataModules = DataModuleFactory().makeAllModules()
            for module in dataModules {
                await container.register(module)
            }

            // 3. 도메인 레이어
            let domainModules = DomainModuleFactory().makeAllModules()
            for module in domainModules {
                await container.register(module)
            }

            // 4. 프레젠테이션 레이어
            let presentationModules = PresentationModuleFactory().makeAllModules()
            for module in presentationModules {
                await container.register(module)
            }
        }
    }
}

2. 테스팅 지원

swift
#if DEBUG
struct TestModuleFactory: ModuleFactory {
    var registerModule = RegisterModule()
    var definitions: [@Sendable () -> Module] = []

    mutating func setupMocks() {
        definitions.append {
            registerModule.makeModule(UserRepository.self) {
                MockUserRepository()
            }
        }

        definitions.append {
            registerModule.makeModule(NetworkService.self) {
                MockNetworkService()
            }
        }
    }

    func makeAllModules() -> [Module] {
        definitions.map { $0() }
    }
}
#endif

3. 오류 처리

swift
struct SafeModuleFactory: ModuleFactory {
    var registerModule = RegisterModule()
    var definitions: [@Sendable () -> Module] = []

    mutating func setup() {
        definitions.append {
            registerModule.makeModule(RiskyService.self) {
                do {
                    return try RiskyServiceImpl()
                } catch {
                    print("RiskyService 생성 실패: \(error)")
                    return FallbackService()
                }
            }
        }
    }

    func makeAllModules() -> [Module] {
        definitions.map { $0() }
    }
}

성능 고려사항

지연 모듈 생성

swift
struct LazyModuleFactory {
    private lazy var expensiveModule = Module(ExpensiveService.self) {
        ExpensiveServiceImpl() // 처음 접근할 때만 생성
    }

    func getExpensiveModule() -> Module {
        expensiveModule
    }
}

WeaveDI의 모듈 팩토리 시스템은 깨끗하고 테스트 가능하며 유지보수 가능한 코드 아키텍처를 유지하면서 복잡한 의존성 그래프를 관리하는 견고한 기반을 제공합니다.

MIT 라이선스 하에 릴리스됨.