Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Roy-wonji/WeaveDI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

WeaveDI โ€“ App Image

WeaveDI

SPM Swift License Platform Docs

ํ˜„๋Œ€์ ์ธ Swift Concurrency๋ฅผ ์œ„ํ•œ ๊ฐ„๋‹จํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ์˜์กด์„ฑ ์ฃผ์ž… ํ”„๋ ˆ์ž„์›Œํฌ

์ฐธ๊ณ : ์ฝ๊ธฐ(๊ทธ๋ž˜ํ”„/ํ†ต๊ณ„/์ตœ์ ํ™” ์—ฌ๋ถ€)๋Š” UnifiedDI/DIContainer์˜ ๋™๊ธฐ ํ—ฌํผ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋‚ด๋ถ€ AutoDIOptimizer์˜ ์ฝ๊ธฐ์šฉ API๋Š” ์Šค๋ƒ…์ƒท ๊ธฐ๋ฐ˜ ๋‚ด๋ถ€์šฉ์ด๋ฉฐ ์™ธ๋ถ€ ์ง์ ‘ ํ˜ธ์ถœ์€ ๋น„๊ถŒ์žฅ(Deprecated)์ž…๋‹ˆ๋‹ค.

๐Ÿ“– ๋ฌธ์„œ: ํ•œ๊ตญ์–ด | English | ๊ณต์‹ ๋ฌธ์„œ | ๋กœ๋“œ๋งต

๐ŸŽฏ ํ•ต์‹ฌ ํŠน์ง•

  • โšก Swift Concurrency ๋„ค์ดํ‹ฐ๋ธŒ: async/await์™€ Actor ์™„๋ฒฝ ์ง€์›
  • ๐Ÿ”’ ํƒ€์ž… ์•ˆ์ „์„ฑ: ์ปดํŒŒ์ผ ํƒ€์ž„ ํƒ€์ž… ๊ฒ€์ฆ
  • ๐Ÿ“ TCA ์Šคํƒ€์ผ ์˜์กด์„ฑ ์ฃผ์ž…: @Injected๋กœ KeyPath์™€ ํƒ€์ž… ๊ธฐ๋ฐ˜ ์ฃผ์ž… ์ง€์› (v3.2.0)
  • ๐Ÿ—๏ธ AppDI ๊ฐ„์†Œํ™”: AppDIManager๋กœ ์ž๋™ ์˜์กด์„ฑ ๋“ฑ๋ก (v3.2.0)
  • ๐ŸŽฏ Needle-style Components: @Component ๋งคํฌ๋กœ๋กœ 10x ๋น ๋ฅธ Needle ํ˜ธํ™˜์„ฑ (v3.2.1)
  • โšก UnifiedRegistry: TypeSafeRegistry ํ†ตํ•ฉ์œผ๋กœ ์„ฑ๋Šฅ๊ณผ ๋™์‹œ์„ฑ ์•ˆ์ „์„ฑ ํ–ฅ์ƒ (v3.2.1)
  • ๐Ÿค– ์ž๋™ ์ตœ์ ํ™”: ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„, Actor hop ๊ฐ์ง€, ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฒ€์ฆ ์ž๋™ํ™”
  • ๐Ÿš€ ๋Ÿฐํƒ€์ž„ ํ•ซํŒจ์Šค ์ตœ์ ํ™”: TypeID + ๋ฝ-ํ”„๋ฆฌ ์ฝ๊ธฐ๋กœ 50-80% ์„ฑ๋Šฅ ํ–ฅ์ƒ
  • ๐Ÿงช ํ…Œ์ŠคํŠธ ์นœํ™”์ : ์˜์กด์„ฑ ๋ชจํ‚น๊ณผ ๊ฒฉ๋ฆฌ ์ง€์›

๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘

์„ค์น˜

dependencies: [
    .package(url: "https://github.com/Roy-wonji/WeaveDI.git", from: "3.2.1")
]

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• (v3.2.0)

import WeaveDI

// 1. ์•ฑ ์ดˆ๊ธฐํ™” - ์ž๋™ ์˜์กด์„ฑ ๋“ฑ๋ก
@main
struct MyApp: App {
    init() {
        WeaveDI.Container.bootstrapInTask { @DIContainerActor _ in
            await AppDIManager.shared.registerDefaultDependencies()
        }
    }
}

// 2. TCA ์Šคํƒ€์ผ @Injected ์‚ฌ์šฉ (๊ถŒ์žฅ)
class ViewModel {
    @Injected(\.userService) var userService
    @Injected(ExchangeUseCaseImpl.self) var exchangeUseCase

