헷갈리는 키워드를 정리하기 위해 포스팅하게됐다.

1. async / await

- 비동기 프로그래밍 문법

- 실행 흐름을 잠깐 끊었다가, 끝나면 다시 이어서 실행하는 문법

using System.Threading.Tasks;
using UnityEngine;

public class LoginExample : MonoBehaviour
{
    public async Task<string> LoginAsync(string username, string password)
    {
        Debug.Log("로그인 시작");

        // 1초 대기 (메인 스레드를 블로킹하지 않음)
        await Task.Delay(1000);

        Debug.Log("1초 뒤 실행");

        return "Token";
    }
}

- Task.Delay동안 메인스레드는 멈추지 않는다.

- await는 잠시 대기 일뿐이다.

- await가 끝나면 다시 원래 스레드로 돌아간다. 

즉, 이 함수에서는 메인 스레드 외의 다른 워커 스레드를 사용하지 않고 있다.

 

C# Task는 Unity에서 쓰기에는 적합하지 않다.

- GC/할당부담

- Unity 오브젝트 라이프사이클과 매칭

- 유니티 프레임루프와 연결이 느슨함

그래서 선택지는 UniTask다

 

2. UniTask

UniTask는 유니티의 프레임루프 기준으로 동작하도록 만들어진

Unity친화적인 비동기 라이브러리다.

public async UniTask LoginAsync()
{
    await UniTask.Delay(1000);

    // 여기부터 다시 Unity 메인 스레드
    Debug.Log("1초 뒤 실행");
}

가장 큰 특징중에 하나는 await이후에 다시 유니티 메인스레드로 복귀 한다는 점이다.

(await이후 unity api 접근 가능하다는 말)

 

3. 언제 멀티스레드가 되나?

비동기를 사용하면 멀티스레드가 된다고 생각했는데, 아니었다.

명시적으로 워커 스레드를 사용했을때만 멀티스레드가 된다. 

await UniTask.Delay(1000);
//메인스레드
await UniTask.RunOnThreadPool(() =>
{
     //워커스레드
    HeavyWork();
});

//메인 스레드 복귀

 

4. 비동기와 멀티스레드 비교

비동기

- 메인 스레드를 막지 않고 대기 방식이라는것이 핵심이다

- 스레드는 하나 일 수 있다

- 주로 네트워크나 파일I/O, 타이머

=> 기다리는 방식

 

멀티스레드

- 병렬 실행이 핵심

- 스레드가 여러개

- 실행로직을 분리해 무거운 연산에 적합하다.

=> 실행을 나누는 방식

 

5. 코루틴과 비교

코루틴은 비동기가 아니다. 단지 메인스레드에서 비동기적 흐름을 흉내낸것이 맞다. 유니티에서는

유니티 메인스레드에서 실행흐름을 쪼개서 비동기처럼 보이게 만드는 구조이다.

 

 

6. 멀티스레드는 만능인가?

복잡한 연산을 멀티스레드로 구현하면, 플레이에 프리징을 줄일 수 있다.

하지만 만능은 아님

- 스레드 관리비용

- 컨텍스트 스위칭 오버헤드

- 모바일 기기에서는 발열

- CPU 스레드 수 제한등

이런것들을 잘 고려하지 못한다면 오히려 더 나빠질 수 있다.

 

+ Recent posts