IMCAT.DEV
로그인 가입
C# 중급 객체지향

C# 델리게이트와 이벤트

C# 델리게이트와 이벤트 — 중급

델리게이트와 이벤트

1. 도입 (왜 배워야 하는가)

C#에서 델리게이트와 이벤트는 사건 기반 프로그래밍의 핵심 요소입니다. 이들을 잘 이해하면 사용자 인터페이스(UI)나 비동기 프로그래밍 등에서 발생하는 다양한 사건을 효과적으로 처리할 수 있습니다. 예를 들어, 버튼 클릭, 데이터 변경 등의 사건을 처리하는 데 필수적입니다.

만약 델리게이트와 이벤트를 모른다면, 다양한 사용자 입력이나 다른 객체와의 상호작용을 수동으로 처리해야 하므로 코드가 복잡해지고 유지보수가 어려워집니다. 이로 인해 실무에서 더 많은 시간과 비용이 소요될 수 있습니다.

2. 핵심 개념 설명

델리게이트

  • 델리게이트는 메서드에 대한 참조를 저장할 수 있는 타입입니다. 즉, 특정 메서드를 호출할 수 있는 "포인터"와 같습니다.
  • 비유: 델리게이트는 레스토랑에서 주문서를 작성하는 것과 비슷합니다. 고객이 요리를 주문하면, 주방이 해당 요리를 만들어내는 것처럼, 델리게이트는 특정 메서드를 호출합니다.
  • 이벤트

  • 이벤트는 델리게이트를 기반으로 하며, 특정 사건이 발생했을 때 통지하는 메커니즘입니다. 다른 객체가 이 사건에 반응할 수 있도록 합니다.
  • 비유: 이벤트는 파티 초대장과 같습니다. 초대장을 받은 사람들은 파티에 참석할 수 있지만, 초대장을 받은 사람은 초대장을 보낸 사람의 요청에 응답하는 것입니다.
  • 용어설명
    델리게이트메서드에 대한 참조를 저장하는 타입
    이벤트델리게이트를 기반으로 한 사건 통지 메커니즘

    3. 기본 코드 예제

    델리게이트와 이벤트의 기본적인 사용법을 보여주는 예제입니다.

    using System;
    
    public delegate void Notify(); // 델리게이트 정의
    
    public class Process
    {
        public event Notify ProcessCompleted; // 이벤트 정의
    
        public void StartProcess()
        {
            Console.WriteLine("프로세스 시작...");
            // 프로세스 작업 수행 (여기서는 단순 출력으로 대체)
            System.Threading.Thread.Sleep(2000); // 2초 대기
            OnProcessCompleted(); // 이벤트 호출
        }
    
        protected virtual void OnProcessCompleted()
        {
            ProcessCompleted?.Invoke(); // 이벤트 발생
        }
    }
    
    public class Program
    {
        public static void Main(string[] args)
        {
            Process process = new Process();
            process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!"); // 이벤트 구독
    
            process.StartProcess(); // 프로세스 시작
        }
    }

    실행 결과:

    프로세스 시작...
    프로세스 완료!

    코드 한 줄씩 동작 설명:

    1. public delegate void Notify(); : Notify라는 이름의 델리게이트를 정의합니다. 반환 값이 없고 인수가 없습니다.
    2. public event Notify ProcessCompleted; : ProcessCompleted라는 이름의 이벤트를 정의합니다. 이 이벤트는 Notify 델리게이트를 사용합니다.
    3. public void StartProcess() : 프로세스를 시작하는 메서드입니다.
    4. System.Threading.Thread.Sleep(2000); : 2초 동안 대기하여 프로세스 작업을 시뮬레이션합니다.
    5. OnProcessCompleted(); : 프로세스가 완료되었음을 나타내는 이벤트를 호출합니다.
    6. protected virtual void OnProcessCompleted() : 이벤트를 발생시키는 메서드입니다. 구독된 메서드를 호출합니다.
    7. ProcessCompleted?.Invoke(); : 이벤트가 구독되어 있으면 호출합니다.
    8. process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!"); : ProcessCompleted 이벤트에 대한 구독을 설정합니다.
    9. process.StartProcess(); : 프로세스를 시작합니다.
    10. 4. 실전 활용 예제

      예제 1: 쇼핑몰 장바구니 구현

      쇼핑몰에서 장바구니에 상품을 추가할 때, 장바구니의 총합을 업데이트하는 이벤트를 사용할 수 있습니다.

      using System;
      using System.Collections.Generic;
      
      public delegate void CartUpdatedEventHandler(decimal total);
      
      public class ShoppingCart
      {
          public event CartUpdatedEventHandler CartUpdated;
          private List<decimal> items = new List<decimal>();
          
          public void AddItem(decimal price)
          {
              items.Add(price);
              OnCartUpdated(CalculateTotal());
          }
      
          private decimal CalculateTotal()
          {
              decimal total = 0;
              foreach (var item in items)
              {
                  total += item;
              }
              return total;
          }
      
          protected virtual void OnCartUpdated(decimal total)
          {
              CartUpdated?.Invoke(total);
          }
      }
      
      public class Program
      {
          public static void Main(string[] args)
          {
              ShoppingCart cart = new ShoppingCart();
              cart.CartUpdated += (total) => Console.WriteLine($"장바구니 총합: {total:C}"); // 이벤트 구독
      
              cart.AddItem(10.99m);
              cart.AddItem(5.49m);
          }
      }

      상황 설명: 사용자가 장바구니에 상품을 추가할 때마다, 장바구니의 총합이 업데이트되고 사용자에게 알림이 전송됩니다.

      예제 2: 비동기 처리

      비동기 작업이 완료되었을 때 이벤트를 사용하는 예제입니다.

      using System;
      using System.Threading.Tasks;
      
      public class AsyncProcess
      {
          public event Action ProcessCompleted;
      
          public async void StartAsyncProcess()
          {
              Console.WriteLine("비동기 프로세스 시작...");
              await Task.Delay(2000); // 2초 대기
              OnProcessCompleted();
          }
      
          protected virtual void OnProcessCompleted()
          {
              ProcessCompleted?.Invoke();
          }
      }
      
      public class Program
      {
          public static void Main(string[] args)
          {
              AsyncProcess asyncProcess = new AsyncProcess();
              asyncProcess.ProcessCompleted += () => Console.WriteLine("비동기 프로세스 완료!");
      
              asyncProcess.StartAsyncProcess();
              Console.ReadLine(); // 프로그램 종료 방지
          }
      }

      상황 설명: 비동기 작업이 완료되면, 해당 작업이 완료되었음을 알리기 위해 이벤트를 사용합니다.

      5. 흔한 실수와 주의사항

      실수 1: 이벤트를 구독하지 않음

    11. 잘못된 코드:
    12.     Process process = new Process();
          process.StartProcess(); // 이벤트 구독 없음
    13. 올바른 코드:
    14.     Process process = new Process();
          process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!");
          process.StartProcess();

      실수 2: 이벤트 핸들러 메서드에 잘못된 형식 사용

    15. 잘못된 코드:
    16.     process.ProcessCompleted += (int total) => Console.WriteLine($"총합: {total}"); // 잘못된 형식
    17. 올바른 코드:
    18.     process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!"); // 올바른 형식

      6. 정리

    19. 델리게이트는 메서드에 대한 참조를 저장할 수 있는 타입이며, 이벤트는 델리게이트를 기반으로 한 사건 통지 메커니즘입니다.
    20. 델리게이트와 이벤트는 사용자 인터페이스 및 비동기 프로그래밍에서 사건 기반 처리에 매우 유용합니다.
    21. 델리게이트와 이벤트를 적절히 활용하면 코드의 가독성과 유지보수성을 높일 수 있습니다.
    22. 다음에 학습하면 좋은 주제

    23. LINQ (Language Integrated Query) : 데이터 처리 및 쿼리 작성
    24. 비동기 프로그래밍 (async/await) : 더 나은 비동기 흐름 제어
    25. 디자인 패턴 (Observer, Command 패턴 등) : 소프트웨어 설계에서의 다양한 패턴 적용.