이전 글에서 yield return 을 사용하면 함수 실행을 중간에 멈췄다가 다시 실행할 수 있다는 것을 배웠습니다. 그렇다면, C# 은 어떻게 이를 가능하게 할까요? 이번 글에서는 yield return 이 내부적으로 어떻게 동작하는지 알아보겠습니다.
yield return 이 포함된 함수는 컴파일 단계에서 변환된다
yield return 을 포함한 함수는 일반적인 함수처럼 작동하는 것이 아니라, 컴파일러에 의해 특별한 클래스로 변환됩니다. 즉, C# 컴파일러는 해당 함수를 IEnumerator 인터페이스를 구현하는 클래스로 변환하여 실행 흐름을 제어합니다. 예를 들어, 다음 코드를 보겠습니다:
IEnumerator MyCoroutine()
{
Console.WriteLine("Step 1");
yield return null;
Console.WriteLine("Step 2");
yield return null;
Console.WriteLine("Step 3");
}
이 함수는 컴파일러에 의해 아래와 같이 변환됩니다.
class MyCoroutineState : IEnumerator
{
private int state = 0;
public object Current { get; private set; }
public bool MoveNext()
{
switch (state)
{
case 0:
Console.WriteLine("Step 1");
Current = null;
state = 1;
return true;
case 1:
Console.WriteLine("Step 2");
Current = null;
state = 2;
return true;
case 2:
Console.WriteLine("Step 3");
state = -1;
return false;
}
return false;
}
// Reset() 함수는 거의 사용되지 않음.
public void Reset() { state = 0; }
}
컴파일러는 yield return 을 만나면 현재 상태를 저장하고 (state 변수), 다음 실행될 위치를 기록하여 중단할 수 있도록 변환합니다. 그리고 MoveNext() 가 호출되면 저장된 위치에서 다시 실행을 시작합니다.
yield return 을 만날 때마다, 자동으로 case 에 대응하는 코드를 생성해줍니다. 즉, yield return이 100개 있다면, 컴파일러는 각각의 위치에 대응하는 case 문을 100개 생성합니다. 이 구조는 내부에서 상태를 switch로 분기하며 실행 흐름을 나누는 방식입니다.
MoveNext() 는 어떻게 실행 흐름을 제어할까?
위 코드에서 MoveNext() 메서드는 switch 문을 사용하여 현재 실행 위치를 추적합니다.
최초 state 값이 0이면, Step 1을 출력하고 return true 를 합니다. 즉 함수를 빠져나갑니다.
다음 번에 MoveNext() 가 호출되면 state가 1이므로, Step 2를 출력하고 다시 함수를 빠져나갑니다.
마지막 Step 3을 출력한 후 state = -1로 설정되어 종료됩니다. 즉, MoveNext() 가 호출될 때마다 state 값을 찾아서 실행합니다.
코드를 작성한 입장에서 보면, yield return 을 만날 때마다 다음 상태를 저장하고 함수를 빠져 나가게 되는 것입니다.
결국 MoveNext()는 yield return 을 기준으로 실행 흐름을 쪼개고, 그 지점을 기억했다가 한 번에 하나씩만 실행되도록 컨트롤하는 핵심 함수입니다.
마무리
yield return이 포함된 함수는 일반적인 함수가 아니라, 컴파일러에 의해 IEnumerator를 구현하는 클래스로 변환됩니다. 변환된 클래스는 MoveNext() 메서드를 사용하여 실행 위치를 관리하고, yield return 을 만나면 멈췄다가 다시 실행될 수 있습니다. 멈춘다는 표현을 보다 정확하게는 return true; 로 MoveNext() 함수를 빠져나가는 것입니다.
IEnumerator는 MoveNext()를 호출하면서 실행 흐름을 제어하는 핵심 인터페이스입니다.
이번 글에서는 yield return이 내부적으로 어떻게 동작하는지 살펴보았습니다. 다음 글에서는 yield return이 코루틴과 어떻게 연결되는지 더 자세히 알아보겠습니다.
'C#' 카테고리의 다른 글
4. yield return 에 대해 ( 활용 01 ) (0) | 2025.03.09 |
---|---|
3. yield return 에 대해 (유니티에서의 동작) (0) | 2025.03.09 |
1. yield return 에 대해 (개념) (0) | 2025.03.09 |
Action 과 Func 의 형변환 살펴보기 (0) | 2025.03.08 |
=> (람다 연산자) 이해하기 (0) | 2025.03.08 |