우리가 흔히 생각하는 일반적인 함수란 입력(파라미터)가 있고, 출력(리턴값)이 있다.
하지만 자바스크립트에서는 출력값이 없고 그 대신에 콜백 함수를 입력받는 함수들이 많이 있다. 콜백함수는 다른 함수에 인자로 넘어가서 실행될 로직을 담게 된다.
function findUserAndCallBack(id, cb) {
const user = {
id: id,
name: "User" + id,
email: id + "@test.com",
}
cb(user)
}
findUserAndCallBack(1, function (user) {
console.log("user:", user)
})
findUserAndCallBack()
함수의 호출부를 보면 두번째 인자로 콜백 함수를 선언하며 넘겼다. 따라서 후에 findUserAndCallBack()
함수가 실행될때 cb
매개 변수는 콜백 함수는 할당 받으며,
cb(user)
가 실행될때, 이 콜백 함수가 실행되게 된다.
자바스크립트에서는 함수도 숫자나 문자처럼 변수에 할당할 수 있는 하나의 값이기 때문에 콜백함수를 다른 함수의 인자로 넘기는 것은 매우 자연스러운 현상이다.
비동기(Asynchronous) 함수란 쉽게 설명하면 호출부에서 실행 결과를 기다리지 않아도 되는 함수이다. 반대로 동기 함수(Synchronous) 함수는 호출부에서 실행 결과가 리턴될때까지 기다려야 하는 함수이다.
비동기 함수의 이러한 Non-blocking 이점 때문에, 자바스크립트처럼 싱글쓰레드 환경에서 실행되는 언어에서 광범위하게 사용된다. 비동기 함수를 사용하면 로직을 순차적으로 처리할 필요가 없기 때문에 동시 처리에서도 동기 함수 대비 유리한 것으로 알려져 있다.
자바스크립트에는 setTimeout
이라는 대표적인 내장 비동기 함수가 있다. setTimeout
은 두 개의 매개 변수를 받는데, 첫번째는 실행할 작업 내용을 담은 콜백 함수이고, 두번째는 이 콜백 함수를 수행하기 전에 기다리는 밀리초 단위 시간이다. 즉, setTimeout
함수는 두번째 인자로 들어온 시간 만큼 기다린 후에 첫번째 인자로 들어온 콜백 함수를 실행해준다.
function findUserAndCallBack(id, cb) {
setTimeout(function () {
console.log("waited 0.1 sec.")
const user = {
id: id,
name: "User" + id,
email: id + "@test.com",
}
cb(user)
}, 100)
}
findUserAndCallBack(1, function (user) {
console.log("user:", user)
})
waited 0.1 sec.
user: {id: 1, name: "User1", email: "1@test.com"}
findUserAndCallBack()
함수의 2번째 인자로 결과값을 더해 결과값을 이용해서 실행될 로직을 넘겼고,
setTimeout()
함수는 0.1초 후에 이 콜백 함수를 호출하였다. 이와 같이 비동기 함수를 호출할 때는 결과값을 리턴 받으려고 하지말고, 결과값을 통해 처리할 로직을 콜백 함수로 넘기는 스타일로 코딩을 해줘야 예상된 결과를 얻을 수 있다.
하지만 자바스크립트 프로젝트가 점점 더 복잡해지면서 최근에는 콜백 함수를 인자로 넘겨서 비동기 처리를 하는 스타일을 피하는 추세이다. 왜냐하면 많은 개발자들이 콜백 지옥이라고 불리는 끔찍한 상황을 겪게 되었고 최근에는 Promise나 async/await를 이용하는 방법들로 대체되고 있기 때문이다.