
함수에 파라미터로 들어가는 함수로, 순차적으로 실행하고 싶을 때 사용한다. 콜백 함수는 다른 함수에 전달되어 특정 이벤트가 발생하거나 비동기 작업이 완료되었을 때 실행되는 함수이다. 꼭 파라미터 내부에서 함수 선언 안해도 된다. 다른 곳에 만든 함수도 콜백 함수로 넣을 수 있다. 콜백 함수가 필요한 함수들에만 사용이 가능하다.
콜백 함수는 호출하는 시점을 스스로 판단해서 실행한다.
콜백 함수를 호출할 때 해당 함수가 요구하는 매개변수와 순서를 따라야 한다. 순서를 따르지 않고 코드를 작성하면 예기치 않은 동작이 발생할 수 있다.
콜백 함수가 사용되는 컨텍스트에서 this는 기본적으로 전역 객체를 참조한다. 사용자 임의로 this를 바꾸고 싶은 경우는 bind() 메서드를 사용하여 원하는 객체에 명시적으로 바인딩할 수 있다.
setTimeout(function() {
console.log('1초 후에 출력돼요');
}, 1000);
// 1초 후에 함수를 실행하는 함수
다른 함수(A)의 인자로 콜백함수(B)를 전달하면, A가 B의 제어권을 갖게 된다.
특별한 요청(bind)이 없는 한 A에 미리 정해놓은 방식에 따라 B를 호출한다.
(미리 정해놓은 방식이란 어떤 시점에 콜백을 호출할지, 인자에는 어떤 값들을 지정할지, this에 무엇을 바인딩할지 등)
콜백 함수로 전달되는 것은 함수이며, 객체의 메소드로 전달되는 경우에도 결국 함수로 실행된다. 콜백 함수는 객체의 메소드로 전달될 수도 있다. 이 때 this의 참조는 해당 객체가 된다.
콜백 함수를 객체의 메소드로 전달하려는 경우에는 bind()를 사용하거나 thisArg 대신에 객체를 넘겨주는 방식을 사용한다. 이를 통해 콜백 함수 내에서 올바른 this 참조를 유지할 수 있다.
콜백 지옥(CallBack Hell)은 비동기 작업을 처리할 때 콜백 함수를 중첩하여 사용하면서 발생하는 코드의 가독성과 유지보수성이 저하되는 현상이다. 자바스크립트에서 흔히 발생하는 문제이다.
주로 이벤트 처리나 서버 통신과 같이 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장하곤 하는데, 가독성이 떨어질뿐더러 코드를 수정하기도 어렵다. 익명의 콜백 함수를 모두 기명함수로 전환하면 가독성을 높일 수 있다.
Promise -> thenES6의 Promise -> then 으로 해결 가능하다.
Promise를 활용하여 비동기 작업을 처리하고, then 메서드를 이용하여 작업이 완료되었을 때 실행할 코드를 체이닝하는 방식이다. 콜백 지옥을 피할 수 있고, 코드의 가독성을 높인다.
GeneratorES6의 Generator 함수를 실행하면 Iterator가 반환되고, Iterator는 next라는 메서드를 갖는다. next 메서드를 호출하면 Generator 함수 내부에서 가장 먼저 등장하는 yield에서 함수의 실행을 멈춘다.
(비동기 작업이 완료되는 시점마다 next메서드를 호출한다면 순차적인 코드 진행이 가능하다.)
async/awaitES2017의 async/await은 가독성이 뛰어나면서 작성법도 간단한 기술이다. Promise를 더 쉽게 다룰 수 있게 한다. 비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고, 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 표기하면 이후 내용을 promise로 자동 전환하고, 내용이 resolve된 이후에 다음으로 진행한다.
코어 자바스크립트 4강 콜백 함수
Q. 예시의 코드를 실행할 때, 콘솔에 출력될 값과 그 이유를 설명해 주세요.
// 1번
let num = 1;
// 2번
setTimeout(() => {
num = 2;
}, 0);
// 3번
num = 3;
// 4번
console.log(num);
A. 2가 출력될 것이다. setTimeout()함수는 비동기 함수이므로 콜백 함수가 현재 코드 실행 흐름을 상관없이, 설정 시간(0ms) 이후에 실행된다. 그렇기 때문에 1번에서 num 변수를 1로 초기화하고, 2번에서 setTimeout() 함수가 호출되고, 3번에서 num이 3으로 변경되고, 모든 코드가 실행된 후에 setTimeout()의 콜백 함수가 실행되어서 num이 다시 2로 변경된다. 4번의 console.log(num) 에서 num 변수의 값인 2가 출력된다.