Skip to content

Needle 스타일 DI 사용법

WeaveDI에서 Uber의 Needle 프레임워크와 유사한 스타일로 의존성 주입을 사용하는 방법에 대한 가이드입니다.

개요

WeaveDI는 더 나은 개발자 경험을 제공하면서 Needle의 모든 핵심 기능을 제공합니다. 이것은 Needle에서 WeaveDI로 마이그레이션하거나 Needle 스타일로 WeaveDI를 사용하려는 개발자를 위한 완전한 가이드입니다.

🏆 WeaveDI vs Needle 비교

기능NeedleWeaveDI결과
컴파일 타임 안전성✅ 코드 생성✅ 매크로 기반동등
런타임 성능⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐WeaveDI 승리
Swift 6 지원⚠️ 제한적✅ 완벽한 네이티브WeaveDI 승리
필수 코드 생성❌ 필수✅ 선택WeaveDI 승리
학습 곡선❌ 가파름✅ 점진적WeaveDI 승리
마이그레이션❌ 전체 전환✅ 점진적WeaveDI 승리

🚀 빠른 시작

1. Needle 수준 성능 활성화

swift
import WeaveDI

@main
struct MyApp: App {
    init() {
        // Needle과 동일한 제로 비용 성능 활성화
        UnifiedDI.enableStaticOptimization()
        setupDependencies()
    }
}

빌드 설정 (최대 성능을 위해):

bash
# Xcode: Build Settings → Other Swift Flags에 추가
-DUSE_STATIC_FACTORY

# 또는 SPM 명령
swift build -c release -Xswiftc -DUSE_STATIC_FACTORY

2. 컴파일 타임 의존성 검증

swift
// Needle의 핵심 장점: 컴파일 타임 안전성
@DependencyGraph([
    UserService.self: [NetworkService.self, Logger.self],
    NetworkService.self: [Logger.self, DatabaseService.self],
    DatabaseService.self: [Logger.self]
])
extension WeaveDI {}

// ✅ 정상: 의존성 그래프가 올바름
// ❌ 순환 의존성이 있으면 컴파일 에러!

📋 Needle 스타일 사용 패턴

패턴 1: 컴포넌트 기반 등록

Needle 방식:

swift
// Needle 코드
import NeedleFoundation

class AppComponent: Component<EmptyDependency> {
    var userService: UserServiceProtocol {
        return UserServiceImpl(networkService: networkService)
    }

    var networkService: NetworkServiceProtocol {
        return NetworkServiceImpl(logger: logger)
    }

    var logger: LoggerProtocol {
        return ConsoleLogger()
    }
}

WeaveDI 동등 코드:

swift
// WeaveDI: 더 간단하고 강력함
import WeaveDI

extension UnifiedDI {
    // 컴포넌트 스타일 의존성 설정
    static func setupAppComponent() {
        // 기본 서비스
        _ = register(LoggerProtocol.self) { ConsoleLogger() }
        _ = register(NetworkServiceProtocol.self) {
            NetworkServiceImpl(logger: resolve(LoggerProtocol.self)!)
        }
        _ = register(UserServiceProtocol.self) {
            UserServiceImpl(networkService: resolve(NetworkServiceProtocol.self)!)
        }

        // Needle 스타일 검증
        _ = validateNeedleStyle(
            component: AppComponent.self,
            dependencies: [LoggerProtocol.self, NetworkServiceProtocol.self, UserServiceProtocol.self]
        )
    }
}

패턴 2: 계층적 의존성 구조

WeaveDI에서 Needle 스타일 계층 구조:

swift
// 1. 루트 컴포넌트 (앱 전체 공통)
extension UnifiedDI {
    static func setupRootComponent() {
        _ = register(Logger.self) { OSLogger() }
        _ = register(NetworkClient.self) { URLSessionClient() }
        _ = register(DatabaseClient.self) { CoreDataClient() }
    }
}

// 2. 기능 컴포넌트 (기능별)
extension UnifiedDI {
    static func setupUserFeature() {
        _ = register(UserRepository.self) {
            UserRepositoryImpl(
                network: resolve(NetworkClient.self)!,
                database: resolve(DatabaseClient.self)!
            )
        }
        _ = register(UserService.self) {
            UserServiceImpl(repository: resolve(UserRepository.self)!)
        }
    }

    static func setupAuthFeature() {
        _ = register(AuthRepository.self) {
            AuthRepositoryImpl(network: resolve(NetworkClient.self)!)
        }
        _ = register(AuthService.self) {
            AuthServiceImpl(repository: resolve(AuthRepository.self)!)
        }
    }
}