    func loadData() async {
        let data = await userService.fetchData()
    }
}

// 3. InjectedKey๋กœ ์˜์กด์„ฑ ์ •์˜
extension InjectedValues {
    var userService: UserServiceProtocol {
        get { self[UserServiceKey.self] }
        set { self[UserServiceKey.self] = newValue }
    }
}

struct UserServiceKey: InjectedKey {
    static var currentValue: UserServiceProtocol = UserService()
}

// โš ๏ธ ๋ ˆ๊ฑฐ์‹œ Property Wrapper (v3.2.0๋ถ€ํ„ฐ Deprecated)
class LegacyViewController {
    @Inject var userService: UserServiceProtocol?     // (v3.2.0๋ถ€ํ„ฐ Deprecated)
    @Factory var generator: PDFGenerator              // ์œ ์ง€๋จ
    @SafeInject var apiService: APIServiceProtocol?   // (v3.2.0๋ถ€ํ„ฐ Deprecated)
}

// ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ: @Injected๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
// ๋” ๋‚˜์€ ํƒ€์ž… ์•ˆ์ „์„ฑ๊ณผ TCA ์Šคํƒ€์ผ KeyPath ์ ‘๊ทผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค

๐ŸŽจ Swift ๋งคํฌ๋กœ ์ง€์› (v3.2.1+)

WeaveDI๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„ ์ตœ์ ํ™”์™€ Needle ์Šคํƒ€์ผ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ Swift ๋งคํฌ๋กœ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

@Component - Needle ์Šคํƒ€์ผ ์ปดํฌ๋„ŒํŠธ (10x ๋น ๋ฆ„)

import WeaveDI

@Component
public struct UserComponent {
    @Provide var userService: UserService = UserService()
    @Provide var userRepository: UserRepository = UserRepository()
    @Provide var authService: AuthService = AuthService()
}

// ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ž๋™ ์ƒ์„ฑ๋จ:
// UnifiedDI.register(UserService.self) { UserService() }
// UnifiedDI.register(UserRepository.self) { UserRepository() }
// UnifiedDI.register(AuthService.self) { AuthService() }

@AutoRegister - ์ž๋™ ์˜์กด์„ฑ ๋“ฑ๋ก

@AutoRegister(lifetime: .singleton)
class DatabaseService: DatabaseServiceProtocol {
    // ์ž๋™์œผ๋กœ UnifiedDI์— ๋“ฑ๋ก๋จ
}

@AutoRegister(lifetime: .transient)
class RequestHandler: RequestHandlerProtocol {
    // ๋งค๋ฒˆ ์ƒˆ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
}

@DIActor - Swift Concurrency ์ตœ์ ํ™”

@DIActor
public final class AutoMonitor {
    public static let shared = AutoMonitor()

    // ๋ชจ๋“  ๋ฉ”์„œ๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•ด์ง
    public func onModuleRegistered<T>(_ type: T.Type) {
        // Actor ๊ฒฉ๋ฆฌ๋œ ์•ˆ์ „ํ•œ ์ž‘์—…
    }
}

@DependencyGraph - ์ปดํŒŒ์ผ ํƒ€์ž„ ๊ฒ€์ฆ

@DependencyGraph([
    UserService.self: [UserRepository.self, Logger.self],
    UserRepository.self: [DatabaseService.self],
    DatabaseService.self: [],
    Logger.self: []
])
class ApplicationDependencyGraph {
    // โœ… ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ˆœํ™˜ ์˜์กด์„ฑ ๊ฒ€์ฆ
}

์„ฑ๋Šฅ ๋น„๊ต (WeaveDI vs ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ)

ํ”„๋ ˆ์ž„์›Œํฌ ๋“ฑ๋ก ํ•ด๊ฒฐ ๋ฉ”๋ชจ๋ฆฌ ๋™์‹œ์„ฑ
Swinject ~1.2ms ~0.8ms ๋†’์Œ ์ˆ˜๋™ ๋ฝ
Needle ~0.8ms ~0.6ms ๋ณดํ†ต ์ œํ•œ์ 
WeaveDI ~0.2ms ~0.1ms ๋‚ฎ์Œ ๋„ค์ดํ‹ฐ๋ธŒ async/await

๋” ์ž์„ธํ•œ ๋งคํฌ๋กœ ์‚ฌ์šฉ๋ฒ•์€ WeaveDI ๋งคํฌ๋กœ ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋ถ€ํŠธ์ŠคํŠธ๋žฉ(์•ฑ ์‹œ์ž‘ ์‹œ ์ดˆ๊ธฐํ™”)

