이벤트(Event)는 클래스나 객체에서 관심 있는 어떤 일이 발생했을 때, 다른 클래스나 객체에 그 사실을 알릴 수 있도록 해주는 C#의 강력한 기능입니다.
이벤트를 발생(raise)시키는 클래스를 게시자(publisher)라고 부르고, 발생한 이벤트를 받아서 처리하는 클래스를 구독자(subscriber)라고 부릅니다.
C# 이벤트의 주요 특징
- 다중 구독 가능: 하나의 이벤트에는 여러 구독자가 등록될 수 있습니다. 반대로 하나의 구독자가 여러 게시자의 여러 이벤트를 동시에 처리할 수도 있습니다.
- 구독자가 없으면 실행되지 않음: 구독자가 하나도 없는 이벤트는 아무리 호출해도 실제로 발생하지 않습니다.
- 역할 분리: 이벤트가 언제 발생하는지는 게시자가 결정하고, 이벤트에 대한 응답으로 어떤 동작을 수행할지는 구독자가 결정합니다.
예제 코드
아래 예제는 MP4 비디오 인코딩이 완료되면 이벤트를 발생시키고, 이를 메일 서비스와 메시지 서비스 두 개의 구독자가 각각 처리하는 상황을 보여줍니다.
class Program {
static void Main() {
var video = new MP4() { Title = "Eminem" };
var videoEncoder = new MP4EncoderNew();
var mailService = new MailService();
var messageService = new MessageService();
// 하나의 이벤트에 두 개의 구독자 등록
videoEncoder.mp4Encoded += mailService.onVideoEncoded;
videoEncoder.mp4Encoded += messageService.onVideoEncoded;
videoEncoder.Encode(video);
Console.ReadKey();
}
}
public class MP4 {
public string Title { get; set; }
}
public class MP4Args : EventArgs {
public MP4 mp4 { get; set; }
}
// 게시자(Publisher)
public class MP4EncoderNew {
public EventHandler mp4Encoded;
public void Encode(MP4 video) {
Console.WriteLine("Encoding MP4");
Thread.Sleep(3000);
OnVideoEncoded(video);
}
protected void OnVideoEncoded(MP4 video) {
if (mp4Encoded != null) {
mp4Encoded(this, new MP4Args() { mp4 = video });
}
}
}
// 구독자 1
public class MailService {
public void onVideoEncoded(object source, MP4Args e) {
Console.WriteLine("Mail Service:,Sending an email {0}", e.mp4.Title);
}
}
// 구독자 2
public class MessageService {
public void onVideoEncoded(object source, MP4Args e) {
Console.WriteLine("Message Service:,Sending an Message {0}", e.mp4.Title);
}
}코드 설명
MP4EncoderNew클래스는 인코딩 작업을 수행한 뒤OnVideoEncoded메서드를 통해mp4Encoded이벤트를 발생시킵니다.Main메서드에서+=연산자를 사용해MailService와MessageService두 구독자를 같은 이벤트에 등록합니다.- 이벤트가 발생하면 등록된 순서대로 모든 구독자의 핸들러가 차례로 호출됩니다.
실행 결과
Encoding MP4 Mail Service:,Sending an email Eminem Message Service:,Sending an Message Eminem
실행 결과에서 볼 수 있듯이, 하나의 이벤트(mp4Encoded)에 등록된 두 구독자가 모두 정상적으로 호출되어 각자의 작업을 수행했습니다. 이처럼 C#의 이벤트는 하나의 이벤트에 대해 여러 구독자를 가질 수 있으며, 게시자와 구독자 간의 느슨한 결합(loose coupling)을 통해 유연하고 확장성 있는 코드를 작성할 수 있게 해줍니다.