프로그래밍/C#

Callback

selinatsu 2024. 10. 12. 18:05
반응형

콜백 함수와 직접 호출 방식의 차이

콜백 함수는 특정 작업이 완료된 후 다른 작업을 실행하기 위해 미리 등록된 함수를 호출하는 방식입니다.

일반적으로 이벤트 기반 프로그래밍이나 비동기 작업에서 유용합니다.
반면, 직접 호출 방식은 함수를 순차적으로 호출하는 방식으로, 코드를 단순하게 유지할 수 있지만 작업의 흐름이 고정적입니다.

 

예시 1: 콜백 없이 직접 호출하는 방식

public class WithoutCallback : MonoBehaviour
{
    void Start()
    {
        Task1();
        Task2();
        Task3();
    }

    void Task1()
    {
        Debug.Log("Task 1 Complete");
    }

    void Task2()
    {
        Debug.Log("Task 2 Complete");
    }

    void Task3()
    {
        Debug.Log("Task 3 Complete");
    }
}

 

이 방식에서는 각 작업이 순차적으로 고정된 순서로 실행됩니다.
만약 순서를 바꾸거나 새로운 작업을 추가하고 싶다면 코드를 수정해야 합니다.

 

 

예시 2: 콜백을 사용하는 방식 (delegate 사용)

public class WithCallback : MonoBehaviour
{
    public delegate void TaskCallback();

    void Start()
    {
        TaskCallback callback = Task1;
        callback += Task2;
        callback += Task3;

        ExecuteTasks(callback);
    }

    void ExecuteTasks(TaskCallback callback)
    {
        if (callback != null)
        {
            callback.Invoke();
        }
    }

    void Task1()
    {
        Debug.Log("Task 1 Complete");
    }

    void Task2()
    {
        Debug.Log("Task 2 Complete");
    }

    void Task3()
    {
        Debug.Log("Task 3 Complete");
    }
}

 

콜백을 사용하면 함수들을 동적으로 추가하거나 제거할 수 있습니다.
작업 순서를 쉽게 변경할 수 있으며, 새로운 작업을 추가할 때 기존 코드를 수정할 필요가 없습니다.

 

콜백 없는 호출 방식 vs 콜백을 사용하는 방식

직접 호출 방식과 콜백을 사용하는 방식의 차이는 작업의 유연성에 있습니다.

직접 호출 방식은 고정된 순서로 작업을 실행하는 반면, 콜백 방식은 동적으로 작업을 관리할 수 있습니다.

 

 

직접 호출 방식

public class PizzaOrderWithoutCallback : MonoBehaviour
{
    void Start()
    {
        OrderPizza();
        OrderDrink();
        OrderSide();
    }

    void OrderPizza()
    {
        Debug.Log("Pizza is ready!");
    }

    void OrderDrink()
    {
        Debug.Log("Drink is ready!");
    }

    void OrderSide()
    {
        Debug.Log("Side dish is ready!");
    }
}

 

이 방식에서는 항상 피자 → 음료 → 사이드 순서로 작업이 고정됩니다.
작업을 추가하거나 순서를 변경하려면 코드를 직접 수정해야 합니다.

 

 

콜백을 사용한 방식 (delegate 활용)

public class PizzaOrderWithCallback : MonoBehaviour
{
    public delegate void OrderCallback();

    void Start()
    {
        OrderCallback orderCallback = PreparePizza;
        orderCallback += PrepareDrink;
        orderCallback += PrepareSide;

        ProcessOrder(orderCallback);
    }

    void ProcessOrder(OrderCallback callback)
    {
        if (callback != null)
        {
            callback.Invoke();
        }
    }

    void PreparePizza()
    {
        Debug.Log("Pizza is ready!");
    }

    void PrepareDrink()
    {
        Debug.Log("Drink is ready!");
    }

    void PrepareSide()
    {
        Debug.Log("Side dish is ready!");
    }
}

 

콜백 방식에서는 작업을 동적으로 추가하거나 제거할 수 있습니다.
나중에 새로운 메뉴(디저트)를 추가하고 싶다면, 콜백에 새로운 작업을 등록하기만 하면 됩니다.

 

 

Invoke()와 Coroutine 사용

Invoke()는 일정 시간이 지난 후 함수를 호출하는 방식입니다.

하지만 Coroutine을 사용해서 비동기 작업을 처리하는 방법도 가능합니다.

Invoke() 없이 Coroutine을 사용한 예시를 통해 비동기 작업을 처리하는 흐름을 설명했습니다.

 

직접 호출 방식에서 Coroutine 사용