import WeaveDI

// ๋™๊ธฐ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ
await DIContainer.bootstrap { di in
    di.register(Logger.self) { ConsoleLogger() }
    di.register(Networking.self) { DefaultNetworking() }
}

// ๋น„๋™๊ธฐ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ
let ok = await DIContainer.bootstrapAsync { di in
    let flags = try await FeatureFlags.fetch()
    di.register(FeatureFlags.self) { flags }
}

// ํ˜ผํ•ฉ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ
@MainActor
await DIContainer.bootstrapMixed(
    sync: { di in di.register(Logger.self) { ConsoleLogger() } },
    async: { di in
        let analytics = await AnalyticsClient.make()
        di.register(AnalyticsClient.self) { analytics }
    }
)

// ์กฐ๊ฑด๋ถ€ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ
_ = await DIContainer.bootstrapIfNeeded { di in
    di.register(Config.self) { LocalConfig() }
}

// ๋ณด์žฅ/ํ…Œ์ŠคํŠธ
DIContainer.ensureBootstrapped()
@MainActor
DIContainer.resetForTesting() // DEBUG ์ „์šฉ

์ฝ๊ธฐ(๊ทธ๋ž˜ํ”„/ํ†ต๊ณ„/์ตœ์ ํ™” ์—ฌ๋ถ€)๋Š” UnifiedDI/DIContainer์˜ ๋™๊ธฐ ํ—ฌํผ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€ AutoDIOptimizer ๋ฆฌ๋”๋Š” ์Šค๋ƒ…์ƒท ๊ธฐ๋ฐ˜ ๋‚ด๋ถ€์šฉ์ด๋ฉฐ, ์™ธ๋ถ€ ์ง์ ‘ ํ˜ธ์ถœ์€ ๋น„๊ถŒ์žฅ(Deprecated)์ž…๋‹ˆ๋‹ค.

๐Ÿ“š ํ•ต์‹ฌ API

๋“ฑ๋ก API

// ๊ธฐ๋ณธ ๋“ฑ๋ก (๊ถŒ์žฅ)
let service = UnifiedDI.register(ServiceProtocol.self) {
    ServiceImpl()
}

// KeyPath ๋“ฑ๋ก
let repository = UnifiedDI.register(\.userRepository) {
    UserRepositoryImpl()
}

// ์กฐ๊ฑด๋ถ€ ๋“ฑ๋ก
let service = UnifiedDI.Conditional.registerIf(
    ServiceProtocol.self,
    condition: isProduction,
    factory: { ProductionService() },
    fallback: { MockService() }
)

// ์Šค์ฝ”ํ”„ ๊ธฐ๋ฐ˜ ๋“ฑ๋ก
let sessionService = UnifiedDI.registerScoped(
    SessionService.self,
    scope: .session
) {
    SessionServiceImpl()
}

Property Wrapper

Property Wrapper ์šฉ๋„ ์˜ˆ์‹œ ์ƒํƒœ
@Injected TCA ์Šคํƒ€์ผ ์ฃผ์ž… (๊ถŒ์žฅ) @Injected(\.service) var service โœ… v3.2.0
@Factory ํŒฉํ† ๋ฆฌ ํŒจํ„ด (์ƒˆ ์ธ์Šคํ„ด์Šค) @Factory var generator: Generator โœ… ์œ ์ง€
@Inject ๊ธฐ๋ณธ ์ฃผ์ž… (๋ ˆ๊ฑฐ์‹œ) @Inject var service: Service? โš ๏ธ (v3.2.0๋ถ€ํ„ฐ Deprecated)
@SafeInject ์•ˆ์ „ํ•œ ์ฃผ์ž… (๋ ˆ๊ฑฐ์‹œ) @SafeInject var api: API? โš ๏ธ (v3.2.0๋ถ€ํ„ฐ Deprecated)

๐Ÿ“– ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ: @Injected ๋ฌธ์„œ | AppDI ๊ฐ„์†Œํ™”

ํ•ด๊ฒฐ API

// ์ผ๋ฐ˜ ํ•ด๊ฒฐ
let service = UnifiedDI.resolve(ServiceProtocol.self)

// ํ•„์ˆ˜ ํ•ด๊ฒฐ (์—†์œผ๋ฉด ํฌ๋ž˜์‹œ)
let logger = UnifiedDI.requireResolve(Logger.self)