// 3. 컴파일 타임 그래프 검증
@DependencyGraph([
    UserService.self: [UserRepository.self],
    UserRepository.self: [NetworkClient.self, DatabaseClient.self],
    AuthService.self: [AuthRepository.self],
    AuthRepository.self: [NetworkClient.self],
    NetworkClient.self: [Logger.self],
    DatabaseClient.self: [Logger.self]
])
extension WeaveDI {}

패턴 3: 고성능 해결 (Needle 수준)

swift
class PerformanceCriticalViewModel {
    // 일반 사용 (편의성 우선)
    @Inject private var userService: UserService?

    // 필요한 곳에서 고성능 (Needle 수준 제로 비용)
    func performanceHotPath() {
        // 정적 해결: 런타임 오버헤드 완전 제거
        let fastUserService = UnifiedDI.staticResolve(UserService.self)

        // 루프에서 최적화
        for _ in 0..<10000 {
            // 매번 해결하는 대신 캐시된 인스턴스 사용
            fastUserService?.performQuickOperation()
        }
    }
}

🔄 Needle 마이그레이션 가이드

단계별 마이그레이션

swift
// 1. 마이그레이션 가이드 확인
func checkMigrationGuide() {
    print(UnifiedDI.migrateFromNeedle())
    // 상세한 단계별 가이드 출력

    print(UnifiedDI.needleMigrationBenefits())
    // 마이그레이션 이점 분석
}

// 2. 점진적 마이그레이션 (Needle의 전체 전환과 다름)
class HybridApproach {
    // 기존 Needle 코드 유지
    private let legacyService = NeedleContainer.resolve(LegacyService.self)

    // 새 코드에만 WeaveDI 사용
    @Inject private var newService: NewService?

    func migrate() {
        // 하나씩 점진적으로 변경 가능
        let mixedResult = legacyService.work() + (newService?.work() ?? "")
    }
}

자동 변환 도구

swift
// 자동 Needle 컴포넌트 검증
extension UnifiedDI {
    static func validateNeedleComponent() -> Bool {
        // 기존 Needle 스타일 의존성 검증
        let dependencies: [Any.Type] = [
            UserService.self,
            NetworkService.self,
            Logger.self
        ]

        return validateNeedleStyle(
            component: AppComponent.self,
            dependencies: dependencies
        )
    }
}

🎯 실제 프로젝트 적용

대규모 앱 구조 예제

swift
// AppDelegate.swift
class AppDelegate: UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Needle 수준 성능 활성화
        UnifiedDI.enableStaticOptimization()

        // 계층적 의존성 설정
        setupCoreDependencies()
        setupFeatureDependencies()
        setupUIDependencies()

        // 의존성 그래프 검증
        validateDependencyGraph()

        return true
    }

    private func setupCoreDependencies() {
        // 핵심 레이어 (Needle의 Root Component와 유사)
        _ = UnifiedDI.register(Logger.self) { OSLogger() }
        _ = UnifiedDI.register(NetworkClient.self) { URLSessionClient() }
        _ = UnifiedDI.register(DatabaseClient.self) { CoreDataClient() }
        _ = UnifiedDI.register(CacheClient.self) { NSCacheClient() }
    }

    private func setupFeatureDependencies() {
        // 비즈니스 레이어 (Needle의 Feature Component와 유사)
        _ = UnifiedDI.register(UserRepository.self) { UserRepositoryImpl() }
        _ = UnifiedDI.register(AuthRepository.self) { AuthRepositoryImpl() }
        _ = UnifiedDI.register(ProductRepository.self) { ProductRepositoryImpl() }

        _ = UnifiedDI.register(UserService.self) { UserServiceImpl() }
        _ = UnifiedDI.register(AuthService.self) { AuthServiceImpl() }
        _ = UnifiedDI.register(ProductService.self) { ProductServiceImpl() }
    }

    private func setupUIDependencies() {
        // 프레젠테이션 레이어
        _ = UnifiedDI.register(UserViewModel.self) { UserViewModel() }
        _ = UnifiedDI.register(AuthViewModel.self) { AuthViewModel() }
        _ = UnifiedDI.register(ProductViewModel.self) { ProductViewModel() }
    }

    private func validateDependencyGraph() {
        // Needle 스타일 검증
        _ = UnifiedDI.validateNeedleStyle(
            component: AppComponent.self,
            dependencies: [
                Logger.self, NetworkClient.self, DatabaseClient.self,
                UserService.self, AuthService.self, ProductService.self
            ]
        )

        print("✅ 모든 Needle 스타일 의존성 검증 완료")
    }
}

