1. C# 델리게이트(Delegate)의 정의
C#에서 델리게이트는 특정 매개변수 목록과 반환 형식을 가진 메서드에 대한 참조를 저장할 수 있는 참조 형식(Reference Type)입니다. 이는 메서드를 변수처럼 다루거나 다른 메서드의 인수로 전달할 수 있게 해주는 강력한 기능으로, 흔히 '타입 세이프(Type-Safe) 함수 포인터'라고도 불립니다. 델리게이트는 참조하는 메서드의 시그니처(매개변수 타입과 개수, 반환 타입)와 일치해야 한다는 타입 세이프 특성을 가지고 있어 컴파일 타임에 오류를 검출하는 데 도움을 줍니다.
2. 델리게이트 선언 및 인스턴스화
델리게이트를 사용하기 위해서는 먼저 해당 델리게이트 타입을 선언해야 합니다. 이는 delegate
키워드를 사용하여 수행하며, 참조할 메서드의 시그니처를 명시합니다.
[문법]
// 접근제한자 delegate 반환타입 델리게이트이름(매개변수 목록);
public delegate void MyDelegate(string message); // string 타입 매개변수 하나를 받고 반환값이 없는 메서드를 참조하는 델리게이트 선언
델리게이트 타입을 선언한 후에는, 해당 타입의 인스턴스를 생성하고 특정 메서드를 참조하도록 할당해야 합니다.
[예시 코드]
using UnityEngine;
public class DelegateExample : MonoBehaviour
{
// 1. 델리게이트 선언
public delegate void MyDelegate(string message);
// 2. 델리게이트 인스턴스 생성 (변수 선언)
private MyDelegate messageDelegate;
void Start()
{
// 3. 메서드를 델리게이트 인스턴스에 할당
// 방법 1: 메서드 이름 직접 할당
messageDelegate = ShowMessage;
// 방법 2: new 키워드 사용 (덜 일반적)
// messageDelegate = new MyDelegate(ShowMessage);
// 델리게이트 호출 준비 완료
}
// 델리게이트 시그니처와 일치하는 메서드
void ShowMessage(string msg)
{
Debug.Log("메시지 수신: " + msg);
}
}
3. 델리게이트 호출 (Invocation)
델리게이트 인스턴스가 특정 메서드를 참조하고 있다면, 이 인스턴스를 함수처럼 호출하여 참조된 메서드를 실행할 수 있습니다. 중요한 점은 델리게이트 인스턴스가 null
인지 확인한 후 호출하는 것이 안전하다는 것입니다. 델리게이트가 아무 메서드도 참조하지 않는 상태(null)에서 호출을 시도하면 NullReferenceException
이 발생합니다.
[예시 코드]
using UnityEngine;
public class DelegateInvocation : MonoBehaviour
{
public delegate void MyDelegate(string message);
private MyDelegate messageDelegate;
void Start()
{
messageDelegate = DisplayLog; // 메서드 할당
// 안전한 델리게이트 호출
if (messageDelegate != null)
{
messageDelegate("델리게이트를 통해 메시지를 전달합니다.");
}
// C# 6.0 이상: Null 조건부 연산자 사용 (?.)
messageDelegate?.Invoke("Null 조건부 연산자를 사용한 안전한 호출");
// 델리게이트 참조 해제
messageDelegate = null;
// 아래 호출은 예외를 발생시키므로 주석 처리하거나 null 체크 필수
// messageDelegate("이 호출은 NullReferenceException을 발생시킬 수 있습니다.");
}
void DisplayLog(string text)
{
Debug.Log(text);
}
}
4. Unity에서의 델리게이트 주요 활용 사례
델리게이트는 Unity 개발에서 다양한 방식으로 활용되어 코드의 유연성과 재사용성을 높이는 데 기여합니다.
이벤트 시스템 구현 (Event System): C#의
event
키워드는 델리게이트를 기반으로 구현됩니다. Unity에서는 UI 상호작용(버튼 클릭 등), 게임 내 특정 이벤트 발생(플레이어 사망, 아이템 획득 등) 시 관련 로직을 실행하기 위해 이벤트 시스템을 광범위하게 사용합니다. 델리게이트(와 이벤트)는 이벤트 게시자(Publisher)와 구독자(Subscriber) 간의 결합도를 낮춰(Decoupling) 시스템을 모듈화하는 데 핵심적인 역할을 합니다.// 예시: 간단한 게임 이벤트 시스템 public class GameEventManager : MonoBehaviour { public delegate void ScoreUpdateAction(int newScore); public static event ScoreUpdateAction OnScoreUpdated; // 이벤트 선언 (델리게이트 기반) public static void TriggerScoreUpdate(int score) { OnScoreUpdated?.Invoke(score); // 이벤트 발생 (안전하게 호출) } } public class ScoreDisplay : MonoBehaviour { void OnEnable() { GameEventManager.OnScoreUpdated += HandleScoreUpdate; } // 이벤트 구독 void OnDisable() { GameEventManager.OnScoreUpdated -= HandleScoreUpdate; } // 이벤트 구독 해지 void HandleScoreUpdate(int newScore) { Debug.Log("점수 업데이트: " + newScore); } }
콜백 함수 (Callback Functions): 비동기 작업(예: 웹 요청, 파일 로딩)이 완료되었을 때 특정 함수를 실행하도록 하거나, 애니메이션 재생 완료, 특정 시간 경과 후 등의 시점에 콜백 함수를 실행하고자 할 때 델리게이트가 유용하게 사용됩니다.
코드 분리 및 유연성 증대: 델리게이트를 사용하면 특정 작업을 수행하는 컴포넌트가 해당 작업의 구체적인 구현 내용을 알 필요 없이, 단지 델리게이트를 통해 필요한 메서드를 호출하기만 하면 됩니다. 이는 컴포넌트 간의 의존성을 줄여 코드 수정 및 확장을 용이하게 만듭니다.
5. 심화 내용: 멀티캐스트 델리게이트와 이벤트(Event)
멀티캐스트 델리게이트 (Multicast Delegate): 하나의 델리게이트 인스턴스는 여러 개의 메서드를 참조할 수 있습니다.
+=
연산자를 사용하여 메서드를 추가하고,-=
연산자를 사용하여 제거할 수 있습니다. 델리게이트를 호출하면 참조 목록에 있는 모든 메서드가 순서대로 호출됩니다. 이는System.MulticastDelegate
클래스에서 파생된 모든 델리게이트의 특징입니다.이벤트 (Event):
event
키워드는 델리게이트를 외부에 노출할 때 사용되며, 델리게이트를 캡슐화하여 특정 제약을 가합니다. 외부에서는+=
(구독) 및-=
(구독 취소) 연산자만 사용할 수 있으며, 직접적인 할당(=
)이나 델리게이트 호출(Invoke()
)은 해당 클래스 내부에서만 가능합니다. 이는 이벤트의 의도치 않은 초기화나 외부에서의 직접적인 이벤트 발생을 방지하여 코드의 안정성을 높입니다.
결론
C# 델리게이트는 메서드를 참조하고 전달하는 강력한 메커니즘을 제공하며, Unity 개발에서 이벤트 기반 프로그래밍, 콜백 구현, 코드 디커플링 등 다양한 시나리오에서 핵심적인 역할을 수행합니다. 델리게이트의 개념과 사용법을 정확히 이해하고 활용하는 것은 보다 견고하고 유연하며 유지보수가 용이한 Unity 애플리케이션을 구축하는 데 필수적입니다. 특히 이벤트 시스템과의 연관성을 이해하는 것은 Unity의 다양한 내장 시스템 및 커스텀 시스템 설계에 큰 도움이 될 것입니다.
참고 자료
- Microsoft C# 공식 문서 - 델리게이트
- Microsoft C# 공식 문서 - 이벤트
- Unity 공식 문서 - 스크립팅 개요 (델리게이트 및 이벤트 관련 내용 포함)