// ๊ธฐ๋ณธ๊ฐ’ ํฌํ•จ ํ•ด๊ฒฐ
let cache = UnifiedDI.resolve(Cache.self, default: MemoryCache())

๐Ÿค– ์ž๋™ ์ตœ์ ํ™”

๋ณ„๋„ ์„ค์ • ์—†์ด ์ž๋™์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค:

๐Ÿ”„ ์ž๋™ ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ

// ๋“ฑ๋ก/ํ•ด๊ฒฐ๋งŒ ํ•˜๋ฉด ์ž๋™์œผ๋กœ ๊ทธ๋ž˜ํ”„ ์ƒ์„ฑ ๋ฐ ์ตœ์ ํ™”
let service = UnifiedDI.register(UserService.self) { UserServiceImpl() }
let resolved = UnifiedDI.resolve(UserService.self)

// ์ž๋™ ์ˆ˜์ง‘๋œ ์ •๋ณด๋Š” LogMacro๋กœ ์ž๋™ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค
// ๐Ÿ“Š Auto tracking registration: UserService
// โšก Auto optimized: UserService (10 uses)

๐ŸŽฏ ์ž๋™ Actor Hop ๊ฐ์ง€ ๋ฐ ์ตœ์ ํ™”

// ํ•ด๊ฒฐํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ์ž๋™์œผ๋กœ Actor hop ๊ฐ์ง€
await withTaskGroup(of: Void.self) { group in
    for _ in 1...10 {
        group.addTask {
            _ = UnifiedDI.resolve(UserService.self) // Actor hop ์ž๋™ ๊ฐ์ง€
        }
    }
}

// ์ž๋™ ๋กœ๊ทธ (5ํšŒ ์ด์ƒ hop ๋ฐœ์ƒ ์‹œ):
// ๐ŸŽฏ Actor optimization suggestion for UserService: MainActor๋กœ ์ด๋™ ๊ถŒ์žฅ

๐Ÿ”’ ์ž๋™ ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฒ€์ฆ

// ํ•ด๊ฒฐ ์‹œ ์ž๋™์œผ๋กœ ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฒ€์ฆ
let service = UnifiedDI.resolve(UserService.self)

// ์ž๋™ ๋กœ๊ทธ (๋ฌธ์ œ ๊ฐ์ง€ ์‹œ):
// ๐Ÿ”’ Type safety issue: UserService is not Sendable
// ๐Ÿšจ Auto safety check: UserService resolved to nil

โšก ์ž๋™ ์„ฑ๋Šฅ ์ตœ์ ํ™”

// ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•˜๋ฉด ์ž๋™์œผ๋กœ ์ตœ์ ํ™”๋จ
for _ in 1...15 {
    let service = UnifiedDI.resolve(UserService.self)
}

// ์ตœ์ ํ™”๋œ ํƒ€์ž…๋“ค์€ ์ž๋™์œผ๋กœ ๋กœ๊น…๋ฉ๋‹ˆ๋‹ค
// โšก Auto optimized: UserService (15 uses)

๐Ÿ“Š ์ž๋™ ์‚ฌ์šฉ ํ†ต๊ณ„ ์ˆ˜์ง‘

// ์‚ฌ์šฉ ํ†ต๊ณ„๋Š” 30์ดˆ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ๋กœ๊น…๋ฉ๋‹ˆ๋‹ค
// ๐Ÿ“Š [AutoDI] Current stats: ["UserService": 15, "DataRepository": 8]

๊ณ ์„ฑ๋Šฅ์ด ์š”๊ตฌ๋˜๋Š” ์•ฑ์„ ์œ„ํ•œ ๋ฏธ์„ธ ์ตœ์ ํ™” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์ตœ์ ํ™” ํ™œ์„ฑํ™”

import WeaveDI

// ์ตœ์ ํ™” ๋ชจ๋“œ ํ™œ์„ฑํ™” (๊ธฐ์กด API๋Š” ๊ทธ๋Œ€๋กœ ์ž‘๋™)
UnifiedRegistry.shared.enableOptimization()

// ๊ธฐ์กด ์ฝ”๋“œ๋Š” ๋ณ€๊ฒฝ ์—†์ด ์„ฑ๋Šฅ ํ–ฅ์ƒ
let service = await UnifiedDI.resolve(UserService.self)

