: 출처 : 문학청년 블로그

개요

콜백(Callback)이란 디자인 패턴 중 하나인 옵저버(Observer) 패턴에서 나온 개념으로써 객체의 상태 변화(이벤트)가 발생 하였을 경우에 이러한 사실을 함수를 통해 전달하게 되는데, 이를 콜백 함수라고 한다. 자바스크립트에서 콜백 함수는 키보드나 마우스 클릭과 같은 디바이스 이벤트 뿐만이 아니라 Ajax, 데이터 처리 등 많은 부분에서 사용되고 있다.

이번 강좌에서는 콜백 함수의 기본적인 사용 방법과 좀 더 활용할 수 있는 방법에 대해 알아볼 것이다.
 

기초

출근을 위해 반드시 오전 8시에 일어나야 한다고 가정해보자. 그렇다면 어떻게 일어나야 할까? 첫 번째 방법으로는 생각날 때마다 현재 시간을 확인하는 것이다. 하지만 이 방법은 매우 좋지 않다. 수 없이 현재 시간을 확인해야 될 뿐더러 계속 신경써야 하기 때문에 쉽게 피곤해질 수 있다. 만약에 오전 8시를 알려주는 알람 시계가 있다면 이러한 문제는 해결된다. 주기적으로 현재 시간을 확인하지 않아도 되기 때문에 신경쓰지 않고 푹 잘 수 있다.

콜백 함수는 시계의 알람 기능과 비슷하다고 생각하면 이해하기가 조금 더 쉬울 것이다. (Link)

위의 예제에 정의된 alram 함수는 사용자가 정한 Minutes에 알림 메시지를 보여주는 함수이다. 콜백 함수는 특정 기능을 수행하기 위한 로직과 기능 수행 후 반환되는 결과 값을 가지고 이를 표현하는 로직을 서로 분리 할 수 있다. 이는 뷰(View)의 분리라는 점에서 MVC 패턴과 비슷하다고 볼 수 있다.

최근에 대세가 되버린 jQuery 라이브러리에서 제공하는 많은 함수들의 결과 값이 콜백 형태로 호출된다. 이런 함수들은 이벤트 처리, 애니메이션, Ajax, 콜렉션 등에서 사용된다. 콜백으로 결과 값을 반환하는 함수들은 공통적인 특징이 하나 있는데, 그것은 바로 뷰(View)를 처리하는 시점이 모호하다는 것이다.

 위의 예제를 실행해보면 undefined 값이 출력 된다. $.getJSON 함수가 먼저 호출되더라도 결과 값은 alert 함수보다 늦게 가져오기 때문에 undefined 값이 출력되는 것이다. 물론 약간의 시간 차이를 두어 값을 받을 수도 있다.

 하지만 모두 시간 차이를 두어서 구현할 수는 없다. 가독성이 떨어질 뿐더러 Ajax 호출의 경우 네트워크 상황에 따라 값을 제대로 가지고 오지 못하는 경우도 발생할 수 있다.
 

심화

특정 함수의 반환 값을 콜백으로 넘기는 방법은 위의 예제들을 보면 알 수 있듯이 그렇게 어렵지 않다. 매개 변수를 통해 함수를 받고, 그 함수를 통해 결과 값을 다시 호출하면 되기 때문이다. 하지만 jQuery에서 제공되는 함수들을 보면 단순히 콜백을 통해 결과 값을 넘기지 않는다.

jQuery $.each 함수는 해당 배열의 요소들을 모두 순환하면서 콜백으로 index 값을 넘기는데 이 요소를 콜백 함수의 매개 변수로 넘기지 않고 함수 내에서 this 키워드로 접근한다.

위의 예제를 보면 this 키워드를 통해 test 배열에 포함되어 있는 요소(객체)들을 접근하고, name이란 프로퍼티를 출력하였다. 하지만 어떻게 콜백 함수 안에서 this 키워드를 사용하여 name 프로퍼티를 출력할 수 있었을까?

답을 말하기에 앞서 우선 아래 예제를 보자. (Link)

위의 함수는 매개 변수로 받은 배열을 순차적으로 접근하여 콜백을 통해 각각의 배열 요소들을 넘겨주는 함수를 구현한 것이다. 하지만 현재 위치의 요소를 콜백 함수의 파라메터로 넘겼을 뿐, 콜백 함수 내에서 this로 접근하지는 못한다.

그럼, 콜백 함수 내에서 this 값이 무엇이 찍히는지 확인해보자.

위의 예제를 실행해보면 “[object Window]“라는 메시지가 3번 출력될 것이다. 자바스크립트에서 함수는 정의될 때, 기본적으로 Window 객체의 메소드가 되기 때문에 콜백 함수 내에서 this는 Window 객체가 되는 것이다.

그렇다면 콜백 함수 내에서 배열 요소를 this로 접근하기 위해서는 어떻게 해야 될까? 먼저 이전 강좌에서 다룬 prototype를 사용하여 콜백 함수의 원형을 배열 요소로 변경해주면 된다.

자바스크립트 함수는 클래스이며 자신의 원형을 prototype로 정할 수 있다. 즉, 매개 변수를 통해 받은 콜백 함수는 name 프로퍼티를 가진 객체 자체가 되는 것이다. 하지만 prototype으로 자신의 원형을 해당 배열 요소로 정했다고는 하지만 단순한 콜백 함수 호출로는 콜백 함수 내에서 this 키워드로 접근 할 수 없다.

왜냐하면 자바스크립트 함수는 앞서 말한 것처럼 기본적으로 Window 객체이기 때문이다. 그렇다면 자신만의 고유한 객체가 되기 위해선 어떻게 해야 될까? 그건 바로 new 키워드를 사용하면 된다.

 이유를 설명하기에 앞서 아래 예제를 보자.

위의 예제의 출력 메시지는 “test1 : [object Window]“, “test2 : [object Object]“이다. 앞서 말한 것처럼 자바스크립트 함수는 클래스이기도 하기 때문에 고유한 객체(인스턴스)를 생성할 수 있다. 즉, new 키워드를 사용하여 콜백 함수를 호출하면 Window 객체가 아닌 새로운 객체가 되는 것이다. 단순하게 new 키워드 사용 유무를 “non-static / static” 개념이라고 생각하면 이해하기 쉬울 것이다. 
(본 강좌에서는 static에 대한 설명은 하지 않겠음)

마지막으로 아래 예제는 이때까지 고대해왔던 완성된 each 함수이다. (Link)

 

+ Recent posts