-
Unity | 코루틴(Coroutine)과 Async/Await(Task)다시한번 개발자도전! 2026. 1. 21. 16:07
< 유니티 코루틴(Coroutine) >
1. 코루틴이란?
실행을 중간에 멈췄다가, 나중에 다시 시작할 수 있는 아주 특별한 함수.
- 비유: 영화를 보다가 일시정지하고 화장실에 갔다가, 다시 돌아와서 멈춘 부분부터 이어서 보는 것과 같음.
2. 비동기적 처리
특정 작업을 "3초 동안" 실행하고 싶을 때 Update() 안에 짜면 매 프레임마다 복잡한 타이머 로직이 필요.
코루틴을 쓰면 이걸 아주 직관적으로 짤 수 있음.
- 예시: 적을 1초 간격으로 스폰하기
IEnumerator SpawnEnemyRoutine() { while (true) { //적 생성 Instantiate(enemyPrefab, spawnPoint.position, Quaternion.identity); // 딱 1초 기다리고 다음 코드 실행함 yield return new WaitForSeconds(1.0f); } } // 실행은 Start에서 한 번만 void Start() { StartCoroutine(SpawnEnemyRoutine()); }
3. 내부 동작 원리
코루틴은 유니티의 메인 스레드에서 돌아감.(멀티스레드x)
- 유니티 엔진은 매 프레임마다 돌아가는 코루틴들을 체크함.
- yield return을 만나면 "다음 프레임(혹은 지정된 시간)에 여기서부터 다시 해!"라고 주소만 저장해두고 바로 제어권을 엔진에 돌려줌.
- 예시 : 메인 일꾼(단일 스레드)이 일을 하다가 yield return을 만나면, 일을 잠시 내려놓고 "다음 프레임에 다시 올게!" 하고 다른 일(화면 그리기 등)을 하러 가는 방식임.
⬇️ 스레드(Thread)란?⬇️
더보기1.스레드(Thread)란?
- 스레드는 프로세스(프로그램) 내에서 실행되는 하나의 작업 흐름. 쉽게 말해 일꾼 한 명이라고 생각하면 됨.
2. 단일 스레드 (Single Thread)
일꾼이 딱 한 명인 시스템임. 유니티의 메인 로직(Update, 코루틴 등)은 기본적으로 이 단일 스레드에서 돌아감.
- 특징: 한 번에 하나의 일만 할 수 있음.
- 장점: 일꾼이 한 명이라 데이터가 꼬일 일이 없음(동기화 문제 없음). 설계가 단순함.
- 단점: 한 작업이 너무 오래 걸리면 전체 프로그램이 멈춰버림(렉, 응답 없음).
- 비유: 편의점에 계산대와 직원이 딱 하나인 상황임. 앞 손님이 대량 결제를 하면 뒷사람은 마냥 기다려야 함.
3. 멀티 스레드 (Multi Thread)
일꾼이 여러 명인 시스템임. 요새 나오는 CPU들은 코어가 많아서 여러 일을 동시에 처리할 수 있음.
- 특징: 여러 작업을 동시에(병렬로) 처리함.
- 장점: 무거운 작업을 백그라운드 일꾼에게 맡기면 메인 일꾼은 계속 화면을 그려줄 수 있어 게임이 부드러움.
- 단점: 일꾼들끼리 같은 물건(데이터)을 동시에 건드리면 싸움이 남(Race Condition). 관리가 매우 까다로움.
- 비유: 대형 마트의 여러 계산대임. 한쪽이 막혀도 다른 줄은 계속 빠짐.
4. 차이점 비교
구분 단일 스레드 (Single Thread) 멀티 스레드 (Multi Thread) 작업 방식 순차적 (하나씩 처리) 병렬적 (동환에 여러 개 처리) 안정성 높음 (데이터 충돌 없음) 낮음 (데이터 동기화 필요) 성능 무거운 작업 시 멈춤 현상 발생 자원을 효율적으로 사용하여 빠름 비동기 구현 코루틴 등으로 흉내 냄 Task, Thread 등으로 실제 구현
4. 핵심 문법 정리
① yield return 종류(정지 지점)
문법 의미 yield return null; 다음 프레임까지 대기 yield return new WaitForSeconds(f); 입력한 초(f)만큼 대기 yield return new WaitForFixedUpdate(); 다음 FixedUpdate 타임까지 대기 yield break; 코루틴을 강제로 완전히 종료 ② 실행과 중지
// 실행 Coroutine myCo = StartCoroutine(MyRoutine()); // 중지 StopCoroutine(myCo); StopAllCoroutines(); // 이 스크립트의 모든 코루틴 중지💡코루틴 꿀팁💡
더보기캐싱 사용: yield return new WaitForSeconds(1f);를 반복문 안에서 계속 쓰면 가비지(Garbage)가 쌓임. 멤버 변수에 미리 담아서 재사용.
비활성화 주의: gameObject.SetActive(false)가 되면 그 오브젝트에서 돌아가던 코루틴은 자동으로 중지됨. 다시 켠다고 해서 멈춘 지점부터 시작되지 않으니 주의해야 함. (단, 스크립트 컴포넌트인 .enabled = false는 영향을 주지 않음)
인자 전달: Invoke와 달리 매개변수를 자유롭게 넘길 수 있으니 적극 활용하길 봄.
< Async / Await >
C#에서 비동기 프로그래밍을 동기 코드(위에서 아래로 흐르는 코드)처럼 짤 수 있게 해주는 문법.
- Async (비동기): 이 메서드는 비동기로 동작할 것이라고 선언하는 키워드임.
- Await (기다림): 비동기 작업이 끝날 때까지 기다리라는 뜻임. 중요한 건 기다리는 동안 메인 스레드(게임 화면)를 멈추지 않고 제어권을 시스템에 양보함.
1. 동작 원리
코루틴이 유니티 엔진의 Update 루프에 의존한다면, Async/Await는 .NET의 Task(작업) 시스템을 기반으로 작동.
- 메서드를 실행하다가 await를 만남.
- 작업이 끝날 때까지 기다려야 한다는 걸 인식하고, 일단 호출했던 곳으로 제어권을 돌려줌 (게임은 계속 돌아감).
- 백그라운드에서 작업이 완료되면, await 바로 다음 줄부터 코드가 다시 실행됨.
2. 장점
- 결과값 반환: 코루틴은 값을 직접 못 돌려주지만, Task<T>를 쓰면 int, string 등 원하는 결과를 바로 받을 수 있음.
- 예외 처리: try-catch 문을 그대로 쓸 수 있어서 서버 통신 에러 등을 잡기가 훨씬 쉬움.
- 병렬 처리: 여러 작업을 한꺼번에 던져놓고 다 끝날 때까지 기다리는(Task.WhenAll) 로직이 매우 강력함.
- 범용성: 유니티뿐만 아니라 일반적인 C# 프로그램 어디서든 쓸 수 있음.
3. 코드 예시
using System.Threading.Tasks; // Task를 쓰기 위해 꼭 필요함! using UnityEngine; public class SimpleAsync : MonoBehaviour { private async void Start() { Debug.Log("로딩 시작"); // await를 붙이면 작업이 끝날 때까지 여기서 '비동기'로 기다림 string result = await GetDataAsync(); // 작업이 끝나면 아래 코드가 이어서 실행됨 Debug.Log("로딩 완료! 결과: " + result); } // Task<반환값>을 리턴하는 비동기 함수임 private async Task<string> GetDataAsync() { // 코루틴의 WaitForSeconds와 비슷한 역할 (2초 대기) await Task.Delay(2000); Debug.Log("데이터를 성공적으로 가져옴"); return "서버 데이터 도착!"; } }💡 키워드 설명💡
- async 키워드: "이 함수 안에서 await를 쓸 거야!"라고 선언하는 거임.
- await 키워드: 비동기 작업(Task)이 끝날 때까지 기다리되, 메인 스레드(게임 화면)를 잡아먹지 않게 해줌.
- Task<string>: 비동기 작업이 끝난 뒤에 string 타입의 결과물을 돌려주겠다는 약속임. (코루틴은 이게 안 됨!)
- Task.Delay(2000): 밀리초 단위임. 2000은 2초를 의미함.
4. 주의할 점
- 메인 스레드 제약: await 이후의 코드가 다른 스레드에서 돌아갈 경우, transform.position 같은 유니티 전용 기능을 건드리면 에러가 날 수 있음.
- 오브젝트 파괴: 코루틴은 오브젝트가 꺼지면 같이 멈추지만, Task는 오브젝트가 파괴되어도 백그라운드에서 계속 돌아감. 그래서 CancellationToken을 써서 직접 멈춰줘야 함.
- UniTask 추천: 유니티 환경에 최적화된 UniTask라는 라이브러리가 있는데, 실무에선 거의 이걸 씀. (메모리 사용량이 훨씬 적음)
< 코루틴 (Coroutine) 과 Async / Await 차이점 >
특징 코루틴 (Coroutine) Async / Await (Task) 반환값 불가능 (결과를 못 돌려줌) 가능 (Task<T>로 결과 반환) 에러 처리 try-catch 사용 불가 try-catch로 예외 처리 가능 메모리 약간의 가비지(GC) 발생 최적화가 더 잘 되어 있음 중지(Stop) StopCoroutine (직관적임) CancellationToken (약간 복잡함) 유니티 친화도 유니티 전용 기능 (친화적) C# 표준 기능 (범용적) - 단순 연출, 초 단위 타이머, 유니티 컴포넌트 제어 → 코루틴
- 네트워크 통신, 복잡한 데이터 로딩, 반환값이 필요한 로직 → Async/Await
'다시한번 개발자도전!' 카테고리의 다른 글
Unity | 크로스페이드(Crossfade) 애니메이션 적용 (0) 2026.01.22 Unity | 반복자(IEnumerator) 와 열거자(IEnumerable) (0) 2026.01.21 Unity | 싱글턴 패턴 (Singleton) (0) 2026.01.20 Unity | 소팅레이어(Sorting Layer) 와 오더인레이어(Order In Layer) (0) 2026.01.20 Unity | 리지드바디(Rigidbody)와 콜라이더(collider)의 관계 (0) 2026.01.20