ํ•ต์‹ฌ ์ตœ์ ํ™” ๊ธฐ์ˆ 

  1. TypeID + ์ธ๋ฑ์Šค ์ ‘๊ทผ: ๋”•์…”๋„ˆ๋ฆฌ โ†’ ๋ฐฐ์—ด ์Šฌ๋กฏ์œผ๋กœ O(1) ์ ‘๊ทผ
  2. ๋ฝ-ํ”„๋ฆฌ ์ฝ๊ธฐ: ์Šค๋ƒ…์ƒท ๋ฐฉ์‹์œผ๋กœ ์ฝ๊ธฐ ๊ฒฝํ•ฉ ์ œ๊ฑฐ
  3. ์ธ๋ผ์ธ ์ตœ์ ํ™”: ํ•จ์ˆ˜ ํ˜ธ์ถœ ์˜ค๋ฒ„ํ—ค๋“œ ์ถ•์†Œ
  4. ํŒฉํ† ๋ฆฌ ์ฒด์ด๋‹ ์ œ๊ฑฐ: ์ง์ ‘ ํ˜ธ์ถœ ๊ฒฝ๋กœ๋กœ ์ค‘๊ฐ„ ๋‹จ๊ณ„ ์ œ๊ฑฐ
  5. ์Šค์ฝ”ํ”„๋ณ„ ์ €์žฅ์†Œ: ์‹ฑ๊ธ€ํ†ค/์„ธ์…˜/์š”์ฒญ ์Šค์ฝ”ํ”„ ๋ถ„๋ฆฌ ์ตœ์ ํ™”

์˜ˆ์ƒ ์„ฑ๋Šฅ ํ–ฅ์ƒ

์‹œ๋‚˜๋ฆฌ์˜ค ๊ฐœ์„ ์œจ ์„ค๋ช…
๋‹จ์ผ ์Šค๋ ˆ๋“œ resolve 50-80% TypeID + ์ง์ ‘ ์ ‘๊ทผ
๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์ฝ๊ธฐ 2-3๋ฐฐ ๋ฝ-ํ”„๋ฆฌ ์Šค๋ƒ…์ƒท
๋ณต์žกํ•œ ์˜์กด์„ฑ 20-40% ์ฒด์ธ ํ”Œ๋ž˜ํŠผํ™”

๋ฒค์น˜๋งˆํฌ ์‹คํ–‰

swift run -c release Benchmarks --count 100k --quick

์ž์„ธํ•œ ๋‚ด์šฉ์€ PERFORMANCE-OPTIMIZATION.md๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋กœ๊น… ์ œ์–ด (๊ธฐ๋ณธ๊ฐ’: ๋ชจ๋“  ๋กœ๊ทธ ํ™œ์„ฑํ™”)

UnifiedDI.setLogLevel(.registration)  // ๋“ฑ๋ก๋งŒ ๋กœ๊น…
UnifiedDI.setLogLevel(.optimization)  // ์ตœ์ ํ™”๋งŒ ๋กœ๊น…
UnifiedDI.setLogLevel(.errors)       // ์—๋Ÿฌ/๊ฒฝ๊ณ ๋งŒ ๋กœ๊น…
UnifiedDI.setLogLevel(.off)          // ๋กœ๊น… ๋„๊ธฐ

๐Ÿงช ํ…Œ์ŠคํŠธ

// ํ…Œ์ŠคํŠธ์šฉ ์ดˆ๊ธฐํ™”
@MainActor
override func setUp() {
    UnifiedDI.releaseAll()

    // ํ…Œ์ŠคํŠธ์šฉ ์˜์กด์„ฑ ๋“ฑ๋ก
    _ = UnifiedDI.register(UserService.self) {
        MockUserService()
    }
}

๐Ÿ“‹ ์ž๋™ ์ˆ˜์ง‘ ์ •๋ณด ํ™•์ธ

// ๐Ÿ”„ ์ž๋™ ์ƒ์„ฑ๋œ ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„
UnifiedDI.autoGraph

// โšก ์ž๋™ ์ตœ์ ํ™”๋œ ํƒ€์ž…๋“ค
UnifiedDI.optimizedTypes

// ๐Ÿ“Š ์ž๋™ ์ˆ˜์ง‘๋œ ์‚ฌ์šฉ ํ†ต๊ณ„
UnifiedDI.stats

// ๐ŸŽฏ Actor ์ตœ์ ํ™” ์ œ์•ˆ ๋ชฉ๋ก
UnifiedDI.actorOptimizations

// ๐Ÿ”’ ํƒ€์ž… ์•ˆ์ „์„ฑ ์ด์Šˆ ๋ชฉ๋ก
UnifiedDI.typeSafetyIssues
//

