brunch

You can make anything
by writing

C.S.Lewis

by 김경민 Apr 25. 2016

소프트웨어 개발자를 위한 Callback의 정석.

콜백이라는 주제로 첫 게시글을 작성하기 이전에, 브런치의 깔끔하고 세련된 디자인과 UI에 감탄하며...

(하준호 멘토님 감사합니당 ♥)






콜백이란것을 공부하면서. 구글링을 통해 찾은 예제를 수도 없이 보았다.

그러나 콜백이 무엇인지에 대해 뚜렷한 정의를 내리지 못한 채 아몰랑. 답답함만을 느끼던 중


결국, 콜백'A가 B를 호출하여 B가 작업을 수행하다 어떤 시점에서 다시 B는 A를 호출, 그 때 A가 정해놓은 작업을 수행'하는 것.



안드로이드 스튜디오에서 세상에서 가장 간단한(수없이 본 예제중 내가 유일하게 이해함) 콜백을 직접 구현해보았다.


아래의 코드는 MainActivity에서 Callee 클래스의 객체를 생성 후, doWork()를 수행한다. Callee의 doWork()내부에서 또다시 Callee2의 객체를 선언하고 Callee2의 doWork()를 수행한다.


각 doWork()메소드 안에서는 자신을 호출한 메소드로 callback을 보내주도록 되어있다. 메소드 작업을 수행하고 콜백을 수행하는 것을 간단한 Log를 찍어 확인해 볼 것이다.


이 때, Callback은 아래와 같이 Interface로 미리 만들어 놓아 Callback 내용을 부르는 메소드 안에서 구현하도록 강제하였다.


public interface Callback {
    void callback();             // Callback 인터페이스 내의 속이 없는 껍데기 함수
}



public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.i("kkm""MainActivity Log");        // Activity 생성 후 가장 먼저 찍힐 Log
        Callee callee = new Callee();               // Callee 객체 생성
        callee.doWork(mCallback);                // Callee 내의 doWork를 호출

    }


    Callback mCallback new Callback() {     // 인터페이스로 정의한 Callback의 내부를

                                                           // 익명객체로 구현.   
        @Override                                      // callee(위에서 설명한 B)가 호출할 콜백 구현은                                                               MainActivity(A)에서 해준다.
        public void callback() {
            Log.i("kkm""callback1");
        }
    };
}



public class Callee {
    public void Callee() {}
    public void doWork(Callback mCallback) {
        Log.i("kkm""Callee doWork() Log");    // 두번 째로 찍힐 Log
        mCallback.callback();                        // 이 시점에서 MainActivity가 지정한 callback                                                             호출. 세 번째 "callback1" Log가 찍히겠지.

        Callee2 callee2 = new Callee2();           // Callee2 클래스 객체 하나 만들고
        callee2.doWork(mCallback2);             // callee2 안의 doWork()수행. 마찬가지로 Callee를

                                                             참조할 수 있도록 Callee에서 구현한 Callback

                                                              인스턴스 변수 mCallback2를 넘겨줌.
    }                                            
    Callback mCallback2 new Callback() {
        @Override
        public void callback() {
            Log.i("kkm""callback2");             // 다섯번 째로 직힐 callback2 Log.
        }
    };
}


public class Callee2 {
    public Callee2() {}
    public void doWork(Callback mCallback) {     // callee로부터 doWork가 호출되면 수행.
        Log.i("kkm""Callee2 doWork() Log");      // 네 번째 Log를 찍고
        mCallback.callback();                            // Callee에서 지정한 callback함수 호출  
    }
}




실행. logcat에서 다음과 같이 Log가 찍힌 것을 볼 수 있었다. 

kkm: ManiActivity Log

kkm: Callee doWork() Log

kkm: callback1

kkm: Callee2 doWork() Log

kkm: callback2


아래의 그림은 Log찍히는 순서를 나타낸 것.




다시한번 정리를 하면,

콜백function이 자신의 일부를 넘기는 행위이다.

즉, A가 B를 호출하는데 B가 A의 일부분을 실행시켜 달라는 소리다.

B가 A가 지정해 놓은 '일부분'을 수행하기 위해 A를 참조해야 하는 데 그 수단으로 위에서 처럼 클래스 자신의 인스턴스 변수를 넘긴 것이고, 호출한 메소드가 자신의 인스턴스 변수를 이용하여 자신의 메소드를 호출할 수 있게 하는 것이다.


끝!

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari