[Java] Java에서 콜백 패턴 구현하기

Date:     Updated:

카테고리:

태그:

Callback 이란?

callback 은 하위 객체가 상위 객체에게 자신의 상태를 알려줄 때 사용하는 개념입니다. C# 에서는 이 콜백을 하게 해주는 delegate라는 녀석이 있습니다. 한국어로 직역하면 대리자 정도로 해석이 됩니다.

이 대리자가 하위 객체에서 상위객체로 자신의 상태를 알려주는 주체가 됩니다. 만약, 필요한 정보가 있다면, 그 정보까지 실어서 보내주게 됩니다.

하지만 Java 에서는 해당 delegate 라는 키워드가 존재하지 않아서, 인터페이스를 활용하여 패턴을 구현해야 합니다.

강의를 할 때 콜백에 대한 내용이 나오면 학생들이 많이 어려워 하는 것 같습니다.

저도 처음에는 엄청 어려웠는데, Callback을 완전히 깨닫게 된게 언제였지를 떠올려보면, Java로 콜백을 구현할 때 였던 것 같습니다.

Java 에서의 콜백 구현

VoidVoidDelegate 구현

Java에서는 콜백을 구현할 때, 인터페이스를 활용하게 됩니다.

우선 인터페이스를 하나 만듭니다.

🗅 interface VoidVoidDelegateImpl

public interface VoidVoidDelegateImpl {  
    public void VoidVoidDelegate();  
}

그 다음 해당 인터페이스를 인자로 받는 함수를 만듭니다. 그리고 해당 객체가 Null 이 아닐 때, 어떤 구현이 들어있는지는 모르지만, 인터페이스의 함수 VoidVoidDelegate 를 실행시킵니다.

(C#에서는 callback?.Invoke() 랑 같습니다.) (이 함수가 static 인 이유는 main 함수가 static 이기 때문에, static 한 main 함수에 올릴려면, 올릴 함수도 static 해야 하기 때문입니다.)

public class Main  
{  
    //여기가 실행부  
    //C의 VoidMain, C#의 Main 클래스랑 같은 역할임  
    public static void main(String[] args)  
    {  
   
    }  
  
    //인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임  
    //인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴  
    //나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함  
    public static void VoidVoidCallback(SomeCallbackInterface _callback)  
    {  
        if(_callback!=null)  
        {  
            _callback.SomeCallback();  
        }  
    }   
}

이제 이 함수를 호출 합니다.

🗅 class Main

public class Main  
{  
    //여기가 실행부  
    //C의 VoidMain, C#의 Main 클래스랑 같은 역할임  
    public static void main(String[] args)  
    {  
  
        //여기서 함수 실행  
        //자바에서는 함수의 인자로 인터페이스를 넣을 수 있음  
        VoidVoidCallback(new SomeCallbackInterface()  
        {  
            @Override  
            public void SomeCallback()  
            {  
               System.out.println("VoidVoidDelegate!");
            }  
        });    
    }  
  
    //인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임  
    //인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴  
    //나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함  
    public static void VoidVoidCallback(VoidVoidDelegateImpl _callback)  
    {  
        if(_callback!=null)  
        {  
            _callback.SomeCallback();  
        }  
    }  
}

이렇게 새로운 인터페이스를 만든 다음에, 구현되어 있지 않고, 정의만 되어 있던 VoidVoidDelegate 함수를 정의해주기만 하면 됩니다.

그러면 _callback.VoidVoidDelegate() 를 실행할 때, 재정의된 행동이 발동 할겁니다.

VoidIntDelegate 구현

자 이제, 반환형이 Void 이고, 인자로 Int 값을 받는 콜백을 구현해 보겠습니다.

🗅 interface VoidIntDelegateImpl

public interface VoidIntDelegateImpl{
	public void VoidIntDelegate(int _int);
}

마찬가지로 함수를 만들어 줍니다.

public class Main  
{  
    //여기가 실행부  
    //C의 VoidMain, C#의 Main 클래스랑 같은 역할임  
    public static void main(String[] args)  
    {  
  
        //여기서 함수 실행  
        //자바에서는 함수의 인자로 인터페이스를 넣을 수 있음  
        VoidVoidCallback(new SomeCallbackInterface()  
        {  
            @Override  
            public void SomeCallback()  
            {  
               System.out.println("VoidVoidDelegate!");
            }  
        });   
    }  
  
    //인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임  
    //인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴  
    //나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함  
    public static void VoidVoidCallback(VoidVoidDelegateImpl _callback)  
    {  
        if(_callback!=null)  
        {  
            _callback.SomeCallback();  
        }  
    }  
  
    public static void VoidIntCallback(VoidIntDelegateImpl _callback)  
    {  
        if(_callback!=null)  
        {  
            _callback.VoidVoidDelegate(10);  
        }  
    }  
}

이 함수에서 매개변수로 10을 던져줍니다. 이렇게 하면 재정의 하는 부분에서, 10이라는 숫자를 인자로 받아서 사용할 수 있습니다.

(C# 에서는 callback?.Invoke(10) 이랑 같은 표현 입니다.)

이제 똑같이, 메인 함수에서 해당 함수를 불러 보겠습니다.

🗅 class Main

public class Main  
{  
    //여기가 실행부  
    //C의 VoidMain, C#의 Main 클래스랑 같은 역할임  
    public static void main(String[] args)  
    {  
  
        //여기서 함수 실행  
        //자바에서는 함수의 인자로 인터페이스를 넣을 수 있음  
        VoidVoidCallback(new VoidVoidDelegateImpl()  
        {  
            @Override  
            public void VoidVoidDelegate()  
            {  
	            System.out.println("VoidVoidDelegate!");
            }  
        });  
        
    /////////////////////////////////////////////////////////
    
        VoidIntCallback(new VoidIntDelegate()  
        {  
            @Override  
            public void VoidIntDelegate(int _int)  
            {  //_int에 10 이라는 정보가 담겨져서 들어올 것임
	            System.out.println("VoidIntDelegate!" + _int);
            }  
        });  
    }  
  
    //인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임  
    //인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴  
    //나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함  
    public static void VoidVoidCallback(VoidVoidDelegateImpl _callback)  
    {  
        if(_callback!=null)  
        {  
            _callback.VoidVoidDelegate();  
        }  
    }  
  
    public static void VoidIntCallback(VoidIntDelegateImpl _callback)  
    {  
        if(_callback!=null)  
        {  
            _callback.VoidIntDelegate(10);  
        }  
    }  
}

이렇게 해주면, Callback!10 이라는 문구가 출력이 됩니다.

Java 카테고리 내 다른 글 보러가기

첫 번째 글입니다 가장 최근 글입니다

댓글 남기기