반응형
처음에 델리게이트 봤을떄 무슨말인지 이해를 못했었다
IT/프로그래밍 분야 (Delegate/Delegation):
함수나 객체가 자신의 작업을 직접 처리하지 않고, 대신 처리해 줄 다른 객체에게 업무를 맡기는 패턴
먼저 아래에서 나오는 메서드가 무슨뜻인지 정의하고 가자
메서드 함수의 차이
C#에서 메소드(Method)는 클래스 내부에 정의된 함수로 객체에 종속적입니다.
일반적인 함수(Function)는 독립적으로 존재할 수 있으나 C#은 객체 지향 언어이므로 모든 함수가 클래스 안에 위치하여 메서드라 불립니다.
결과적으로 C#에서 메서드는 클래스의 기능을 수행하는 함수로 간주됩니다.
즉!
함수(Function)와 메소드(Method)의 핵심 차이는 객체(Class)에 종속되는지 여부
모든 메서드는 함수이지만 모든 함수가 메서드는 아님
Delegate / Action / Func 정리
1. 개념 구조
Delegate (개념 / 타입)
├─ 사용자 정의 delegate
├─ Action
└─ Func
- Delegate: 메서드를 참조하는 타입 (함수를 변수처럼 다루게 해줌)
- Action / Func: 편의성을 위해 미리 정의된 delegate 타입
2. Delegate란 무엇인가
정의
메서드(함수)를 변수처럼 저장하고 호출할 수 있게 해주는 참조 타입
내부 개념
delegate = (target object, method pointer)
- target object: 어떤 객체의 메서드인지
- method pointer: 어떤 메서드를 호출할지
예시
class Player
{
public void Jump() { }
}
Player player = new Player();
Action action = player.Jump;
action(); // player.Jump() 실행
핵심
delegate는 단순한 함수 주소가 아니라
"객체 + 메서드 호출 정보"를 들고 있는 구조다
3. Action / Func 차이
Action
반환값이 없는 delegate
Action<int> action = (x) => Debug.Log(x);
Func
반환값이 있는 delegate
Func<int, int> func = (x) => x * 2;
정리
구분 설명
| Delegate | 직접 정의 가능한 함수 참조 타입 |
| Action | 반환값 없음 |
| Func | 반환값 있음 |
4. 멀티캐스팅 (Multicast Delegate)
개념
delegate는 여러 개의 메서드를 동시에 등록할 수 있다.
Action action = A;
action += B;
action += C;
action(); // A → B → C 순서 실행
내부 구조
Invocation List = [A, B, C]
반환값 있는 delegate 주의
Func<int> func = A;
func += B;
func += C;
int result = func(); // C의 반환값만 반환
멀티캐스트 Func는 마지막 함수의 반환값만 의미 있음
샘플 코드
using System;
using UnityEngine;
public class DelegateFuncActionSamples : MonoBehaviour
{
//delegate 선언
public delegate int IntBinaryOperator(int a, int b); //int 반환
public delegate void StringHandler(string message); //void 반환
private void Start()
{
DelegateSample();
}
public void DelegateSample()
{
// ====== Delegate 예제 ======
IntBinaryOperator add = Add;
Debug.Log("Add: " + add(1, 2));
//멀티 캐스트(여러 메서드 연결)
StringHandler stringHandler = Print;
stringHandler += PrintUpper;
stringHandler("Hello");
//Hello 이후 HELLO 출력
//멀티캐스팅 + 반환값 있는 델리게이트는 마지막 반환값만 남음
IntBinaryOperator mulitply = Add;
mulitply += Multiply;
//Debug.Log("Add: " + mulitply(1, 2)); //add 실행안되고 곱만 실행되서 2가 나옴
Debug.Log("Mulitply: " + mulitply(2, 3)); //6 출력
//왜 add 함수의 반환값이 나오지 않는가?
//값을 하나만 반환해줄 수 있으니 마지막 실행된 메서드의 반환값이 들어옴(Multiply 함수의 반환값 6)
//Add 함수의 반환값은 버려짐
// ====== Action 예제 (void) ======
Action<string> action = Print;
action+= PrintUpper;
action("Hello");
//Hello 이후 HELLO 출력
// ====== Func 예제 (반환값 있는 델리게이트) ======
Func<int, int, int> func = Add;
Debug.Log("Func: " + func(1, 2));
//Func 예제 2 : 반환값 있는 델리게이트 예제
Func<string, int > func2 = str => str.Length; //string을 받아서 int를 반환
Debug.Log($"func length: {func2("Test")}"); // 4 출력
}
private int Add(int a, int b) => a + b;
private int Multiply(int a, int b) => a * b;
private void Print(string msg)
{
Debug.Log(msg);
}
private void PrintUpper(string msg)
{
Debug.Log(msg.ToUpper());
}
}
5. Delegate와 GC 관계
핵심
delegate는 target object를 강하게 참조한다
결과
delegate가 살아있으면
→ 해당 객체도 GC 대상이 아니다
6. Unity에서 메모리 릭 발생 원인
문제 구조
EventManager → delegate → 객체
객체가 Destroy 되었어도
delegate가 참조하고 있으면 GC가 수거하지 못함
해결 방법
OnEnable → Add
OnDisable → Remove 또는 Dispose
7. static 이벤트 주의
public static event Action OnSomething;
문제
static은 앱 종료까지 살아있음
→ 모든 구독 객체를 계속 참조
→ 메모리 릭 발생
8. 람다(delegate) 사용 시 주의
예시
EventManager.Add(() => Debug.Log(this.name));
문제
람다가 this를 캡처
→ delegate가 객체를 계속 참조
→ GC 수거 불가
추가 위험
EventManager.Add(() =>
{
SomeMethod();
});
클로저(closure) 생성
→ 숨겨진 객체 생성
→ 참조 관리 어려움
9. 최종 핵심 정리
Delegate = 함수 참조 타입
Action = 반환값 없는 delegate
Func = 반환값 있는 delegate
delegate는 객체를 참조하기 때문에
이벤트 구독을 해제하지 않으면 GC가 객체를 수거하지 못한다
Unity에서는 반드시 이벤트 해제를 해줘야 한다
핵심 한 줄
delegate는 "함수를 담는 것"이 아니라
"객체와 메서드 호출을 연결하는 참조"다
그래서 언제 이벤트를 써야하냐고 물으신다면 정답은 없지만 아래 내용이 도움이 되었다.
Chapter 06. 델리게이트와 이벤트 기반 구조
## 6.1 왜 프로그램은 점점 “직접 호출”만으로 버거워질까요? 입문 단계에서 프로그램의 흐름은 비교적 단순합니다. A 메서드가 B 메서드를 호출하고, B 메서드가 C 메서드…
wikidocs.net
이벤트가 더 자연스러운 경우
- 어떤 사건에 여러 대상이 반응할 수 있다
- 누가 반응할지 발생 주체가 몰라도 된다
- 반응 대상이 나중에 늘어나거나 바뀔 수 있다
- 알림과 후속 처리를 분리하는 것이 구조적으로 좋다
예:
- 플레이어 사망
- 버튼 클릭
- 점수 변경
- 아이템 획득
- 스테이지 완료
직접 호출이 더 자연스러운 경우
- 호출 흐름이 핵심 로직으로 매우 분명하다
- 단순한 1:1 협력이다
- 발생과 처리의 관계가 고정적이다
- 흐름이 눈에 바로 보이는 것이 더 중요하다
예:
- 계산 메서드 호출
- 내부 상태 갱신
- 명확한 서비스 사용
- 꼭 필요한 다음 단계 실행
즉, 이벤트는 만능이 아닙니다. 핵심 흐름까지 전부 이벤트화하면 오히려 코드가 안 보이게 될 수 있다고한다.
반응형
'유니티' 카테고리의 다른 글
| Saga Pattern, Outbox Pattern (0) | 2026.05.18 |
|---|---|
| 파이어베이스 게임 데이터 수집 및 분석 관련 블로그 (0) | 2026.05.14 |
| c# 심화 (0) | 2026.04.28 |
| 유니티 생성자, 소멸자 (0) | 2026.04.28 |
| Unity Thread, Task, async/await, EventBus (0) | 2026.04.28 |