✅ 클로저(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 이렇게 복사한 변수를 써야 버튼마다 다르게 작동한다!