// โšก Actor hop ํ†ต๊ณ„
UnifiedDI.actorHopStats

// ๐Ÿ“Š ๋น„๋™๊ธฐ ์„ฑ๋Šฅ ํ†ต๊ณ„ (๋ฐ€๋ฆฌ์ดˆ)
UnifiedDI.asyncPerformanceStats

๐Ÿ”ง Deprecated ์ฝ๊ธฐ API (๋Œ€์ฒด ๊ฒฝ๋กœ)

์•„๋ž˜ AutoDIOptimizer์˜ ์ฝ๊ธฐ์šฉ API๋Š” ๋‚ด๋ถ€ ์Šค๋ƒ…์ƒท ๊ธฐ๋ฐ˜์œผ๋กœ ์žฌ๊ตฌ์„ฑ๋˜์—ˆ์œผ๋ฉฐ, ์™ธ๋ถ€ ์‚ฌ์šฉ์€ ๋น„๊ถŒ์žฅ(Deprecated)์ž…๋‹ˆ๋‹ค. UnifiedDI/DIContainer์˜ ๋™๊ธฐ ํ—ฌํผ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

Deprecated (AutoDIOptimizer) Replacement
getCurrentStats() UnifiedDI.stats() / DIContainer.getUsageStatistics()
visualizeGraph() UnifiedDI.autoGraph() / DIContainer.getAutoGeneratedGraph()
getFrequentlyUsedTypes() UnifiedDI.optimizedTypes() / DIContainer.getOptimizedTypes()
getDetectedCircularDependencies() UnifiedDI.circularDependencies() / DIContainer.getDetectedCircularDependencies()
isOptimized(_:) UnifiedDI.isOptimized(_:) / DIContainer.isAutoOptimized(_:)
getActorOptimizationSuggestions() UnifiedDI.actorOptimizations
getDetectedTypeSafetyIssues() UnifiedDI.typeSafetyIssues
getDetectedAutoFixedTypes() UnifiedDI.autoFixedTypes
getActorHopStats() UnifiedDI.actorHopStats
getAsyncPerformanceStats() UnifiedDI.asyncPerformanceStats
getRecentGraphChanges(...) UnifiedDI.getGraphChanges(...)
getCurrentLogLevel() UnifiedDI.logLevel / UnifiedDI.getLogLevel()

๋‚ด๋ถ€ ์šฉ๋„๋กœ๋Š” AutoDIOptimizer.readSnapshot()๋ฅผ ํ†ตํ•ด ์Šค๋ƒ…์ƒท์„ ์ฝ์–ด ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๊ณ„์‚ฐํ•˜์„ธ์š”.

๐Ÿงช ์„ฑ๋Šฅ ๋ฒค์น˜ ํ…œํ”Œ๋ฆฟ

์‹คํ–‰:

swift run -c release Benchmarks -- --count 100000 --debounce 100

# ์—ฌ๋Ÿฌ ์กฐํ•ฉ ํ…Œ์ŠคํŠธ(10k/100k/1M ร— 50/100/200ms)
swift run -c release Benchmarks

์ถœ๋ ฅ ์˜ˆ์‹œ:

๐Ÿ“Š Bench: counts=[10000, 100000, 1000000], debounces=[50, 100, 200] (ms)
debounce= 50ms, n=     10000 | total=   12.34ms | p50= 0.010 p95= 0.020 p99= 0.030
...

CSV ์ €์žฅ ๋ฐ ์ฐจํŠธ ์ƒ์„ฑ(์„ ํƒ)

# CSV์— ๋ˆ„์  ์ €์žฅ
swift run -c release Benchmarks -- --count 100000 --debounce 100 --csv bench.csv

# ๋น ๋ฅธ ํ™•์ธ(์ฒซ ์กฐํ•ฉ๋งŒ)
swift run -c release Benchmarks -- --quick --csv bench.csv

# ํ…์ŠคํŠธ ์š”์•ฝ + PNG ์ฐจํŠธ(์„ ํƒ, matplotlib ํ•„์š”)
python3 Scripts/plot_bench.py --csv bench.csv --out bench_plot

matplotlib์ด ์—†์œผ๋ฉด ํ…์ŠคํŠธ ์š”์•ฝ๋งŒ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜: pip install matplotlib

๐Ÿ“– ๋ฌธ์„œ ๋ฐ ํŠœํ† ๋ฆฌ์–ผ

๐Ÿ“š ๊ณต์‹ ๋ฌธ์„œ

