[이득우의 언리얼] 9. 언리얼 C++ 설계 - 델리게이트

2026. 2. 6. 16:21·기타/[강의] 이득우의 언리얼 프로그래밍 Part1

개요

이번 강의에서는 Unreal Engine의 델리게이트(Delegate)를 사용하여 클래스 간의 느슨한 결합(Loose Coupling)을 구현하는 방법을 학습합니다. 발행-구독(Publish-Subscribe) 디자인 패턴을 통해 학사 정보 시스템과 학생 간의 알림 기능을 구현하면서 델리게이트의 실용적인 활용법을 익힙니다.

 

학습 목표

- 느슨한 결합의 장점과 델리게이트의 역할 이해

- 발행-구독 디자인 패턴의 개념과 구현 방법 학습

- Unreal 델리게이트의 다양한 종류와 선언 방법 습득

- 델리게이트를 활용한 이벤트 기반 시스템 구축

 


 

느슨한 결합이란 ?

강한 결합 (Tight Coupling)

: 클래스들이 서로 직접 의존하는 관계

// ❌ 강한 결합 - Person이 Card에 직접 의존
class UPerson
{
private:
    TObjectPtr<UCard> Card;  // Card 클래스에 강하게 결합
};

문제점

- 카드 시스템이 핸드폰 인증으로 변경되면 ?

- UPerson과 모든 자식 클래스를 수정해야 함

- 유지보수가 어려움

 

느슨한 결합 (Loose Coupling)

: 추상화를 통한 간접 의존

// ✅ 느슨한 결합 - 인터페이스를 통한 추상화
class ICheckIn
{
    virtual void CheckIn() = 0;
};

class UCard : public ICheckIn
{
    virtual void CheckIn() override { /* 카드로 체크인 */ }
};

class UPhone : public ICheckIn
{
    virtual void CheckIn() override { /* 핸드폰으로 체크인 */ }
};

class UPerson
{
private:
    TObjectPtr<ICheckIn> CheckInDevice;  // 인터페이스에 의존
};

장점

- 구현이 변경되어도 UPerson 코드는 그대로

- 새로운 체크인 방식 추가 용이

- 테스트와 유지보수 간편

 


 

델리게이트 선언 방법

델리게이트 유형

 

선언 예시

// 인자 없음, 반환값 없음
DECLARE_DELEGATE(FSimpleDelegate)

// 인자 1개 (FString), 반환값 없음
DECLARE_DELEGATE_OneParam(FStringDelegate, const FString&)

// 인자 2개, 반환값 없음 (멀티캐스트)
DECLARE_MULTICAST_DELEGATE_TwoParams(
    FOnCourseInfoChanged, 
    const FString&,  // 주체
    const FString&   // 내용
)

// 인자 3개, 반환값 있음 (float)
DECLARE_DELEGATE_RetVal_ThreeParams(
    float,           // 반환값
    FCalculateDelegate,
    float,           // 파라미터 1
    float,           // 파라미터 2
    float            // 파라미터 3
)

 

CourseInfo.h

더보기
#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "CourseInfo.generated.h"

// 델리게이트 선언 (클래스 외부, UCLASS 위)
DECLARE_MULTICAST_DELEGATE_TwoParams(
    FOnCourseInfoChangedSignature,  // 델리게이트 타입 이름
    const FString&,                  // 첫 번째 파라미터: 주체
    const FString&                   // 두 번째 파라미터: 내용
);

UCLASS()
class UNREALDELEGATE_API UCourseInfo : public UObject
{
    GENERATED_BODY()
    
public:
    /** 생성자입니다. */
    UCourseInfo();
    
    /** 학사 정보 변경 델리게이트입니다. */
    FOnCourseInfoChangedSignature OnCourseInfoChanged;
    
    /** 학사 정보를 변경하는 함수입니다. */
    void ChangeCourseInfo(const FString& SchoolName, const FString& NewInfo);
    
private:
    /** 학사 정보 내용 변수입니다. */
    FString Contents;
};

CourseInfo.cpp

더보기
#include "CourseInfo.h"

UCourseInfo::UCourseInfo()
{
    // 기본 학사 정보 설정
    Contents = TEXT("기존 학사 정보");
}