// DependencyGraph.swift - 컴파일 타임 검증
@DependencyGraph([
    // UI 레이어
    UserViewModel.self: [UserService.self],
    AuthViewModel.self: [AuthService.self],
    ProductViewModel.self: [ProductService.self],

    // 비즈니스 레이어
    UserService.self: [UserRepository.self, Logger.self],
    AuthService.self: [AuthRepository.self, Logger.self],
    ProductService.self: [ProductRepository.self, CacheClient.self, Logger.self],

    // 데이터 레이어
    UserRepository.self: [NetworkClient.self, DatabaseClient.self],
    AuthRepository.self: [NetworkClient.self],
    ProductRepository.self: [NetworkClient.self, DatabaseClient.self],

    // 핵심 레이어
    NetworkClient.self: [Logger.self],
    DatabaseClient.self: [Logger.self],
    CacheClient.self: [Logger.self]
])
extension WeaveDI {}

📊 성능 모니터링

swift
// Needle과 달리 실시간 성능 분석 제공
class PerformanceAnalyzer {
    func analyzeDIPerformance() {
        // WeaveDI vs Needle 성능 비교
        print(UnifiedDI.performanceComparison())
        /*
        출력:
        🏆 WeaveDI vs Needle 성능:
        ✅ 컴파일 타임 안전성: 동등
        ✅ 런타임 성능: 동등 (제로 비용)
        🚀 개발자 경험: WeaveDI 우수
        🎯 Swift 6 지원: WeaveDI 독점
        */

        // 실시간 성능 통계
        let stats = UnifiedDI.stats()
        print("📊 DI 사용 통계: \(stats)")

        // Actor hop 최적화 분석 (Needle에 없는 기능)
        Task {
            let hopStats = await UnifiedDI.actorHopStats
            let optimizations = await UnifiedDI.actorOptimizations

            print("⚡ Actor Hop 통계: \(hopStats)")
            print("🤖 최적화 제안: \(optimizations)")
        }
    }
}

🎨 고급 사용법

Swift 6 동시성과 함께

swift
// Needle은 Swift 6 지원이 제한적이지만 WeaveDI는 완벽한 지원
actor DataManager {
    @Inject private var networkService: NetworkService?
    @Inject private var databaseService: DatabaseService?

    func syncData() async {
        // Actor 내에서 안전한 DI 사용
        let networkData = await networkService?.fetchData()
        await databaseService?.save(networkData)
    }
}

// MainActor에서도 안전
@MainActor
class UIViewModel: ObservableObject {
    @Inject private var userService: UserService?

    func updateUI() {
        // MainActor 컨텍스트에서 안전한 DI 해결
        userService?.updateUserData()
    }
}

모듈 기반 의존성 관리

swift
// 대규모 프로젝트를 위한 모듈 기반 관리
enum DIModule {
    case core
    case user
    case auth
    case product
}

extension UnifiedDI {
    static func setup(module: DIModule) {
        switch module {
        case .core:
            setupCoreModule()
        case .user:
            setupUserModule()
        case .auth:
            setupAuthModule()
        case .product:
            setupProductModule()
        }
    }

    private static func setupCoreModule() {
        // 핵심 모듈 의존성
        _ = register(Logger.self) { OSLogger() }
        _ = register(NetworkClient.self) { URLSessionClient() }
    }

    // ... 다른 모듈들
}

📝 체크리스트

✅ Needle에서 WeaveDI로 마이그레이션

  • [ ] import WeaveDI 추가
  • [ ] UnifiedDI.enableStaticOptimization() 호출
  • [ ] 빌드 플래그에 -DUSE_STATIC_FACTORY 추가 (최대 성능을 위해)
  • [ ] @DependencyGraph로 컴파일 타임 검증 설정
  • [ ] validateNeedleStyle()로 호환성 확인
  • [ ] 기존 Component를 WeaveDI 스타일로 점진적 전환

✅ 새 프로젝트에서 Needle 스타일 WeaveDI 사용

  • [ ] 계층적 의존성 구조 설계
  • [ ] 컴포넌트 스타일 의존성 등록
  • [ ] 컴파일 타임 의존성 그래프 정의
  • [ ] 성능에 민감한 부분에 staticResolve() 적용
  • [ ] 실시간 성능 모니터링 설정

🚀 결론

WeaveDI는 Needle의 모든 핵심 장점을 제공하면서 다음을 추가로 제공합니다:

  • 더 쉬운 사용: 코드 생성 도구 불필요
  • 더 나은 성능: Actor hop 최적화 + 실시간 분석
  • 더 안전한 마이그레이션: 점진적 전환 가능
  • 더 현대적: 완벽한 Swift 6 지원

Needle을 사용 중이시라면 WeaveDI로의 마이그레이션을 강력히 권장합니다! 🏆

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