[Unity] Coroutine vs async/await

spixychz·2026년 6월 8일

Unity

목록 보기
15/15

Coroutine

: Unity 엔진이 제공하는 실행을 일시 중단하고, 이후 특정 시점에 이어서 실행할 수 있는 함수

  • C#의 반복자 (IEnumerator)를 유니티 엔진이 활용하여 만든 협력적 멀티태스킹 (Cooperative Multitasking) 방식
    • C# 컴파일러가 IEnumerator 상태 머신으로 변환
      • 이 상태머신은 클래스라 힙 메모리 할당
    • yield return 을 만나면 함수가 완전히 종료되는 것이 아닌 그 지점에서 실행을 일시 정지하고 제어권을 자신이 호출한 쪽으로 넘긴다
    • 유니티 PlayerLoop가 MoveNext() 를 호출하면, 멈췄던 바로 그 다음 줄부터 코드를 다시 이어서 실행
  • 비동기 처럼 보이지만 멀티 스레드 환경이 아닌, 메인 스레드에서 실행
    • 여러 코루틴 코드가 유니티 엔진의 스케줄링하에 프레임 단위로 쪼개져 실행
  • MonoBehaviour 객체에 종속
    • MonoBehaviour 컴포넌트가 비활성화 → 코루틴 중단 없음
    • GameObject가 비활성화되거나 파괴 → 코루틴 중단
  • try-catch 블록 내부에서 yield return 사용 불가
  • 직접적인 반환 값 사용 불가
  • 종료
    • StopCoroutine
    • yield break : 종료
  • 사용처
    • 단순한 시각적 효과, 프레임 단위의 애니메이션 제어 등 유니티 라이프사이클과 결합된 프론트엔드 연산을 할 때
  • yield return 종류
    • null : 다음 프레임의 Update 이후 재개
    • new WaitForSeconds(1f) : 1초 후 다음 갱신 시점에 재개
    • new WaitForFixedUpdate() : 다음 프레임의 FixedUpdate 이후 재개
    • new WaitForEndOfFrame() : 현재 프레임의 렌더링 이후 재개
    • new WaitUntil(() ⇒ isComplete) : 조건이 만족되면 재개
    • new WaitWhile(() => isLoading) : 조건이 만족되는 동안 중단

async/await

: 비동기 작업이 완료될 때까지 기다렸다가 이후 코드를 이어서 실행하는 C# 네이티브 기능

  • async : 이 메소드 안에서 await를 사용할 수 있도록 만드는 키워드
    • C# 컴파일러가 코드를 상태 머신으로 변환 ( IAsyncStateMachine )
  • await : Task가 완료될 때까지 현재 메소드 실행을 일시 중단하는 키워드
  • try-catch 사용 가능
  • CancellationToken 으로 취소
  • 사용처
    • 네트워크 통신, 파일 I/O, 무거운 데이터 로딩 등 시스템 외부와 통신하거나 순수한 비즈니스 로직을 처리할 때

Task

: 비동기 작업의 상태와 완료 여부를 표현하는 객체

  • 생성됨 or 실행중 or 완료됨 or 실패함 or 취소됨
  • Task ≠ Thread
  • 주요 멤버
    • Task.CompletedTask
      • 이미 완료된 Task
    • Task.FromResult<T>()
      • 즉시 결과 값 반환
    • Task.Run()
      • CPU를 많이 사용하는 작업을 Worker Thread에서 실행
      • Thread를 생성하는 것이 아닌 ThreadPool에 작업 등록
      • Main Thread → ThreadPool Worker Thread → Main Thread 복귀
    • Task.WhenAll()
      • 모든 Task가 완료될 때까지 대기
      • 독립적인 작업을 동시에 진행할 때 사용
    • Task.WhenAny()
      • 가장 먼저 완료된 Task 반환
  • 값 반환
    • Task<T> 를 통해 반환 값 사용 가능
    • async Task는 명시적인 return 문이 없어도 컴파일러가 알아서 완료된 Task 반환
    • async 키워드가 없는 경우 직접 반환 필수
  • 주의 사항
    • async void 지양 ⇒ async Task 로 사용
      • 호출 측에서 await 사용 불가능하기 때문
    • 게임 오브젝트가 파괴되어도 자동 취소되지 않는다
      • CancellationToken 을 통해 명시적으로 취소 가능
    • Worker Thread에서 Unity API 접근 불가
    • async/await는 상태 머신과 Task 객체를 생성하며, 실행 과정에서 추가적인 메모리 할당이 발생할 수 있다
      • C# 컴파일러가 만드는 상태머신은 구조체
      • 서드파티 라이브러리 UniTask 를 사용하여 GC 할당 감소 가능

코루틴 vs Async

코루틴Async
정의Unity 엔진이 제공하는 실행 흐름 제어 기능C#이 제공하는 비동기 프로그래밍 기능
멀티 스레드XTask.Run
반환 값직접 반환 불가Task
예외 처리제한적try-catch 가능
생명 주기MonoBehaviour에 종속독립적
취소StopCoroutineCancellationToken
사용처Unity의 프레임 흐름이나 게임 연출과 밀접한 작업외부 작업의 완료를 기다리는 작업

Coroutine을 선호하는 경우

  • Ex
    • 프레임 내부에서도 제어가 필요할 때
    • 연출 및 애니메이션
    • 시간 흐름을 표현하는 로직
    • 게임 오브젝트 생명주기에 종속된 로직
  • Why
    • MonoBehaviour
    • Transform, UI, 물리 연산 등 엔진 API는 메인스레드에서만 접근 가능

Async를 선호하는 경우

  • Ex
    • 네트워크 통신
    • I/O
    • 무거운 CPU 연산
      • 메인 스레드에서 처리하면 프레임 드랍이 생기는 로직
  • Why
    • 외부 라이브러리와 연동
      • C# 생태계 대부분이 Task 기반
    • 반환값이 필요할 때
      • Task
    • 예외 처리
      • try-catch의 한계
    • 여러 작업 동시 처리
      • Task.WhenAll
profile
UNITY로 게임 개발하는 사람

0개의 댓글