이번 게시글에서는 델리게이트 (Delegate) 와 이벤트 (Event) 가 무엇인지에 대해서 알아보는 시간을 가져보도록 하겠습니다. 들어가기 전에, 델리게이트 (Delegate) 와 이벤트 (Event) 는 우리가 여러가지 응용프로그램 (앱) 을 개발하기 위해서는 반드시 숙지해두어야 하는 필수 문법이므로 반드시 완벽한 이해를 하신 후 넘어가도록 합시다.
델리게이트란 무엇일까?
델리게이트(delegate)의 사전적 의미로는 대리자 입니다. 대리자라는 사람은 무언가의 일을 대신해서 해 주는 사람이라는 뜻입니다. 이와 같이 델리게이트 역시 프로그램에서 어떠한 기능을 대신 수행해 주는 역할을 가지고 있는 것입니다. 따라서, 대신해서 수행 해 주는 녀석! 정도로 정의 해두고, 어떠한 일을 대신 해 주는 것인지를 같이 학습해 보겠습니다.
델리게이트 (Delegate) 의 선언
델리게이트는 사용자 정의 형 이라고 정의 할 수 있습니다. 그렇다면 사용자 정의형이라는 의미가 무엇인지 알아봐야 될 것 같네요. 사용자 정의는 절대 어려운 개념이 아닙니다. 사용자 정의 형에 대한 대표적인 예는 클래스 (Class) 입니다.
어떤 특정한 형식을 사용자가 정의 해 둔 것을 의미 합니다. 아래 그림을 보고 이해해 보도록 합시다.