public class PizzaOrderWithoutCallback : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(OrderPizza());
        OrderDrink();  // 피자가 끝나기 전에 음료 준비
        OrderSide();   // 음료 끝나기 전에 사이드 준비
    }

    IEnumerator OrderPizza()
    {
        Debug.Log("Starting Pizza...");
        yield return new WaitForSeconds(3.0f);  // 피자 준비 시간이 3초 걸린다고 가정
        Debug.Log("Pizza is ready!");
    }

    void OrderDrink()
    {
        Debug.Log("Drink is ready!");
    }

    void OrderSide()
    {
        Debug.Log("Side dish is ready!");
    }
}

 

이 방식에서는 피자가 준비되기 전에 음료와 사이드가 바로 준비된 것으로 처리됩니다.

 

 

콜백과 Coroutine을 함께 사용한 비동기 처리

public class PizzaOrderWithCallback : MonoBehaviour
{
    public delegate void OrderCallback();

    void Start()
    {
        OrderCallback orderCallback = PrepareDrink;
        orderCallback += PrepareSide;

        // 조건에 따라 디저트를 추가
        bool wantDessert = true;
        if (wantDessert)
        {
            orderCallback += PrepareDessert;
        }

        StartCoroutine(PreparePizza(orderCallback));
    }

    IEnumerator PreparePizza(OrderCallback callback)
    {
        Debug.Log("Starting Pizza...");
        yield return new WaitForSeconds(3.0f);
        Debug.Log("Pizza is ready!");

        if (callback != null)
        {
            callback();
        }
    }

    void PrepareDrink()
    {
        Debug.Log("Drink is ready!");
    }

    void PrepareSide()
    {
        Debug.Log("Side dish is ready!");
    }

    void PrepareDessert()
    {
        Debug.Log("Dessert is ready!");
    }
}

 

콜백 방식은 비동기 작업이 끝난 후 처리할 작업들을 동적으로 등록할 수 있습니다.
작업이 비동기적으로 처리되면서, 필요에 따라 후속 작업을 추가하거나 제거할 수 있습니다.

 

콜백 방식의 유연성 및 확장성

콜백 방식의 가장 큰 장점은 작업을 동적으로 관리할 수 있다는 점입니다. 특정 조건에 따라 추가 작업을 할지 말지 결정할 수 있고, 작업 순서를 자유롭게 변경할 수 있습니다.

 

직접 호출 방식과 콜백 방식의 차이

PrepareDessert();와 orderCallback += PrepareDessert;의 차이는 작업 흐름을 동적으로 관리할 수 있는 유연성에 있습니다.
직접 호출 방식은 코드가 고정되어 있어, 새로운 작업을 추가하거나 조건에 따라 처리해야 할 때 코드를 계속 수정해야 합니다.
반면에, 콜백 방식은 조건에 따라 작업을 동적으로 추가하거나 삭제할 수 있어 확장성과 유지보수성이 뛰어납니다.

 

조건에 따라 작업을 동적으로 관리하는 방식

public class PizzaOrderWithConditionalCallback : MonoBehaviour
{
    public delegate void OrderCallback();

    void Start()
    {
        // 기본 작업 등록
        OrderCallback orderCallback = PrepareDrink;
        orderCallback += PrepareSide;

        // 조건에 따라 디저트를 추가
        bool wantDessert = true;
        if (wantDessert)
        {
            orderCallback += PrepareDessert;
        }

        StartCoroutine(PreparePizza(orderCallback));
    }

    IEnumerator PreparePizza(OrderCallback callback)
    {
        Debug.Log("Starting Pizza...");
        yield return new WaitForSeconds(3.0f);
        Debug.Log("Pizza is ready!");

        // 콜백으로 등록된 작업 실행
        if (callback != null)
        {
            callback();
        }
    }

    void PrepareDrink()
    {
        Debug.Log("Drink is ready!");
    }

    void PrepareSide()
    {
        Debug.Log("Side dish is ready!");
    }

    void PrepareDessert()
    {
        Debug.Log("Dessert is ready!");
    }
}

 

이 방식에서는 필요에 따라 작업을 동적으로 추가할 수 있습니다.
프로젝트가 커지거나 요구사항이 변경될 때, 기존 코드를 수정하지 않고도 작업을 쉽게 관리할 수 있습니다.

 

콜백의 필요성에 대한 결론

작은 프로젝트나 간단한 작업 흐름에서는 직접 호출 방식이 더 직관적이고 간편합니다.
하지만 복잡한 작업 흐름에서, 특히 비동기 작업과 조건에 따른 작업 처리가 필요한 경우에는 콜백과 delegate가 필수적일 수 있습니다.
콜백 방식은 작업을 동적으로 관리할 수 있어, 유연성과 확장성이 뛰어나며, 큰 프로젝트에서 유지보수가 용이합니다.

 

 

 

반응형

'프로그래밍 > C#' 카테고리의 다른 글

event 그리고 delegate, Action  (0) 2024.10.12
Action  (0) 2024.10.12
event 와 delegate  (0) 2024.10.12
delegate  (1) 2024.10.12
Interface  (1) 2024.10.10