자바스크립트에서의 Promise Hell 문제
여러분도 알고 계시듯이, 프로미스는 callback hell 문제를 해결하기 위해 만들어졌습니다. 하지만 시간이 지나면서, 프로미스 역시 복잡한 코드를 만들어낼 수 있다는 것이 드러났습니다. 이러한 문제는 유사하게 promise hell이라고 불리게 되었습니다.
코드 예제를 통해 이 문제를 살펴보겠습니다.
매개변수를 받아 그 매개변수에 따라 결과를 반환하는 함수 getSmth가 있다고 가정해 봅시다:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
이 경우, 우리는 (예를 들어 서버에서 데이터를 가져오는 것과 같은) 어떤 유용한 작업을 시뮬레이션하고 있습니다. 시뮬레이션을 위해, 우리는 단순히 숫자를 매개변수로 전달하고 1초 후 그 숫자의 제곱을 반환합니다.
이제 우리의 getSmth 함수를 다른 함수 안에서 사용해 보겠습니다:
function func() {
getSmth(2).then(res => {
console.log(res); // 4를 출력합니다
});
}
func();
첫 번째 문제
연속적으로 이어지는 많은 then 구조는 코드 이해를 어렵게 만듭니다:
function func(){
getSmth(2).then(res1 => {
// 어떤 작업을 합니다
}).then(res2 => {
// 어떤 작업을 합니다
}).then(res3 => {
// 어떤 작업을 합니다
}).then(res4 => {
// 어떤 작업을 합니다
}).then(res5 => {
// 어떤 작업을 합니다
}).then(res6 => {
// 어떤 작업을 합니다
});
}
func();
두 번째 문제
또 다른 유형의 문제도 있습니다. 이제 우리가 이 함수를 두 번 사용한 다음 결과를 합산하고 싶다고 가정해 봅시다. 결과적으로 다음과 같은 코드가 만들어집니다:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // 13을 출력합니다
});
});
}
func();
이미 callback hell을 닮지 않았나요? 함수 호출을 하나 더 추가하면 코드는 더욱 나빠질 것입니다:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
물론 Promise.all을 사용할 수 있습니다:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
하지만, 우리가 똑같은 결과를 얻었을까요? 아닙니다! 첫 번째 경우에는 각 새로운 함수가 이전 프로미스의 완료를 기다리는 반면, 두 번째 경우에는 모든 프로미스가 동시에 실행됩니다. 이 차이는 우리가 이전 호출의 결과를 다음 함수에 전달하고 싶을 때 매우 중요해질 것입니다:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();