📚 델리게이트 시리즈
1편: 함수 포인터
2편: std::function
3편: Delegate 구현
4편: 엔진 스타일 Delegate
🚀 들어가며
이전 글에서는 std::function과 람다를 이용해
👉 유연한 콜백 구조를 만드는 방법을 살펴봤습니다.
std::function<void()> func = []()
{
std::cout << "Hello\n";
};
func();
이 구조만으로도 충분히 강력합니다.
하지만 게임 엔진에서는 여기서 한 단계 더 나아갑니다.
❓ “하나의 이벤트에 여러 함수를 연결할 수는 없을까?”
예를 들어:
버튼 클릭 → 사운드 재생 → UI 업데이트 → 로그 출력
👉 하나의 이벤트에 여러 동작이 연결됩니다.
이걸 가능하게 만드는 구조가 바로 델리게이트(Delegate)입니다.
🎯 델리게이트란 무엇인가?
델리게이트는 간단히 말하면:
- 여러 개의 콜백 함수를 저장하고, 한 번에 실행하는 구조입니다.
🧠 기본 아이디어
이벤트 발생 ↓ 등록된 함수 리스트 순회 ↓ 모든 함수 실행
🎮 단순한 구현
먼저 아주 단순한 구조부터 만들어보겠습니다.
#include <vector>
#include <functional>
class Delegate
{
public:
void Add(std::function<void()> func)
{
functions.push_back(func);
}
void Broadcast()
{
for (auto& func : functions)
{
func();
}
}
private:
std::vector<std::function<void()>> functions;
};
🎯 사용 예제
#include <iostream>
void PlaySound()
{
std::cout << "Play Sound\n";
}
void UpdateUI()
{
std::cout << "Update UI\n";
}
Delegate onClick; onClick.Add(PlaySound); onClick.Add(UpdateUI); onClick.Broadcast();
👉 출력:
Play Sound Update UI
🔥 핵심 포인트
여러 개의 함수를 등록한다 ↓ 한 번에 실행한다
👉 이것이 델리게이트의 본질입니다.
🎯 람다와 함께 사용하기
onClick.Add([]()
{
std::cout << "Log Event\n";
});
👉 이제 함수뿐 아니라 람다도 등록 가능합니다.
🎮 객체와 함께 사용하기
class Player
{
public:
void OnClick()
{
std::cout << "Player Click\n";
}
};
Player player;
onClick.Add([&player]()
{
player.OnClick();
});
👉 결과:
Player Click
🧠 이 구조의 의미
이제 이벤트 시스템을 이렇게 표현할 수 있습니다.
이벤트 ↓ 리스너 등록 ↓ 이벤트 발생 시 호출
👉 완전한 이벤트 시스템 구조입니다.
⚠️ 문제점 1: 제거(Remove)가 없다
현재 구조는 추가만 가능합니다.
onClick.Add(func);
👉 하지만 제거는 불가능합니다.
🔧 간단한 Remove 구현
델리게이트에 추가된 함수 포인터 전체 제거는 쉽게 처리할 수 있습니다.
void Clear()
{
functions.clear();
}
하지만, 특정 함수 제거는 더 복잡합니다.
이를 위해 실제 엔진에서는 ID 기반으로 관리합니다.
⚠️ 문제점 2: 성능
std::function는 함수 포인터보다 유연하지만 추가 비용이 발생
👉 이유:
- 타입 소거
- 내부 힙 할당 가능성
🎯 그래서 엔진에서는?
게임 엔진에서는 보통:
✔ 빠른 호출 ✔ 타입 안전성 ✔ 다양한 바인딩 방식
👉 이걸 위해 직접 델리게이트 시스템을 구현합니다
🔥 싱글 캐스트 vs 멀티 캐스트
지금 만든 것은:
👉 멀티 캐스트 델리게이트
✔ 싱글 캐스트
함수 1개만 저장
✔ 멀티 캐스트
함수 여러 개 저장
👉 지금 구현한 구조
🎮 엔진에서의 실제 사용
게임 엔진에서는 이런 구조로 사용됩니다.
키 입력 → 여러 시스템 반응 충돌 발생 → 여러 컴포넌트 반응 UI 이벤트 → 여러 리스너 실행
🎯 구조 정리
함수 포인터 ↓ std::function ↓ Delegate ↓ 이벤트 시스템
🔥 핵심 정리
- 델리게이트는 여러 콜백을 저장하는 구조이다.
- Broadcast를 통해 모든 함수를 실행한다.
- 람다와 함께 사용하면 매우 유연하다.
- 이벤트 시스템의 핵심 구조다.
🎯 다음 단계
다음 단계에서는:
👉 엔진 스타일 델리게이트로 확장
- 함수 등록 ID
- 제거 기능
- 성능 개선
- 템플릿 기반 구조
👉 실제 엔진 수준으로 확장해보겠습니다.
🎮 마무리
델리게이트는 단순한 자료구조가 아니라
👉 게임 엔진의 이벤트 시스템 그 자체입니다.
이 구조를 이해하면:
- 입력 시스템
- UI 이벤트
- 게임 로직 연결
👉 모두 하나의 흐름으로 보이기 시작합니다.
🚀 한 단계 더 나아가고 싶다면
델리게이트 구조는
입력 시스템, 이벤트 처리, 객체 구조와 깊게 연결됩니다.
단순히 사용하는 것을 넘어서,
엔진이 어떻게 동작하는지 이해하는 데 초점을 맞춘 내용입니다.