โšก ํ•ซํŒจ์Šค ์ •์ ํ™” ํ™œ์„ฑํ™” (USE_STATIC_FACTORY)

  • ์˜๋ฏธ: ๋ฐ˜๋ณตยทํ”„๋ ˆ์ž„ ๋ฃจํ”„ ๋“ฑ ํ•ซํŒจ์Šค์—์„œ ๋Ÿฐํƒ€์ž„ ํ•ด์„์„ ์—†์•  ์ •์  ์ƒ์„ฑ/์บ์‹œ๋กœ ๋Œ€์ฒดํ•ด ๋น„์šฉ์„ 0์— ์ˆ˜๋ ดํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ ์œ„์น˜: ์ฝ”๋“œ์— #if USE_STATIC_FACTORY ๋ถ„๊ธฐ(์ด๋ฏธ ํ…œํ”Œ๋ฆฟ ํฌํ•จ) โ†’ ๋นŒ๋“œ ํ”Œ๋ž˜๊ทธ๋กœ on/off
  • ํ™œ์„ฑํ™” ๋ฐฉ๋ฒ•
    • Xcode: Target โ†’ Build Settings โ†’ Other Swift Flags(Release ๋˜๋Š” ์ „์šฉ ์Šคํ‚ด)์— -DUSE_STATIC_FACTORY ์ถ”๊ฐ€
    • SPM CLI: swift build -c release -Xswiftc -DUSE_STATIC_FACTORY
      • ํ…Œ์ŠคํŠธ: swift test -c release -Xswiftc -DUSE_STATIC_FACTORY

๐Ÿ“ ์„ฑ๋Šฅ ์ธก์ • ๊ฐ€์ด๋“œ

  • ๋ฐ˜๋“œ์‹œ Release + WMO(Wholeโ€‘Module Optimization)์—์„œ ์ธก์ •ํ•˜์„ธ์š”.
    • Xcode: Release ์Šคํ‚ด์œผ๋กœ ์‹คํ–‰(Release๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ WMO ์ ์šฉ)
    • SPM: swift build -c release, swift test -c release
  • ๋…ธ์ด์ฆˆ ์ตœ์†Œํ™” ํŒ
    • ๋กœ๊ทธ ๋ ˆ๋ฒจ ๋‚ฎ์ถ”๊ธฐ: UnifiedDI.setLogLevel(.errors) ๋˜๋Š” .off
    • ์ž๋™ ์ตœ์ ํ™” ON: UnifiedDI.configureOptimization(...), UnifiedDI.setAutoOptimization(true)
    • ๋ฐ˜๋ณต ๋ฃจํ”„๋Š” resolve ์บ์‹œ(๋ฃจํ”„ ๋ฐ– 1ํšŒ ํ™•๋ณด โ†’ ์•ˆ์—์„œ๋Š” ์žฌ์‚ฌ์šฉ)

๐ŸŽฏ ํŠœํ† ๋ฆฌ์–ผ

๐ŸŽฏ ์ฃผ์š” ์ฐจ๋ณ„์ 

๐Ÿ† vs Uber Needle: ๋ชจ๋“  ์žฅ์  + ๋” ๋‚˜์€ ๊ฒฝํ—˜

ํŠน์ง• Needle WeaveDI ๊ฒฐ๊ณผ
์ปดํŒŒ์ผํƒ€์ž„ ์•ˆ์ „์„ฑ โœ… ์ฝ”๋“œ ์ƒ์„ฑ โœ… ๋งคํฌ๋กœ ๊ธฐ๋ฐ˜ ๋™๋“ฑ
๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ โœ… ์ œ๋กœ ์ฝ”์ŠคํŠธ โœ… ์ œ๋กœ ์ฝ”์ŠคํŠธ + Actor ์ตœ์ ํ™” WeaveDI ์šฐ์Šน
Swift 6 ์ง€์› โš ๏ธ ์ œํ•œ์  โœ… ์™„๋ฒฝ ๋„ค์ดํ‹ฐ๋ธŒ WeaveDI ์šฐ์Šน
์ฝ”๋“œ ์ƒ์„ฑ ํ•„์š” โŒ ํ•„์ˆ˜ โœ… ์„ ํƒ์  WeaveDI ์šฐ์Šน
ํ•™์Šต ๊ณก์„  โŒ ๊ฐ€ํŒŒ๋ฆ„ โœ… ์ ์ง„์  WeaveDI ์šฐ์Šน
๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ โŒ All-or-nothing โœ… ์ ์ง„์  WeaveDI ์šฐ์Šน
// Needle ์ˆ˜์ค€ ์„ฑ๋Šฅ + ๋” ์‰ฌ์šด ์‚ฌ์šฉ๋ฒ•
UnifiedDI.enableStaticOptimization()  // Needle๊ณผ ๋™์ผํ•œ ์ œ๋กœ ์ฝ”์ŠคํŠธ

