실제로 콜백 지옥(Callback Hell)은 매우 빈번하게 발생하게 됩니다. 아래의 예시들을 통해 알아봅시다.
setTimeout(() => {
document.body.style.backgroundColor = 'red'
}, 1000)
setTimeout(() => {
document.body.style.backgroundColor = 'orange'
}, 2000)
setTimeout(() => {
document.body.style.backgroundColor = 'yellow'
}, 3000)
위와 같이 setTimeout
함수를 통해 1초마다 배경색이 변하는 코드를 작성하였습니다. 그러나 이 코드는 매번 시간을 계산해야한다는 단점이 있습니다. 이를 개선하기 위해 nesting을 해보도록 합시다.
setTimeout(()=>{
document.body.style.backgroundColor = 'red'
setTimeout(()=>{
document.body.style.backgroundColor = 'orange'
setTimeout(()=>{
document.body.style.backgroundColor = 'yellow'
setTimeout(()=>{
document.body.style.backgroundColor = 'green'
setTimeout(()=>{
document.body.style.backgroundColor = 'blue'
setTimeout(()=>{
document.body.style.backgroundColor = 'navy'
setTimeout(()=>{
document.body.style.backgroundColor = 'purple'
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
이번엔 함수의 nesting을 통해서 직접 시간을 계산하지 않아도 되는 코드를 작성하였습니다. 하지만 여기서의 문제점은 같은 함수가 너무 많이 중복이 되어있다는 점입니다. 또 이번엔 이를 해결해볼까요?
const delayedColorChange = (newColor, delay, doNext) => {
setTimeout (() => {
document.body.style.backgroundColor = newColor
doNext && doNext()
}, delay)
}
delayedColorChange('red', 1000, () => {
delayedColorChange('orange', 1000, () => {
delayedColorChange('yellow', 1000, () => {
delayedColorChange('green', 1000, () => {
delayedColorChange('blue', 1000, () => {
})
})
})
})
})
이렇게 delayedColorChange
라는 함수를 정의해서 별도로 호출만 진행하면 될 수 있도록 코드를 작성하였습니다. 위의 코드보다 훨씬 간결한 것을 확인할 수 있습니다. 여기서 이 함수의 세번째의 매개변수를 보시면 doNext
가 있고 그 함수 안에는 doNext()
라는 본인을 호출하는 함수가 있습니다. 이것이 바로 아시다시피 재귀 함수입니다.
그러나 이또한 매우 여러번의 nesting으로 인해서 굉장히 복잡하다고 생각이 드실 겁니다. 이것이 바로 콜백 지옥(Callback Hell)입니다.
searchMoviesAPI('amadeus', () => {
saveToMyDB(movies, () => {
// if it works, run this
}), () => {
// if it doesn't work, run this
}, () => {
// if API is down, or requests failed
}
})
실제로 위와 같은 코드가 매우 자주 사용됩니다. API에게 요청을 하여, 데이터를 받아오고 API 요청이 제대로 됐다면 나의 DB에 저장합니다. 그러나 이러한 일이 반드시 될 것이란 보장이 없겠죠?
API가 다운이 될 수도, 요청이 실패할 수도 그리고 내 DB에 저장하는 도중에 갑자기 오류가 발생할 수도 있습니다. 이러한 상황에서 콜백 지옥(Callback Hell)은 무수히 많이 일어나게 됩니다.
이러한 일은 JavaScript는 싱글 스레드로 작동하며, 한 번에 하나씩만 처리할 수 있는 로직으로 만들어져있기 때문입니다. 따라서 우리는 코드의 실행을 지연(delay)하기 위해 WebAPI를 통해 콜백(Callback)을 사용해야만 합니다. 그러므로 이렇게 코드가 복잡해지는 것이죠.
그러나 다행히도 이러한 콜백 지옥(Callback Hell)을 쉽게 해줄 수 있도록 최신의 JavaScript의 버전에서는 promise와 async function이라는 개념을 사용할 수 있게 되었습니다. 다음 시간부터는 이에 대해 알아보도록 합시다.