델리게이트 (Delegate) 는 사용자 정의 형으로 클래스 (Class) 와 같은 위치에서 선언됩니다. 그리고 선언 형식은 메서드(함수)와 동일한 형식으로 선언됩니다. 눈치가 빠른 사람이라면 델리게이트 (Delegate) 는 메서드 (Method) 와 연관이 있다라는 것을 짐작했을 것입니다. 그럼 델리게이트가 가지고 있는 기능을 살펴 보도록 하겠습니다.
메서드의 대리자, 델리게이트 (Delegate)
델리게이트의 대표적 기능은 메서드를 대신 수행해 주는 역할을 합니다. C 언어에서는 포인터 함수라는 같은 개념이 존재합니다. 하지만 C# 은 포인터의 개념을 사용하지 않으므로 이렇게 델리게이트라는 문법을 만들어 버린 것입니다. 포인터 함수의 개념을 이해하고 배우는 기간이나 난이도에 비해, 델리게이트 문법을 익히는 것이 훨씬 쉽고 빠르게 이해 하실 수 있습니다. 그만큼 차세대 언어는 개발자의 편의성을 많이 고려하여 설계 된 것입니다.
그럼 아래 예제를 통해서 델리게이트를 선언하는 방법과 어떻게 메서드로 대리자의 기능을 하게 되는지 살펴 보도록 합시다.
using System;
//델리게이트 선언
delegate void dele1();
delegate int dele2(int a,int b);
class MainClass
{
static void Main(string[] args)
{
//Math 클래스 선언 및 인스턴스화
MathClass MathClass = new MathClass();
//델리게이트 선언 및 인스턴스화
dele1 Sum1 = new dele1(MathClass.Intro);
dele2 Sum2 = new dele2(MathClass.Sum);
//델리게이트에 위임된 메서드 실행
Sum1();
Console.WriteLine("Result : {0}", Sum2(-10, 90));
}
}
class MathClass
{
public void Intro()
{
Console.WriteLine("계산을 시작합니다.");
}
public int Sum(int a, int b)
{
return a + b;
}
}
실행 결과 :
계산을 시작합니다.
Result : 80
먼저 MathClass를 만들었습니다. 이 클래스는 두 개의 메서드를 가지고 있습니다. 하나는 반환형과 매게변수가 없는 Intro 라는 함수 이고, 또 다른 하나는 덧셈 기능을 수행하여 리턴 해 주는 Sum 이라는 함수입니다.
자! 그럼 3 ~ 4 번째 줄에 선언 된 델리게이트를 살펴봅시다. MathClass 가 가지고 있는 함수와 똑같은 형식을 갖춘 델리게이트 두 개가 선언 되어 있습니다. dele1 은 반환 값이나 매개변수가 존재하지 않고, dele2 는 두 개의 int 형 매개변수를 가지고 있으며 int 형 반환 값을 가지고 있습니다.
12, 13 번째 줄에 보면 선언된 델리게이트를 인스턴스 화 시킵니다. 그리고 생성자에는 메서드가 참조됩니다. 만약 dele1 Sum1 = new dele1() 로 델리게이트를 선언한다면 컴파일 에러가 발생하게 됩니다.
즉, 델리게이트는 반드시 메서드를 참조 시켜야 한다는 사실을 반드시 기억하고 있어야 합니다.
그리고 dele1 에 MathClass.Sum 과 같은 매개변수와 선언 형식이 다른 메서드를 참조시키려고 하더라도 “메서드와 대리자가 일치하지 않습니다” 라는 컴파일 에러가 발생하게 되고 위임 메서드는 대리자와 형식이 일치 해야 된다는 사실 역시 기억해 두어야겠죠.
이제 15, 16 번째 줄에서 Sum1() 과 Sum2 라는 델리게이트를 실행하게 됩니다. 그럼 이제 위임받은 메서드를 대신하여 실행하게 되는 것입니다. 결과 역시 메서드를 직접 호출하는 것과 같은 값이 출력됩니다.
Delegate 의 연산
델리게이트 객체는 Combine 과 Remove 라는 두 가지의 연산 메서드를 지원합니다. 이것은 델리게이트가 여러 메서드의 참조가 가능하다는 것입니다.
- Combine: 기존의 위임에 또 다른 위임을 추가합니다. = [+]
- Remove: 기존의 위임에 특정 위임을 제거합니다. = [-]
그럼 이러한 연산 메서드가 어떻게 사용되는지 아래 예제를 통해서 연산되는 과정을 살펴보도록 합시다.
using System;
delegate void deleMath(int Value); //델리게이트 선언
class MainClass
{
static void Main(string[] args)
{
//Math클래스 선언 및 인스턴스화
MathClass MathClass=new MathClass();
//델리게이트 선언 및 인스턴스화(덧셈)
deleMath Math=new deleMath(MathClass.Plus);
//위임연산 (뺄셈, 곱셈추가)
Math+=new deleMath(MathClass.Minus);
Math+=new deleMath(MathClass.Multiply);
//결과 1
MathClass.Number=10;
Math(10);
Console.WriteLine("Result:{0}",MathClass.Number);
//위임 연산 (뺄셈 제거)
Math-=new deleMath(MathClass.Minus);
//결과 2
MathClass.Number=10;
Math(10);
Console.WriteLine("Result:{0}",MathClass.Number);
//위임 연산 (곱셈 제거)
Math-=new deleMath(MathClass.Multiply);
//결과 3
MathClass.Number=10;
Math(10);
Console.WriteLine("Result:{0}",MathClass.Number);
}
}
class MathClass
{
public int Number;
public void Plus(int Value) // 더하기
{
Number += Value;
}
public void Minus(int Value) // 빼기
{
Number -= Value;
}
public void Multiply(int Value) // 곱하기
{
Number *= Value;
}
}
실행 결과 :
Result : 100
Result : 200
Result : 20
37 번 째 줄에 정의 된 MathClass의 메서드들을 살펴 보면 3 개의 연산 메서드들이 존재합니다. 이 메서드들은 매개변수로 받은 값을 Number 라는 전역변수와 연산을 하고 Number 변수에 저장하게 됩니다.
먼저 += 연산자의 의미를 살펴 보도록 합시다. 만약 int i =5; 라고 선언을 하고 i 에 10을 더해주고 싶다면 i += 10; 이렇게 코딩을 하여 사용해 왔을 것입니다. 즉 i += 10; 은 i = i + 10과 같은 뜻이 됩니다. 여기서 사용된 += 연산자 역시 마찬가지 의미로 사용되지만, 단지 메서드를 추가로 참조 시키고 뺀다는 의미가 되는 것입니다.
그럼 코드에서 11 번째 줄을 살펴 봅시다. Math 델리게이트는 선언함과 동시에 Plus 메서드를 기본으로 참조시켰습니다. 그리고 14 번째 줄을 보면 += 연산을 이용하여 추가로 메서드를 추가하고 있습니다. 이제 Math 델리게이트는 3 개의 메서드가 참조된 델리게이트가 된 것입니다.
18번째 줄 에서는 10 이라는 매개 변수를 넣어 델리게이트를 실행합니다. 이 델리게이트는 Plus(10), Minus(10), Multiply(10) 이렇게 세 개의 메서드를 차례대로 호출하는 것과 똑같은 의미를 가집니다. 결과 역시 차례대로 수행한 100 이 출력됩니다.
이제 22번째 줄을 봅시다. – 연산자를 이용하여서 메서드를 Minus 메서드를 참조에서 제외시킵니다. 처리 결과를 출력해 보면 곱하기와 덧셈 메서드만 실행된 화면을 볼 수 있습니다.
위에서 살펴본 것과 같이 +=, -= 와 같은 연산자를 이용하여 여러 메서드들을 추가 하고 참조를 제어 할 수 있다는 것을 알 수 있을 것입니다.
델리게이트는 이후에 다룰 스레드, 비동기 처리, 이벤트 등등에서 기본적으로 사용 되는 아주 중요한 문법입니다. 델리게이트를 선언하고, 메서드를 참조하여 사용 하는 방법까지 확실하게 이해하고 넘어가시길 바랍니다.
이벤트 (Event) 란 무엇일까?
앞서 학습한 델리게이트를 활용하기 위해서 이벤트라는 녀석을 학습해 보도록 하겠습니다. 윈도우 프로그램을 다루어 보신 분이라면, 쉽게 이해할 수 있을 것이지만, 윈도우 응용프로그램을 다루어 본적이 없으신 분이라면 “엇! 이벤트?!” 그 이런 것이 아닐까라는 생각들이 머리에 그려지고 있을 것입니다.
자, 그럼 이벤트라는 것은 어떤 것인지 알아 봅시다. 지금 제가 사용하는 윈도우 2000 운영체제를 예를 들어 설명해 보겠습니다. 제가 컴퓨터를 사용하고 있다고 가정합니다. 컴퓨터를 사용하고 있는 지금 마우스를 움직이고, 키보드를 누르고, 창을 열고 있습니다. 지금 저는 수많은 이벤트들을 발생 시킨 것이죠. 이제 이해가 되었나요? 어떠한 사건이 없이는 프로그램은 동작하지 않습니다. 그 어떠한 사건이 바로 이벤트인 것이고, 우리는 이 사건을 받아서 어떠한 처리를 해줄 것인지 프로그래밍을 하면 되는 것입니다. 머, 생각보다 거대한 개념은 아닙니다. 그럼 본격적으로 이벤트를 학습해 보도록 하겠습니다.
이벤트는 델리게이트를 통하여 구현 됩니다. 하나의 이벤트는 여러 개의 작업들이 추가 될 수 있어야 합니다. 그리고 그 작업들은 외부 메서드를 필요로 할 수도 있을 것입니다. 이런 작업을 위해서 델리게이트를 필요로 하게 되는 것입니다.
이벤트 (Event)
이벤트 선언하기
event 선언된 델리게이트 이벤트명;
이제 선언된 델리게이트를 이벤트와 연결하여 사용하는 이벤트 예제를 살펴보도록 하겠습니다.
using System;
// 델리게이트 선언
delegate void eventDelegate();
class EventTest
{
// Event1 이라는 우리만의 새로운 이벤트를 선언해 주고,
// 이 이벤트의 처리는 eventDelegate 타입의 delegate들이
// 하게 된다는 것을 알립니다.
public event eventDelegate ckEvent;
// 어떤 버튼을 누를 때, 이 메서드가 호출된다고 가정합시다.
public void btnClick()
{
ckEvent();
}
}
class MainClass
{
static void Click()
{
Console.WriteLine("클릭되었습니다.");
}
static void Main(string[] args)
{
// 클래스 선언 및 인스턴스화
EventTest eTest = new EventTest();
// 미리 정의한 이벤트 즉, ckEvent가 발생한 경우
// eTest 라는 인스턴스에서 이 이벤트를 처리할 메서드
// (핸들러, Delegate) 를 지정합니다.
eTest.ckEvent += new eventDelegate(MainClass.Click);
// 어떤 버튼이 눌려서 클릭 이벤트가 발생되었다고 가정합니다.
eTest.btnClick();
}
}
실행 결과 :
클릭되었습니다.
이제, 코드를 살펴 보면서 이벤트의 동작을 이해 해 봅시다. 9 번 째 줄에서 ckEvent 라는 이벤트를 선언 하였고, 이 ckEvent 는 앞서 3 번 째 줄에서 선언된 eventDelegate 형식을 가지게 됩니다.
11 번 째 줄에 선언된 btnClick() 라는 메서드는 ckEvent() 를 실행하고 있습니다. 여기서 우리는 이벤트를 메서드와 같은 형식으로 호출 할 수 있다는 것을 알 수 있습니다.
이제 MainClass안의 Main 메서드를 살펴 보도록 합시다. 먼저 클래스를 인스턴스화 하였습니다. 30 번 째 줄에서는 이벤트 동작에 의해 실행 될 메서드를 추가하고 있습니다. 메서드를 추가하는 방법은 앞서 학습한 델리게이트의 형식을 똑같이 따르고 있습니다.
아직 이벤트에 대한 개념이 잘 잡히지 않는다 하더라도 너무 걱정 할 필요는 없습니다. 나중에 윈도우 응용 프로그램을 다루게 될 그 때, 조금 더 자세하게 이벤트에 대해서 언급하도록 하겠습니다.
정리
이번 게시글에서는 델리게이트(delegate) 와 이벤트(Event)에 대해서 알아 보았습니다. 델리게이트는 이벤트 뿐만 아니라 뒤에 학습하게 될 스레드 (Thread) 에서도 활용되는 개념이므로 무엇보다도 델리게이트에 대해서는 완벽히 이해하신 후 넘어 가시기 바랍니다.
감사합니다.
