# 요약 - 비동기 프로그래밍을 활용하면 시간이 오래 걸리는 작업(ex 네트워크를 통한 데이터 통신, 무거운 씬 로딩)을 메인 스레드에서 블로킹하지 않고 작업 할 수 있게 해준다. - Unity에서는 AsyncOperation을 활용하여 씬 로딩, 에셋로딩을 비동기로 수행할 수 있다. # 동기 VS 비동기 #### **동기 프로그래밍 (Synchronous Programming)** 동기 프로그래밍은 하나의 작업이 완료될 때까지 프로그램이 기다리는 방식입니다. 즉, 코드가 순차적으로 실행되며, 이전 작업이 완료되어야 다음 작업이 시작됩니다. 이 방식은 직관적이지만, 특정 작업이 오래 걸릴 경우(예: 파일 로딩, 네트워크 요청) 프로그램의 다른 부분이 일시적으로 중단될 수 있습니다. ##### **동기 프로그래밍의 특징** - **순차 실행**: 각 작업은 순서대로 실행되며, 이전 작업이 완료되지 않으면 다음 작업이 시작되지 않습니다. - **간단함**: 직관적이고 코드를 따라가기 쉽지만, 긴 작업이 있을 때 메인 스레드에 병목이 생길 수 있습니다. - **블로킹**: 실행 중인 작업이 완료될 때까지 다른 작업이 진행되지 않기 때문에, 프로그램이 잠시 멈춘 것처럼 보일 수 있습니다. ```csharp private void Start() { LoadDataSynchronously(); // LoadDataSynchronously 작업이 끝난 후 시작 for(int i = 0; i < 100; ++i) { Debug.Log(quot;Current Count : {i}"); } } public void LoadDataSynchronously() { // 파일을 동기적으로 로드 string path = Path.Combine(CONST_PATH, "data.txt"); string data = System.IO.File.ReadAllText(path); Debug.Log(data); // 파일 로딩이 끝난 후에만 아래 코드 실행 Debug.Log("파일 로드 완료!!"); } ``` ![[Pasted image 20240909230457.png]] #### **비동기 프로그래밍 (Asynchronous Programming)** 비동기 프로그래밍은 작업이 완료될 때까지 기다리지 않고, 다른 작업을 동시에 실행할 수 있는 방식입니다. 비동기 작업은 메인 스레드를 차단하지 않기 때문에, 긴 작업이 있을 때도 프로그램의 다른 부분이 정상적으로 동작할 수 있습니다. 게임 개발에서는 파일 로딩, 네트워크 요청, 씬 전환 등에서 흔히 사용됩니다. ##### **비동기 프로그래밍의 특징** - **병렬 실행 가능**: 비동기 작업은 별도의 스레드에서 실행되므로, 동시에 여러 작업을 처리할 수 있습니다. - **논 블로킹**: 작업이 진행되는 동안 다른 작업이 계속 실행됩니다. - **복잡성**: 동기 프로그래밍에 비해 흐름을 추적하는 것이 복잡할 수 있으며, 적절한 오류 처리와 타이밍 관리가 필요합니다. ```csharp private void Start() { LoadDataAsynchronously(); // LoadDataAsynchronously 작업이 끝나는 걸 기다리지 않고 시작 for(int i = 0; i < 100; ++i) { Debug.Log(quot;Current Count : {i}"); } } public async void LoadDataAsynchronously() { // 파일을 비동기적으로 로드 string path = Path.Combine(CONST_PATH, "data.txt"); Task<string> loadTask = System.IO.File.ReadAllTextAsync(path); string data = await loadTask; Debug.Log(data); Debug.Log("파일 로드 완료!!"); } ``` 이 경우, 파일이 로딩되는 동안 메인 스레드는 계속해서 다른 작업을 진행할 수 있으며, 파일 로딩이 완료된 후 결과가 처리됩니다. ![[Pasted image 20240909230642.png]] # AsyncOperation을 사용해보자! #### AsyncOperation `AsyncOperation`은 Unity에서 제공하는 비동기 작업을 추적하는 클래스입니다. 이 클래스는 주로 씬 로딩(`SceneManager.LoadSceneAsync`), 에셋 번들 로드, 리소스 로드(`Resources.LoadAsync`) 등의 작업에 사용됩니다. #### **`AsyncOperation`의 주요 프로퍼티** - `isDone`: 작업이 완료되었는지 여부를 나타냅니다. `true`이면 작업이 완료된 상태입니다. - `progress`: 0부터 1까지의 값을 반환하며, 현재 작업의 진행률을 나타냅니다. `allowSceneActivation`값이 false로 설정되면 `progress`값은 0.9에서 중지됩니다. - `allowSceneActivation`: 씬 로딩 작업에서 이 값을 `false`로 설정하면, 씬 로딩이 완료되었더라도 씬을 활성화하지 않습니다. 이 기능을 통해 특정 조건이 만족될 때까지 씬 전환을 지연시킬 수 있습니다. ```csharp private void Start() { StartCoroutine(LoadSceneAsynchronously()); } private IEnumerator LoadSceneAsynchronously() { AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Lobby"); if (asyncOperation == null) { Logger.LogError("Lobby async loading error."); yield break; } asyncOperation.allowSceneActivation = false; while (asyncOperation.isDone == false) // 로딩이 진행 중일 때 { Debug.Log(quot;{asyncOperation.progress:P0}"); // 씬 로딩이 완료되었다면 로비로 전환하고 코루틴 종료 if (asyncOperation.progress >= 0.9f) { Debug.Log(quot;{asyncOperation.progress:P0}"); asyncOperation.allowSceneActivation = true; Debug.Log("Scene Loading Complete!"); yield break; } yield return null; } } ``` ![[Pasted image 20240909231713.png]] # 참고자료 - https://learn.microsoft.com/ko-kr/dotnet/api/system.io.file.readalltextasync?view=net-8.0 - https://docs.unity3d.com/ScriptReference/AsyncOperation.html - https://www.inflearn.com/course/%EC%9C%A0%EB%8B%88%ED%8B%B0-%EC%8B%9C%EC%8A%A4%ED%85%9C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-1