카테고리 없음

[Unity/C#] Delegate & Event & Lambda 정리

Joon_Im 2025. 4. 4. 20:40

[Unity/C#] Delegate & Event & Lambda 정리

이제까지 느낌으로만 대충 이해하고 있었던 delegate, event, lambda식에 대해서 한번 다시 복습해야겠다고 생각하던 찰나,

참고하며 공부하기 좋은 블로그를 발견하여 다시 공부하고 실습하면서 내용을 익혀보았다.

 

먼저 테스트용 Unity 프로젝트를 만들고  Player 클래스와 Enemy 클래스를 만들어주었다.

Player 클래스는 IAttack 인터페이스를 상속 받아 Attack 메서드를 사용할 수 있고,

Enemy 클래스는 IDamage를 상속 받아 TakeDamge 메서드를 사용할 수 있다.

 

1. Delegate

 

▲ 델리게이트 예시

 

먼저 delegate BuffAttack을 정의하고, 정의한 델리게이트 타입의 변수(객체)를 선언 (private BuffAttack buffAttack;) 해준다. 

 

▲ 델리게이트를 이용하여 Player 클래스에서 Attack 메서드 호출 시 buff bool 값에 따라 다른 문구 출력

 

Attack 메서드 안에서 buff 관련 bool값에 따라

bool buff1이 true면 buffAttack 델리게이트에 Buff1 메서드 연결, 호출

bool buff2가 true면 buffAttack 델리게이트에 Buff2 메서드 연결, 호출

 

결과

▲ buff1 true, 버프1 적용! 문구 출력

 

▲ buff2 true, 버프2 적용! 문구 출력

 

또한 델리게이트에는 += 연산자, -=연산자를 활용하여 여러 메서드를 구독해 호출하거나, 구독 해지를 할 수 있다.

▲ 델리게이트 체인 예시

 

델리게이트는 유용하지만, 남용할 경우 디버그 시 함수 호출 추적이 매우 어려울 수 있어 코드 분석이 어려워진다는 단점이 있다.

2. Event

델리게이트와 같지만, 외부에서 호출 불가능하고 내부에서만 호출 가능하다는 특징이 있다.

▲ Enemy 클래스에서 event 델리게이트 정의, 변수 선언
▲ Player 클래스에서 호출하려하면 오류가 나온다.

그럼 델리게이트 말고 왜 이벤트를 쓰냐는 의문이 들 수 있는데, 이런 특징으로 인한 장점들이 존재한다.

 

Event의 장점은

1. 외부에서 호출할 수 없다.

좀 더 안정적인 이벤트 기반 프로그래밍을 만들 수 있다.

실수로 호출해야할 부분이 아닌 다른 외부에서 호출하는 것을 막아줄 수 있다.

 

2. 외부에서 대입연산자를 사용할 수 없다.

델리게이트 체인에서 마지막 부분에 실수로 대입연산자를 사용했다면, 앞의 연결들이 끊어지고 가장 마지막에 대입된 함수만 실행될 것이다. 그러나 이벤트라면 대입연산자 사용이 막히기 때문에 안정적으로 프로그래밍 할 수 있다.

 

위와 같은 특징들 때문에 이벤트(event)는 객체의 상태 변화나 사건의 발생을 알리는 용도로 구분해서 사용하고,

델리게이트(delegate)는 콜백 기능이 필요할 때 사용하는 방식으로 구분하는 것이 좋다.

 

3. Lambda

1. 익명 메서드

▲ 익명 메서드 예시

만약 enemyDamaged 델리게이트에서만 사용되는 메서드라면

위와 같이 익명 메서드로 대체해서 축약하여 쓸 수 있다.

 

2. 람다식

▲ 람다식 예시

익명 메서드와 비슷한 모양이지만 더 축약이 되었다.

내용이 한 줄일 때는 위와 같이, 여러 줄일 경우 아래와 같이 사용한다.

 

람다식은 유용하지만 몇 가지 단점이 존재하는데,

 

1. 람다식은 델리게이트 체인 관리가 어렵다.

델리게이트는 -= 연산자로 기존 연결을 끊을 수 있지만, 람다식은 해제가 되지 않는다.

따라서 나중에 구독해지가 필요하다면 람다식을 사용하지 말아야한다.

 

2. 코드 분석이 어려워진다.

이 단점은 델리게이트 단점과 동일하다.

남용할 경우 디버그 시 함수 호출 추적이 매우 어려울 수 있다.

 

3. 메모리 효율성 저하

람다식을 사용하는 과정은

익명 클래스를 내부적으로 생성하고, 이 클래스가 객체를 힙에 할당하는 방식이기 때문에

기본의 메서드 호출보다 더 많은 메모리를 소비하게 된다.

 

 

이제까지 느낌으로만 대충 이해하고 있었던 delegate, event, lambda식에 대해서 다시 공부하고 실습하면서

모호한 부분들이 해결이 된 것 같았다.

앞으로 활용하면서도 헷갈리는 일이 있을 때 참고할 수 있을 것 같다.