void UCourseInfo::ChangeCourseInfo(const FString& SchoolName, const FString& NewInfo)
{
    // 학사 정보 변경
    Contents = NewInfo;
    
    // 알림 발송 로그
    UE_LOG(LogTemp, Log, TEXT("[CourseInfo] 학사 정보가 변경되어 알림을 발송합니다."));
    
    // 구독자들에게 브로드캐스트
    OnCourseInfoChanged.Broadcast(SchoolName, NewInfo);
}

Student.h

더보기
#pragma once

#include "CoreMinimal.h"
#include "Person.h"
#include "Student.generated.h"

UCLASS()
class UNREALDELEGATE_API UStudent : public UPerson
{
    GENERATED_BODY()
    
public:
    /** 생성자입니다. */
    UStudent();
    
    /** 알림을 받는 함수입니다. */
    void OnNotification(const FString& SchoolName, const FString& NewCourseInfo);
};

Student.cpp

더보기
#include "Student.h"

UStudent::UStudent()
{
    Name = TEXT("이학생");
}

void UStudent::OnNotification(const FString& SchoolName, const FString& NewCourseInfo)
{
    // 알림 수신 로그
    UE_LOG(LogTemp, Log, TEXT("[Student] %s님이 알림을 받음 - 학교: %s, 내용: %s"), 
           *Name, 
           *SchoolName, 
           *NewCourseInfo);
}

MyGameInstance.h

더보기
#pragma once

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyGameInstance.generated.h"

// 전방 선언
class UCourseInfo;

UCLASS()
class UNREALDELEGATE_API UMyGameInstance : public UGameInstance
{
    GENERATED_BODY()
    
public:
    virtual void Init() override;
    
private:
    /** 학사 정보 변수입니다. */
    UPROPERTY()
    TObjectPtr<UCourseInfo> CourseInfo;
};

MyGameInstance.cpp

더보기
#include "MyGameInstance.h"
#include "CourseInfo.h"
#include "Student.h"

void UMyGameInstance::Init()
{
    Super::Init();
    
    UE_LOG(LogTemp, Log, TEXT("===== 델리게이트 예제 시작 ====="));
    
    // 1. 학사 정보 시스템 생성
    CourseInfo = NewObject<UCourseInfo>(this);
    
    // 2. 학생 3명 생성
    UStudent* Student1 = NewObject<UStudent>();
    Student1->SetName(TEXT("학생1번"));
    
    UStudent* Student2 = NewObject<UStudent>();
    Student2->SetName(TEXT("학생2번"));
    
    UStudent* Student3 = NewObject<UStudent>();
    Student3->SetName(TEXT("학생3번"));
    
    // 3. 델리게이트에 구독자 바인딩
    CourseInfo->OnCourseInfoChanged.AddUObject(
        Student1, 
        &UStudent::OnNotification
    );
    
    CourseInfo->OnCourseInfoChanged.AddUObject(
        Student2, 
        &UStudent::OnNotification
    );
    
    CourseInfo->OnCourseInfoChanged.AddUObject(
        Student3, 
        &UStudent::OnNotification
    );
    
    // 4. 학사 정보 변경 (자동으로 모든 구독자에게 알림)
    CourseInfo->ChangeCourseInfo(TEXT("학교"), TEXT("변경된 학사 정보"));
    
    UE_LOG(LogTemp, Log, TEXT("===== 델리게이트 예제 종료 ====="));
}


**실행 결과:**
===== 델리게이트 예제 시작 =====
[CourseInfo] 학사 정보가 변경되어 알림을 발송합니다.
[Student] 학생1번님이 알림을 받음 - 학교: 학교, 내용: 변경된 학사 정보
[Student] 학생2번님이 알림을 받음 - 학교: 학교, 내용: 변경된 학사 정보
[Student] 학생3번님이 알림을 받음 - 학교: 학교, 내용: 변경된 학사 정보
===== 델리게이트 예제 종료 =====

 

델리게이트 바인딩 메서드

1. AddUObject (가장 일반적)

// UObject의 멤버 함수 바인딩
MyDelegate.AddUObject(ObjectInstance, &UMyClass::MemberFunction);

특징 :

- Unreal Object의 멤버 함수 바인딩

- 자동 메모리 관리 (객체 소멸 시 자동 해제)

- 가장 안전하고 권장되는 방법

 

2. AddStatic

// 정적 함수 바인딩
MyDelegate.AddStatic(&MyStaticFunction);

특징 :

- 전역 또는 정적 함수 바인딩

- 객체 인스턴스 불필요

 

3. AddRaw

