### **VContainer + UniTask** - **UniTask란?** - Unity에 빠르고 강력한 `async/await` 지원을 제공하는 라이브러리입니다. - .NET 표준의 `Task`-기반 비동기 패턴과 거의 동일한 API를 제공하지만, Unity의 `PlayerLoop`에 최적화되어 있습니다. - `UnityWebRequest`와 같은 Unity 내장 비동기 작업에 대한 `async/await` 지원도 추가합니다. - **통합 활성화:** - 프로젝트에 `com.cysharp.unitask` 패키지가 설치되어 있으면, `VCONTAINER_UNITASK_INTEGRATION` 컴파일러 심볼이 자동으로 활성화되어 다음과 같은 VContainer 기능이 자동으로 활성화됩니다. **1. `IAsyncStartable`** - **설명:** `VCONTAINER_UNITASK_INTEGRATION`이 활성화되면, `IAsyncStartable` 인터페이스는 `UniTask`를 반환 값으로 사용합니다. - **코드 예시:** ```csharp public class FooController : IAsyncStartable { public async UniTask StartAsync (CancellationToken cancellation) { await LoadSomethingAsync(cancellation); // 다른 비동기 작업 수행 } } // LifetimeScope에서 등록 builder.RegisterEntryPoint<FooController>(); - **작동 방식:** `IAsyncStartable`를 구현하는 클래스가 등록되면, `StartAsync` 메서드가 `IStartable`와 유사하게 자동으로 실행됩니다. **2. `StartAsync()` 타이밍** - **설명:** 현재 VContainer가 제공하는 유일한 비동기 인터페이스는 `IAsyncStartable`입니다. 만약 다른 `PlayerLoop` 단계에서 비동기 코드를 실행해야 한다면, UniTask 자체의 `PlayerLoopTiming`을 사용하여 메서드 내에서 실행 타이밍을 제어할 수 있습니다. - **코드 예시:** 코드 스니펫 ``` await UniTask.Yield(PlayerLoopTiming.FixedUpdate); ``` - **주의사항:** - 모든 `StartAsync` 호출은 (개별 구현 내에서 별도로 지정되지 않는 한) 메인 스레드에서 동시에 실행되도록 예약됩니다. - 향후 `PlayerLoop` 단계는 이 비동기 작업이 완료되기를 기다리지 않습니다. 즉, `StartAsync` 내의 `await`는 다음 `PlayerLoop` 단계(예: `Update`)를 지연시키지 않습니다. **3. 예외 처리 (Exception Handling)** - **장점:** `IEnumerator` 기반의 코루틴과 달리, `async` 메서드는 `try/catch/finally` 문을 완벽하게 지원합니다. - **UniTask 기본 예외 처리:** `UniTaskScheduler.UnobservedTaskException` 이벤트를 사용할 수 있습니다. - **VContainer 특정 예외 처리:** 각 `LifetimeScope`별로 별도의 오류 핸들러를 등록하려면, 이전 5.1 문서에서 설명된 `builder.RegisterEntryPointExceptionHandler(ex => { ... });`를 사용할 수 있습니다. **4. `CancellationToken` (취소 토큰)** - **설명:** `StartAsync` 메서드에는 `CancellationToken`이 제공됩니다. 이 토큰은 `IAsyncStartable`를 등록한 `LifetimeScope`가 파괴될 때 취소됩니다. 이를 통해 `LifetimeScope`의 수명과 연동된 비동기 작업을 안전하게 취소할 수 있습니다. **5. 비동기 에셋 로딩 (Async Asset Loading)** - **활용:** UniTask는 에셋과 씬을 비동기적으로 로드하는 기능을 제공합니다. 이 기능은 VContainer의 `LifetimeScope.Enqueue*` 메서드와 함께 사용할 때 매우 유용합니다. - **코드 예시:** C# ``` var extraAsset = await Addressables.LoadAssetAsync<ExtraAsset>(key); using (LifetimeScope.EnqueueParent(parentScope)) using (LifetimeScope.Enqueue(builder => builder.RegisterInstance(extraAsset))) { await SceneManager.LoadSceneAsync("AdditiveScene"); } ``` - 이 예시는 `Addressables`를 사용하여 에셋을 비동기적으로 로드한 다음, 로드된 에셋을 현재 스코프에 등록하고, 그와 동시에 추가적인 씬을 비동기적으로 로드하는 방법을 보여줍니다. `Enqueue` 및 `EnqueueParent`는 새로운 `LifetimeScope`에 대한 추가적인 등록(Configuration)을 미리 예약할 때 사용됩니다. ### 요약 VContainer가 UniTask와 긴밀하게 통합되어 Unity에서 비동기 DI를 효과적으로 구현할 수 있음을 강조합니다. 특히 `IAsyncStartable`를 통한 비동기 진입점, UniTask의 `PlayerLoopTiming`을 사용한 유연한 타이밍 제어, 견고한 예외 처리, 그리고 `CancellationToken`을 통한 안전한 비동기 작업 취소, 그리고 비동기 에셋 로딩과의 시너지를 설명합니다. 이 통합은 Unity 프로젝트에서 복잡한 비동기 로직과 의존성 관리를 훨씬 더 효율적이고 안정적으로 만들어줍니다. --- 이전 : [[5.1 Plain CSharp Entry point]] | 다음 : [[5.3 UniRx]]