본문 바로가기
C#

C# Action delegate 완벽 가이드: 콜백 함수(callback)와 이벤트 핸들링(event handling) 활용

by 대박플머 2024. 11. 1.

C#의 Action 대리자는 코드에서 메서드를 캡처하여 나중에 호출할 수 있는 강력한 도구입니다. 이 글에서는 Action의 개념, 사용 방법, 주요 활용 예시를 다루며, Func 대리자와의 차이점, Action을 사용할 때의 이점과 주의사항을 포함하겠습니다.


1. Action이란?

Action은 .NET 프레임워크의 내장 대리자(delegate) 타입 중 하나입니다. Action 대리자는 반환값이 없는 메서드를 캡처할 때 사용되며, 최대 16개의 입력 매개변수를 받을 수 있습니다.

기본적으로 Action 대리자는 void를 반환하는 메서드를 참조할 수 있으며, Func와 달리 반환값을 기대하지 않습니다.

기본 문법

public delegate void Action<T1, T2, ...>();
  • T1, T2 등은 입력 매개변수의 타입을 나타내며, 최대 16개까지 지정할 수 있습니다.
  • 반환 타입은 void로, 결과값을 반환하지 않는 메서드에서 사용됩니다.

2. Action의 기본 사용법

간단한 예제를 통해 Action을 사용하는 방법을 살펴보겠습니다.

using System;

public class Program
{
    public static void Main()
    {
        Action<string> greet = (name) => Console.WriteLine($"Hello, {name}!");
        greet("Alice");
    }
}

위 코드에서 greet는 문자열 하나를 매개변수로 받는 Action으로, 이름을 받아서 인사를 출력하는 람다식을 할당했습니다. Action<string>string 타입의 인수를 받고 void를 반환하는 메서드를 가리킵니다.

3. 여러 인수를 받는 Action

Action은 다양한 인수 개수를 지원하며, 이를 통해 다수의 매개변수를 전달할 수 있습니다.

예를 들어, 두 개의 정수를 받아 합계를 출력하는 Action<int, int>를 정의할 수 있습니다.

Action<int, int> add = (x, y) => Console.WriteLine(x + y);
add(3, 4);  // 출력: 7

위 예제에서 Action<int, int>는 두 개의 정수형 매개변수를 받으며, 이를 통해 합계를 출력합니다.

4. Func와의 차이점

Action과 유사하게 Func 대리자도 존재하지만, Func는 반환값을 기대할 때 사용됩니다. 반면, Action은 반환값이 필요하지 않은 경우에 주로 사용됩니다.

Func<int, int, int> multiply = (x, y) => x * y;
int result = multiply(3, 4);  // result는 12

위 예제에서 Func<int, int, int>는 두 개의 int 매개변수를 받고 int를 반환합니다. Action과 달리 반환값이 있는 경우 Func를 사용하는 것이 적합합니다.

5. Action의 활용 예제

Action은 다양한 상황에서 활용될 수 있으며, 특히 콜백 함수와 이벤트 핸들링에서 유용하게 쓰입니다.

5.1 콜백 함수로 사용하기

비동기 작업에서 작업이 완료된 후 특정 작업을 수행하는 콜백 함수로 Action을 사용할 수 있습니다.

void PerformAction(int x, Action<int> callback)
{
    // 특정 작업 수행
    int result = x * 2;
    callback(result); // 콜백 함수 호출
}

PerformAction(5, result => Console.WriteLine($"Result: {result}")); // 출력: Result: 10

위 예제에서는 PerformAction 메서드가 비동기 작업을 수행하고, 작업이 완료된 후 결과를 출력하는 콜백을 호출합니다.

5.2 이벤트 핸들러로 사용하기

이벤트 핸들러로 Action을 사용하는 것도 가능합니다. 예를 들어, 특정 조건이 충족될 때 이벤트를 발생시키는 상황에서 Action을 활용할 수 있습니다.

class Button
{
    public Action OnClick { get; set; }

    public void Click()
    {
        OnClick?.Invoke();
    }
}

Button button = new Button();
button.OnClick = () => Console.WriteLine("Button clicked!");
button.Click(); // 출력: Button clicked!

위 예제에서 OnClickAction 타입의 이벤트 핸들러이며, Click 메서드에서 이를 호출합니다.

6. Action을 사용할 때의 주의사항

Action은 간단하고 강력하지만, 다음과 같은 주의사항을 고려해야 합니다.

6.1 Null 참조 주의

Action이 null일 때 호출하면 NullReferenceException이 발생하므로, 호출 전에 null 여부를 항상 확인해야 합니다.

Action action = null;
action?.Invoke();  // 안전하게 호출

6.2 과도한 람다 사용 주의

람다식을 과도하게 사용하면 코드가 복잡해질 수 있습니다. 가능한 간결하게 작성하거나 별도의 메서드로 분리하는 것이 좋습니다. 예를 들어, 다음과 같은 코드는 과도한 람다 사용의 예시입니다:

PerformAction(5, result => {
    if (result > 10) {
        Console.WriteLine("Result is greater than 10");
    } else {
        Console.WriteLine("Result is less than or equal to 10");
    }
});

이 코드는 람다식 내부에서 복잡한 로직을 포함하고 있습니다. 이러한 경우, 코드의 가독성을 높이고 유지 보수를 용이하게 하기 위해 별도의 메서드로 분리하는 것이 좋습니다.

void HandleResult(int result)
{
    if (result > 10) {
        Console.WriteLine("Result is greater than 10");
    } else {
        Console.WriteLine("Result is less than or equal to 10");
    }
}

PerformAction(5, HandleResult);

7. 정리

Action 대리자는 반환값이 필요 없는 메서드를 캡처하는 데 유용한 도구입니다. 주로 콜백 함수나 이벤트 핸들러로 사용되며, 코드의 재사용성과 가독성을 높이는 데 기여할 수 있습니다. Func와의 차이점을 이해하고 적절한 상황에서 Action을 활용하여 더 나은 C# 코드를 작성해 보세요.