@DependencyGraph([  // ์ปดํŒŒ์ผํƒ€์ž„ ๊ฒ€์ฆ
    UserService.self: [NetworkService.self, Logger.self]
])
extension WeaveDI {}

print(UnifiedDI.migrateFromNeedle())  // Needle โ†’ WeaveDI ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฐ€์ด๋“œ

1. ์™„์ „ ์ž๋™ํ™”๋œ ์ตœ์ ํ™”

  • ๋ณ„๋„ ์„ค์ • ์—†์ด Actor hop ๊ฐ์ง€, ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฒ€์ฆ, ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ์ž๋™ ์‹คํ–‰
  • ์‹ค์‹œ๊ฐ„ ๋ถ„์„์œผ๋กœ 30์ดˆ๋งˆ๋‹ค ์ตœ์ ํ™” ์ˆ˜ํ–‰ (Needle์— ์—†๋Š” ๊ธฐ๋Šฅ)
  • ๊ฐœ๋ฐœ์ž ์นœํ™”์  ์ œ์•ˆ์œผ๋กœ ์„ฑ๋Šฅ ๊ฐœ์„ ์  ์ž๋™ ์•ˆ๋‚ด

2. Swift Concurrency ๋„ค์ดํ‹ฐ๋ธŒ (Needle ๋Œ€๋น„ ์šฐ์œ„)

  • Actor ์•ˆ์ „์„ฑ ์ž๋™ ๊ฒ€์ฆ ๋ฐ ์ตœ์ ํ™” ์ œ์•ˆ
  • async/await ์™„๋ฒฝ ์ง€์› (Needle์€ ์ œํ•œ์ )
  • Sendable ํ”„๋กœํ† ์ฝœ ์ค€์ˆ˜ ๊ฒ€์ฆ

3. ๋‹จ์ˆœํ•˜๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•œ API

  • 2๊ฐœ Property Wrapper๋งŒ์œผ๋กœ ๋ชจ๋“  ์ฃผ์ž… ํŒจํ„ด ์ปค๋ฒ„ (@Injected, @Factory)
    • ์ฐธ๊ณ : @Inject์™€ @SafeInject๋Š” v3.2.0๋ถ€ํ„ฐ Deprecated. @Injected ์‚ฌ์šฉ ๊ถŒ์žฅ
  • ํƒ€์ž… ์•ˆ์ „ํ•œ KeyPath ๊ธฐ๋ฐ˜ ๋“ฑ๋ก
  • ์ง๊ด€์ ์ธ ์กฐ๊ฑด๋ถ€ ๋“ฑ๋ก

๐Ÿ“„ ๋ผ์ด์„ ์Šค

MIT License. ์ž์„ธํ•œ ๋‚ด์šฉ์€ LICENSE ํŒŒ์ผ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๐Ÿ‘จโ€๐Ÿ’ป ๊ฐœ๋ฐœ์ž

์„œ์›์ง€ (Roy, Wonji Suh)

๐Ÿค ๊ธฐ์—ฌํ•˜๊ธฐ

WeaveDI๋ฅผ ๋” ์ข‹๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”!

๊ธฐ์—ฌ ๋ฐฉ๋ฒ•

  1. ์ด์Šˆ ์ œ๊ธฐ: GitHub Issues์—์„œ ๋ฒ„๊ทธ ๋ฆฌํฌํŠธ๋‚˜ ๊ธฐ๋Šฅ ์š”์ฒญ
  2. Pull Request: ๊ฐœ์„ ์‚ฌํ•ญ์ด๋‚˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์„œ ๊ธฐ์—ฌ
  3. ๋ฌธ์„œ ๊ฐœ์„ : README๋‚˜ ๋ฌธ์„œ์˜ ์˜คํƒ€, ๊ฐœ์„ ์‚ฌํ•ญ ์ œ์•ˆ

๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •

git clone https://github.com/Roy-wonji/WeaveDI.git
cd WeaveDI
swift build
swift test

WeaveDI์™€ ํ•จ๊ป˜ ๋” ๋‚˜์€ Swift ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ๋งŒ๋“ค์–ด๊ฐ€์„ธ์š”! ๐Ÿš€

โญ ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด Star๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”! โญ