### **Zenject와 VContainer 비교** 문서는 Zenject를 훌륭한 라이브러리로 인정하면서도, VContainer가 특정 측면에서 이점을 가진다고 주장합니다. **VContainer의 장점:** - **뛰어난 성능 (Good performance):** - `Resolve` 속도가 Zenject보다 5-10배 빠릅니다. (1.1 About _ What is VContainer.pdf 참조) - `Resolve` 시점에 인스턴스가 스폰되지 않는 한, GC(Garbage Collection) 할당이 0입니다. (1.1 About _ What is VContainer.pdf 참조) - 리플렉션 및 어설션(assertion)의 대부분이 컨테이너 빌드 단계로 격리되어 런타임 성능에 미치는 영향이 적습니다. - **쉬운 구현 이해 (Easy to read implementation):** - 내부 타입이 적고, `callvirt` 호출이 적어 코드 베이스가 간결합니다. (1.1 About _ What is VContainer.pdf 참조) - **올바른 DI 방식 지원 (Assisting correct DI way):** - 간단하고 투명한 API를 제공하며, 신중하게 기능을 선택하여 DI 선언이 지나치게 복잡해지는 것을 방지합니다. (1.1 About _ What is VContainer.pdf 참조) - VContainer는 데이터 중심 객체를 컨테이너에 등록하거나 View 컴포넌트에 적극적으로 주입하는 것을 권장하지 않습니다. 이는 DI 선언의 복잡성을 낮추는 데 기여합니다. (1.2 About _ What is DI.pdf 참조) - **MonoBehaviour와 DI의 역할 분리 강조:** Zenject는 동적이거나 데이터 중심적인 객체에 주입하는 데 자주 사용되지만, 이는 복잡성을 야기할 수 있습니다. VContainer는 `MonoBehaviour` 자체에 직접 주입하기보다 `MonoBehaviour`를 감싸는(owning) `GameObject`에 주입하는 것을 권장합니다. - Zenject는 씬 시작 시 모든 `GameObject`를 리플렉션을 통해 탐색하는데, 이 작업은 비용이 많이 듭니다. VContainer는 이러한 작업을 수행하지 않아 성능 이점을 가집니다. - **코드 크기 (Code size):** - VContainer의 DLL 크기와 IL2CPP C/C++ 빌드 시의 코드 크기가 Zenject보다 훨씬 작다는 그래프가 제시되어 있습니다. (VContainer는 약 2000줄, Zenject는 약 6000줄 이상) 이는 빌드 시간 및 최종 애플리케이션 크기에 긍정적인 영향을 미칠 수 있습니다. ### **API 차이점** 문서는 Zenject와 VContainer의 몇 가지 일반적인 DI 등록 및 사용 패턴에 대한 API 비교 테이블을 제공합니다. |Zenject API|VContainer API|설명| |:--|:--|:--| |`Container.Bind<Service>().AsTransient()`|`builder.Register<Service>(Lifetime.Transient)`|Transient 라이프타임 등록: 요청 시마다 새 인스턴스 생성.| |`Container.Bind<Service>().AsCached()`|`builder.Register<Service>(Lifetime.Scoped)`|Scoped 라이프타임 등록: 해당 `LifetimeScope` 내에서 단일 인스턴스 유지.| |`Container.Bind<Service>().AsSingle()`|`builder.Register<Service>(Lifetime.Singleton)`|Singleton 라이프타임 등록: 모든 컨테이너에 걸쳐 단일 인스턴스 유지.| |`Container.Bind<IService>().To<Service>().AsCached()`|`builder.Register<IService, Service>(Lifetime.Scoped)`|인터페이스-구현체 매핑 (Scoped).| |`Container.Bind(typeof(IInitializable), typeof(IDisposable)).To<Service>().AsCached()`|`builder.Register<Service>(Lifetime.Scoped).As<IInitializable, IDisposable>()`|여러 인터페이스로 등록.| |`Container.BindInstance(instance)`|`builder.RegisterInstance(instance)`|이미 존재하는 인스턴스 등록.| |`Container.Bind<Service>().FromInstance(instance)`|(위와 동일)|| |`Container.Resolve<Service>()`|`container.Resolve<Service>()`|서비스 해결 (인스턴스 가져오기).| |`Container.Inject(obj)`|`container.Inject(obj)`|기존 객체에 의존성 주입.| |`Container.Instantiate<Foo>()`|`container.Instantiate<Foo>()`|일반 C# 객체 인스턴스화 및 주입.| |`Container.InstantiatePrefab(prefab)`|`container.Instantiate(prefab)`|프리팹으로부터 `GameObject` 인스턴스화 및 `MonoBehaviour` 주입.| |`Container.BindFactory<Enemy, Enemy.Factory>().FromComponentInNewPrefab(enemyPrefab)`|`builder.RegisterFactory<Enemy>(container => () => { ... })`|팩토리 등록: Zenject는 `PlaceholderFactory`를 사용하지만, VContainer는 `Func<T>` 델리게이트와 `Instantiate`를 조합하여 팩토리 기능을 제공합니다. 예시에서는 플레이어를 주입받아 Enemy를 생성하는 팩토리를 보여줍니다.| |`Signal`|`Not supported`|VContainer는 자체적인 메시징/시그널 시스템을 내장하고 있지 않습니다. 대신 `VitalRouter`, `Cysharp/MessagePipe` 등 외부 라이브러리를 사용할 것을 권장합니다. 이는 프로젝트 스타일에 따라 유연하게 선택할 수 있도록 합니다.| |`Memory Pool`|`Not supported`|VContainer는 메모리 풀링을 내장하고 있지 않습니다. 대신 팩토리 등을 통해 프로젝트 목적에 맞는 풀링 구현을 직접 주입하여 사용할 것을 권장합니다.| |`Container.Bind<Foo>().FromComponentInNewPrefabResource("Some/Path/Foo")`|`We should load Resources using LoadAsync family. You can use RegisterInstance() etc after loading the Resource.`|VContainer는 Unity의 Resources.Load API 대신 `LoadAsync` 계열의 비동기 로딩을 사용한 후, 로드된 리소스를 `RegisterInstance()` 등으로 등록하는 방식을 권장합니다. 이는 비동기 로딩의 이점을 활용하기 위함입니다.| |`Container.Bind<Foo>().WithId("foo").AsCached()`|`Duplicate type Resolve is not recommended. You can instead use type-specific Register builder`|VContainer는 동일한 타입에 대해 ID를 부여하여 여러 인스턴스를 관리하는 것을 권장하지 않습니다. 대신 타입별로 고유한 등록 빌더를 사용하거나, 다른 타입을 정의하여 명확하게 구분하는 방식을 권장합니다. (예: `GameSettings` 클래스 안에 `CameraSettings`, `ActorSettings`를 각각 등록하는 방식 - 4.5 Register ScriptableObject.pdf 참조)| ### 요약 VContainer가 Zenject에 비해 성능, 코드 간결성, 올바른 DI 원칙 준수 측면에서 강점을 가지고 있음을 강조합니다. 특히 `MonoBehaviour`와의 DI 상호작용 방식에서 차이를 보이며, VContainer는 `MonoBehaviour`를 뷰 컴포넌트로서의 역할에 집중시키고 도메인 로직과 분리하는 것을 지향합니다. 또한, 두 라이브러리의 주요 API들을 비교하여 개발자가 VContainer로 전환하거나 선택할 때 참고할 수 있도록 유용한 정보를 제공합니다. --- 이전 : [[8.4 Pre IL Code Generation (Deprecated)]]