본문 바로가기
유니티

c# unity Delegate 델리게이트

by 유니티세상 2026. 4. 29.
반응형

처음에 델리게이트 봤을떄 무슨말인지 이해를 못했었다

 

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는 "함수를 담는 것"이 아니라
"객체와 메서드 호출을 연결하는 참조"다

그래서 언제 이벤트를 써야하냐고 물으신다면 정답은 없지만 아래 내용이 도움이 되었다.

https://wikidocs.net/342320

 

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