Unity_본캠프

[내일배움캠프 28일차] 델리...케이트...람...다?

티백고래 2025. 5. 16. 23:37

1. 오늘의 학습

 

델리케이트와 람다에 대해 학습했다.

델리케이트의 연장선인 Action과 Function도 학습했다.

Action은 저번에 쓴 게 비슷한 것 같은데....(event Action과 다른 걸까?)

간단해 정리해보자 Let's go

 

2. 학습 정리📘

 

Action을 들어가고 싶지만 그 전에 델리케이트를 정리한다.

 

1. 델리케이트(Delegate)

(솔직히 Dedicated로 들었다.)

함수를 변수처럼 다룰 수 있으면 좋겠다~ 아 있을 것 같은데~했는데….

이게 진짜 있네. 의 주인공이다.

그 전에 알고 있던 건 돌아다니면서 겨우 주워먹은 event Action뿐이라 헤에 그렇구나 하고 그냥 가져다 썼는데 이번 기회에 확실히 습득할 수 있어서 기쁘다.

 

Delegate. 위에 말했듯 함수, 메서드를 '변수'처럼 다룰 수 있게 해주는 코드이다. 

Delegate에다가 함수 자체를 변수로 저장하고 출력 가능.

 

어떻게?

이렇게.

 

//접근제한자+delegate+반환형+델리게이트명();
public delegate void DeliTest();
public DeliTest deliTest;

public void DebugCode()
{
    Debug.Log("테스트 코드 ON");
}

public void ShowDebug()
{
    deliTest = DebugCode;
	deliTest?.Invoke();
}

그리고 ShowDebug를 Start()에서 실행하면 DebugCode()의 내용이 그대로 출력된다.

매개변수가 들어가면 똑같이 매개변수를 추가해주면 된다.

?.Invoke는 해당 함수가 null값을 반환해도 처리할 수 있도록 해둔 안전장치이다.

그리고 이걸 더 간단하게 한 버전이 있다.

 

2. Action, Func

사용방법은 델리게이트보다 더 쉽다.

기존 델리게이트의 2줄짜리 선언을 

public Action actionTest;

로 바꾸면 끝난다.

그리고 actionTest = DebugCode; 로 할당만 해주면 나머지는 끝.

델리게이트보다 더 쉽고 간단하게 함수를 변수로 바꿀 수 있다.

하지만 Action은 기본적으로 void일 때만 사용할 수 있고, 반환형이 그 외의 것이라면 Func를 사용한다.

사용법은 거의 같지만, Func는 return int, string등을 반환할 수 있다.

 

3. Action과 event Action의 차이

그런데 내가 개판냥판을 만들 때 썼던 건 event Action이었다. 구조는 거의 같은 것 같았는데.

event키워드가 더 붙었는데 뭔가 다른가?

역시 다르겠지? 코딩인데 괜히 하나가 더 붙은 채 기능한 게 아닐테니까?

 

바로 찾아보자.

 

event ActionAction 타입에 C# event 키워드를 붙인 것이다.

이 키워드를 통해 해당 Delegate에 대한 접근을 제한, 외부에서는 이벤트를 '구독(+=)'과 '구독 취소(-=)'만 가능하게 만들어준다.

이벤트 자체를 직접 호출하거나 =null로 초기화 하는 것은 선언된 클래스 내부에서만 가능하다.

 

아래는 개판냥판에서 사용했던 Item.cs의 일부이다.

 //이벤트 시스템으로 Fish와 Bone의 카운트 변화가 있을 때마다 호출
 public static event Action OnItemCountChanged;

 private void Awake()
 {
     //Fish, Bone 오브젝트 아래에 있는 자식들(Fish 클론들) 카운트)
     BoneCount = BoneObj.transform.childCount;
     FishCount = FishObj.transform.childCount;
     OnItemCountChanged?.Invoke();
 }

 public static void ChangeFishCount(int delta)
 {
     FishCount += delta;
     OnItemCountChanged?.Invoke();
 }

 public static void ChangeBoneCount(int delta)
 {
     BoneCount += delta;
     OnItemCountChanged?.Invoke();
 }

 

그리고 해당 요소를 구독/구독 취소한 곳은 ItemCountUI.cs로, 여기서는 구독(+=)과 구독취소(-=)밖에 하지 못했다.

여기서 직접 OnItemCountChanged?.Invoke();는 사용할 수 없는 것이다.

 

 

하지만 Action은 클래스 내부 뿐만이 아니라 외부에서도 호출이 가능하다.

할당 및 초기화도 Action은 외부에서도 가능하지만 event Action은 불가능하다.

하지만 함수를 할당하는 것은 둘 다 외부와 내부 모두 가능하다.

 

즉 둘의 차이

: event Action = 내부에서만 호출가능. 특정 사건 발생 시 알림 시스템 (OnEnable과 OnDisable을 통해 구독관리)

Action = 외부에서도 호출 가능. 임시 이벤트 처리나 간단한 함수 콜백 등 유연하게 메소드를 가져오고 싶을 때 사용.

 

event Action은 이벤트가 터질 때마다 중복으로 적용되는 걸 방지하기 위해 OnEnable과 OnDisable을 잘 이용해주는 게 좋다.

 

4. 람다

 

=>로 익숙한 것.

일종에 이름 없는 함수를 만드는 형태이다. (함수 식조차 쓰기 귀찮은 자들의...)

장점: 단순하고 가독성이 좋으며 가볍게 쓰기 좋다.

단점: 길어지면 가독성을 오히려 해치므로 따로 함수로 뺄 것.

 

보통의 사용 처: 임시로 간단한 기능을 수행하는 함수가 필요할 때 사용 (대충 한줄 짜리..)

LINQ에서 많이 쓴다.

 

Action simpleLambda = () => Console.WriteLine("매개변수 없는 람다 식.");

 

정말 이거면 되는거야? 싶지만 정말 이거면 되는게 람다.

여기다가 이제 simpleLambda(); 나  simpleLambda.Invoke();를 쓰면 출력으로 매개변수 없는 람다식.이 나온다.

우와 중괄호도 없어!! 한줄이면 끝나!!!

물론 수식이 여러개면 { } 중괄호를 쓰면 된다. 이건 일반 함수랑 똑같다.

매개 변수가 있는 경우, 아래처럼 만들 수 있다.

 

Func<int, int> square = x => x*x;

square라는 이름의 Func식을 람다로 짧게 만든 것이다.

※ Func 식은 기본적으로 void형 델리게이트인 Action과 비슷하지만 반환값이 있는 메서드를 델리게이트 할때 사용한다. 그렇기에 뒤에 <매개변수, 반환값>의 형태를 가지는데, 매개변수가 여러개라도, 없더라도, 마지막은 무조건 반환값이다.

 

매개변수 int x를 받아서 x*x를 리턴하는 형태이다.

 

주의
: return 해야할 것이 너무 많거나, 복잡해지면 디버깅도 힘들어진다. 복잡하면 일반 메서드로 분리할 것. 잘 쓸 수 있으면 좋지만 못쓰겠으면 일단 일반 메서드나 잘 쓸 것.

 

3. 마무리

사실 이 TIL의 주요 내용은 event Action과 Action의 차이를 구분하는 것이었다.

이러나저러나 델리게이트는 상당히 유용해보이므로 앞으로 잘 쓸 수 있도록 해봐야겠다.