[UNITY] 클로저(Closure)란?

 

✅ 클로저(Closure)란?

클로저는 어떤 함수가 자신이 선언될 때의 스코프(scope)에 있는 변수들을 기억하는 기능이에요.

예시:

for (int i = 0; i < 3; i++)
{
    Action printI = () => Debug.Log(i);
    printI();
}

 

이 코드는 0, 1, 2를 출력할 것 같지만…
사실은 **모두 3**을 출력합니다.

왜냐면 printI() 안의 i는 반복문이 끝난 후의 최종 값 3을 참조하고 있기 때문이에요.
람다 함수 안에서 i를 "값으로 복사"하는 게 아니라 **"참조"**만 하기 때문에 이런 문제가 발생합니다.


✅ Unity에서의 클로저 문제

Unity에서 버튼에 이벤트를 연결할 때도 비슷한 문제가 생깁니다:

for (int i = 0; i < AnswersBtnList.Length; i++)
{
    AnswersBtnList[i].onClick.AddListener(() => OnClick_AnsweBtn(AnswersBtnList[i].gameObject));
}

이렇게 하면 어떤 버튼을 누르든 항상 마지막 i 값 (예: 3번째 버튼)이 호출되는 문제가 발생합니다.
즉, 누른 버튼이 아닌 반복문 마지막에 설정된 버튼만 실행돼요.


✅ 해결법: 지역 변수에 임시 저장

for (int i = 0; i < AnswersBtnList.Length; i++)
{
    int index = i; // 클로저 문제 해결!
    AnswersBtnList[i].onClick.AddListener(() => OnClick_AnsweBtn(AnswersBtnList[index].gameObject));
}

위와 같이 index라는 지역 변수에 i 값을 복사해 놓으면,
각 버튼마다 자기만의 index 값을 기억하게 되기 때문에 의도한 대로 동작합니다!


✅ 요약

개념 설명

클로저 함수가 선언 당시의 외부 변수를 기억하는 성질
클로저 문제 반복문에서 외부 변수(i 등)가 반복 끝난 후의 값으로 전부 바뀌는 현상
해결 방법 반복문 안에서 임시 지역 변수(int index = i;)를 사용해서 복사

간단히 말해서:

❌ i를 직접 쓰면 안 되고
✅ int index = i 이렇게 복사한 변수를 써야 버튼마다 다르게 작동한다!