[로봇활용_11주차] C# 멀티캐스트 대리자

최윤호·2025년 10월 21일
post-thumbnail

여러 명 심부름꾼에게 명령하기

C#에서 대리자는 메서드를 변수처럼 다루는 강력한 기능입니다.
만약 한 명의 심부름꾼에게 여러 개의 임무를 순서대로 시키고 싶다면
어떻게 해야 할까요? 예를 들어, 버튼 하나를 클릭했을 때 로그도 남기고,
파일도 저장하고, 화면도 갱신하는 것처럼요. 이럴 때 C#은 여러 개의 메서드를
체인처럼 연결하여 순차적으로 호출하는 강력한 기능을 가지고 있습니다.
이를 멀티캐스트 대리자(Multicast Delegate)라고 부릅니다.

1)멀티캐스트 대리자란?

멀티캐스트 대리자(Multicast Delegate)는 하나의 대리자 인스턴스가
여러 개의 메서드를 참조하는 목록(Invocation List)을 가지는 것을 말합니다.
한 번 호출하면, 연결된 모든 메서드가 목록에 추가된 순서대로 실행됩니다.
C#에서 System.MulticastDelegate클래스에서 파생된
모든 대리자 타입(delegate, Func, Action모두 포함)은
이 멀티캐스트 기능을 기본적으로 가지고 있습니다.

비유: 심부름 목록

기존의 대리자가 "우유 사 오기"라는 단일 임무 쪽지였다면,
멀티캐스트 대리자는 아래와 같이 여러 임무가 적힌 '체크리스트'와 같습니다.

[오늘의 심부름 목록]
1. 은행 가서 입금하기
2. 세탁소 가서 옷 찾아오기
3. 마트 가서 계란 사 오기

우리는 심부름꾼에게 이 목록 하나만 전달하면,
심부름꾼은 1번부터 3번까지 순서대로 모든 임무를 수행합니다.

2)대리자 체인 만들기

대리자는 +- (또는 +=, -=) 연산자를 사용하여 메서드 목록을 쉽게 조작할 수 있습니다.

1. 예제를 위한 준비

먼저, 여러 가지 알림(Notification) 기능을 수행하는 메서드들을 준비해 보겠습니다.

[코드]

public class Notifier
{
    public void SendEmail(string message)
    {
        Console.WriteLine($"[이메일 발송] {message}");
    }

    public void SendSms(string message)
    {
        Console.WriteLine($"[SMS 발송] {message}");
    }

    public void LogToFile(string message)
    {
        Console.WriteLine($"[파일 로깅] {message}");
    }
}

2. += 연산자로 메서드 연결

이제 Action<string>타입의 대리자 하나에 위 메서드들을 차례대로 연결해 보겠습니다.

[코드]

class Program
{
    static void Main()
    {
        Notifier notifier = new Notifier();

        // 1. 빈 대리자 인스턴스를 생성
        Action<string> notificationChain = null;

        // 2. += 연산자를 사용하여 메서드를 하나씩 체인에 추가
        notificationChain += notifier.SendEmail;
        notificationChain += notifier.SendSms;
        notificationChain += notifier.LogToFile;

        // 3. 대리자를 단 한 번만 호출!
        Console.WriteLine("--- 알림 발송 시작 ---");
        notificationChain("긴급 서버 점검이 있습니다.");
    }
}

[실행 결과]

--- 알림 발송 시작 ---
[이메일 발송] 긴급 서버 점검이 있습니다.
[SMS 발송] 긴급 서버 점검이 있습니다.
[파일 로깅] 긴급 서버 점검이 있습니다.

notificationChain을 한 번 호출했을 뿐인데,
연결된 세 개의 메서드가 모두 순서대로 실행되었습니다.

3. -= 연산자로 메서드 제거

이번에는 연결된 체인에서 특정 메서드를 제거해 보겠습니다.
예를 들어, "이제 SMS는 보내지 않는다."라고 결정한 상황입니다.

[코드]

class Program
{
    static void Main()
    {
        Notifier notifier = new Notifier();

        // 1. 빈 대리자 인스턴스를 생성
        Action<string> notificationChain = null;

        // 2. += 연산자를 사용하여 메서드를 하나씩 체인에 추가
        notificationChain += notifier.SendEmail;
        notificationChain += notifier.SendSms;
        notificationChain += notifier.LogToFile;

        // 3. -= 연산자를 사용하여 SendSms 메서드를 체인에서 제거
        notificationChain -= notifier.SendSms;

        // 4. 다시 대리자를 호출
        Console.WriteLine("--- SMS 제외 후 알림 발송 시작 ---");
        notificationChain("점검이 완료되었습니다.");
    }
}

[실행 결과]

--- SMS 제외 후 알림 발송 시작 ---
[이메일 발송] 점검이 완료되었습니다.
[파일 로깅] 점검이 완료되었습니다.

SendSms메서드가 성공적으로 제거되어 더 이상 호출되지 않는 것을 확인할 수 있습니다.

3)주의사항

멀티캐스트 대리자는 매우 강력하지만, 반환 값이 있는
대리자(Func등)와 함께 사용할 때 주의해야 할 점이 있습니다.
만약 반환 값이 있는 메서드들이 체인으로 연결되어 있다면,
최종 반환 값은 가장 마지막에 호출된 메서드의 반환 값만 남게 됩니다.

이전 메서드들의 반환 값은 모두 무시됩니다.

[코드]

Func<int, int> calcChain = null;

calcChain += FirstCalc;
calcChain += SecondCalc;

int result = calcChain(10);

Console.WriteLine($"최종 결과: {result}");

int FirstCalc(int x)
{
    Console.WriteLine("첫 번째: x + 1");
    return x + 1;
}

int SecondCalc(int x)
{
    Console.WriteLine("두 번째: x * 2");
    return x * 2;
}

[실행 결과]

첫 번째: x + 1
두 번째: x * 2
최종 결과: 20

첫 번째 메서드가 반환한 11은 사라지고, 마지막 메서드가
반환한 20만이 최종 결과가 되었습니다. 따라서 멀티캐스트 대리자는
주로 반환 값이 없는 Action계열 대리자와 함께 사용하여
'일련의 동작'을 수행하는 데 사용하는 것이 일반적입니다.

4)정리

멀티캐스트 대리자(Multicast Delegate)는 하나의 호출로 여러 동작을
연쇄적으로 실행할 수 있게 해주는 C#의 핵심 기능 중 하나입니다.

연산자역할설명
+=구독(Subscribe)대리자의 호출 목록에 새로운 메서드를 추가합니다.
-=구독 취소(Unsubscribe)대리자의 호출 목록에서 특정 메서드를 제거합니다.
profile
🚀 미래의 엔지니어를 꿈꾸는 훈련생의 기록 📝

0개의 댓글