// 일반 C++ 객체의 멤버 함수 바인딩
MyDelegate.AddRaw(CppObject, &MyCppClass::MemberFunction);

특징 :

- Non-UObject C++ 클래스 바인딩

- 수동 메모리 관리 필요

 

4. AddLambda

// 람다 함수 바인딩
MyDelegate.AddLambda([](const FString& Param)
{
    UE_LOG(LogTemp, Log, TEXT("Lambda: %s"), *Param);
});

특징 :

- 인라인 함수 정의

- 간단한 로직에 적합

- 캡처 사용 가능

 

5. AddSP (Shared Pointer)

// TSharedPtr로 관리되는 객체의 멤버 함수 바인딩
MyDelegate.AddSP(SharedObject, &MyClass::MemberFunction);

특징 :

- 스마트 포인터 기반 객체 바인딩

- 참조 카운팅 자동 관리

'기타 > [강의] 이득우의 언리얼 프로그래밍 Part1' 카테고리의 다른 글

[이득우의 언리얼] 11. 언리얼 컨테이너 라이브러리 - 구조체, Map  (0) 2026.02.08
[이득우의 언리얼] 10. 언리얼 컨테이너 라이브러리 - TArray, TSet  (0) 2026.02.07
[이득우의 언리얼] 8. 언리얼의 C++ 설계 - 컴포지션  (0) 2026.02.06
[이득우의 언리얼] 7. 언리얼 C++ 설계 - 인터페이스  (0) 2026.02.04
[이득우의 언리얼] 6.언리얼 오브젝트 리플렉션 시스템 2  (0) 2026.02.04
'기타/[강의] 이득우의 언리얼 프로그래밍 Part1' 카테고리의 다른 글
  • [이득우의 언리얼] 11. 언리얼 컨테이너 라이브러리 - 구조체, Map
  • [이득우의 언리얼] 10. 언리얼 컨테이너 라이브러리 - TArray, TSet
  • [이득우의 언리얼] 8. 언리얼의 C++ 설계 - 컴포지션
  • [이득우의 언리얼] 7. 언리얼 C++ 설계 - 인터페이스
Meoyoung's Development Logs
Meoyoung's Development Logs
내가 보려고 만든 블로그
  • Meoyoung's Development Logs
    이게뭐영
    Meoyoung's Development Logs
  • 전체
    오늘
    어제
    • 분류 전체보기 (229)
      • 게임잼 (3)
      • 언리얼 엔진 (53)
        • 꿀 Tip ! (7)
        • 트러블슈팅 (24)
        • 최적화 (0)
        • 캐릭터 (2)
        • VR (1)
        • Lighting (2)
        • 멀티스레드 (2)
        • 문자열 (0)
      • C++ (31)
        • 문법 정리 (8)
        • [서적] Fundamental C++ 프로그래밍 .. (5)
        • [서적] 이것이 C++이다 (11)
        • [서적] Effective C++ (7)
      • C# (1)
        • [서적] 이것이 C#이다 (1)
      • 코딩테스트 (26)
        • 프로그래머스 (6)
        • 알고리듬 (13)
        • 자료구조 (7)
      • 컴퓨터 과학 (27)
        • 운영체제 (11)
        • 데이터베이스 (0)
        • 디자인패턴 (0)
        • 자료구조 (5)
        • 네트워크 (0)
        • 컴퓨터구조 (11)
      • 면접준비 (0)
        • C++ (0)
        • 운영체제 (0)
        • 자료구조 (0)
      • 프로젝트 (25)
        • [팀프로젝트] The Fourth Descenda.. (5)
        • [개인프로젝트] FPS 구현 맛보기 (5)
        • GetOutOf (15)
      • 기타 (54)
        • [강의] 이득우의 언리얼 프로그래밍 Part1 (10)
        • [강의] 이득우의 언리얼 프로그래밍 Part3 (12)
        • [강의] 소울라이크 개발 A-Z (4)
        • [강의] Udemy-2D (5)
        • [서적] 인생 언리얼5 (4)
        • 스파르타코딩클럽 (15)
        • 객체지향프로그래밍 (2)
        • 컴퓨터회로 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    버블정렬
    셸정렬
    알고리즘
    자료구조
    삽입정렬
    참가후기
    게임개발
    쉘정렬
    게임잼
    경북게임잼
    선택정렬
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Meoyoung's Development Logs
[이득우의 언리얼] 9. 언리얼 C++ 설계 - 델리게이트
상단으로

티스토리툴바