콜백 함수는 다른 함수에 인자로 전달되는 함수예요. 그러면 콜백 함수를 호출해서 뒤따르는 동작을 실행할 수 있어요. 콜백은 어떤 작업의 결과를 처리하거나, 이벤트가 발생했을 때 동작을 처리할 때 자주 사용해요. 콜백 함수는 동기 프로그래밍과 비동기 프로그래밍 모두에서 사용할 수 있어요.
const sideLength = 5;
// Caller function takes a callback function
function applySideLength(callback) {
return callback(sideLength);
}
// Callback must expect the possible argument from the calling function
function areaOfSquare(side) {
return side * side;
}
applySideLength(areaOfSquare); // => 25
콜백을 함수 표현식으로 작성할 수도 있어요:
applySideLength(function squarePerimeter(side) {
return side * 4;
});
JavaScript는 한 번에 하나의 함수 호출만 실행할 수 있는 단일 스레드 런타임으로 설계되었기 때문에, 이 패턴은 JavaScript에서 유용해요. 함수가 실행되는 동안에는 그 함수가 반환되기 전까지 런타임이 다른 이벤트에 응답하거나 실행을 이어갈 수 없어요.
많은 API 호출(I/O 함수, 타이머, 이벤트 리스너)은 작업이 끝날 때까지 현재 함수 호출을 잠시 옆으로 밀어 두는 비동기 방식을 사용해요. 작업이 완료되면 콜백 함수가 메시지 큐에 놓이고, 런타임이 함수 호출 사이에 있을 때 이 메시지들이 콜백 함수를 호출함으로써 처리돼요.
콜백 함수는 나중에 호출되는 함수에서는 접근할 수 없는 클로저 스코프의 변수를 참조할 수 있기 때문에 유용하기도 해요.
이벤트 핸들러는 JavaScript에서 콜백의 흔한 사용 사례예요. 'onload'나 'onclick' 같은 브라우저 이벤트는 함수를 호출하도록 트리거할 수 있는 신호예요. DOM [문서 객체 모델 객체의 addEventListener 메서드는 이벤트가 발생했다는 것을 "듣게" 되었을 때 호출할 콜백 함수를 등록해요.
document.addEventListener('onload', function () {
alert('The webpage has now been loaded');
});
Node.js에서는 콜백 함수가 프로그램의 흐름을 제어하기 위한 관례를 따라요. 이 관례는 이런 패턴을 따라요. 콜백 함수의 첫 번째 인자는 Error나 null을 받을 수 있고, 두 번째 이후의 인자는 호출한 함수가 보내도록 설계된 데이터를 받아요.
오류가 발생하면 두 번째 이후의 인자가 없을 수도 있으므로, 그 인자가 있다고 가정하면 안 돼요.
function operation(a, b, callback) {
// Work ...
if (/* an error occurs */) {
return callback(new Error('An error occurred'))
}
// On success:
callback(null, data)
}
function callback(error, returnedData) {
if (error) {
// An error occurred, handle it here.
return
}
// No error occurred, continue with the returned data.
}
operation(1, 2, callback)
비동기 함수를 다루면서 흐름 제어를 도울 때 이 패턴을 자주 보게 돼요.
자주 쓰이는 Array 함수들은 콜백 함수로 동작을 정의해요:
Array.prototype.forEach:
콜백을 받아서, 배열의 각 요소에 콜백을 적용해요.
[1, 2, 3].forEach(function (element) {
doSomething(element);
});
// => doSomething() is invoked 3 times, once with each element
Array.prototype.map
콜백을 받아서, 배열의 각 요소에 콜백을 적용하고 그 결과로 새 배열을 만들어요.
[1, 2, 3].map(function (element) {
return element + 1;
});
// => [2, 3, 4]
Array.prototype.reduce
콜백을 받아서, 배열의 각 요소에 콜백을 적용하고 그 결과를 다음 호출로 넘겨줘요.
[1, 2, 3].reduce(function (runningSum, element) {
return runningSum + element;
}, 0);
// => 6