ES6 Promise.all 오류 처리 방식 정리
문제 상황
대시보드 화면에서 5개의 API를 동시에 호출해야 했다. Promise.all을 사용했는데, 하나의 API만 실패해도 전체가 reject되어 정상적으로 받아온 데이터마저 사용할 수 없었다.
const fetchData = async () => {
try {
const [users, orders, stats, notifications, settings] = await Promise.all([
fetch('/api/users'),
fetch('/api/orders'),
fetch('/api/stats'),
fetch('/api/notifications'),
fetch('/api/settings')
]);
} catch (error) {
// 하나만 실패해도 여기로
console.error(error);
}
};
해결 방법
각 Promise를 catch로 감싸서 실패해도 reject되지 않도록 처리했다.
const fetchData = async () => {
const results = await Promise.all([
fetch('/api/users').catch(err => ({ error: err })),
fetch('/api/orders').catch(err => ({ error: err })),
fetch('/api/stats').catch(err => ({ error: err })),
fetch('/api/notifications').catch(err => ({ error: err })),
fetch('/api/settings').catch(err => ({ error: err }))
]);
const [users, orders, stats, notifications, settings] = results;
// 각각의 성공/실패 여부 확인
if (users.error) {
console.error('Users API failed:', users.error);
}
};
더 나은 방법
반복되는 코드를 줄이기 위해 헬퍼 함수를 만들었다.
const settle = promise =>
promise
.then(data => ({ status: 'fulfilled', data }))
.catch(error => ({ status: 'rejected', error }));
const fetchData = async () => {
const results = await Promise.all([
settle(fetch('/api/users')),
settle(fetch('/api/orders')),
settle(fetch('/api/stats')),
settle(fetch('/api/notifications')),
settle(fetch('/api/settings'))
]);
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
// 성공 처리
} else {
// 실패 로깅
}
});
};
정리
Promise.all은 하나라도 실패하면 전체가 실패한다. 부분적인 실패를 허용하려면 각 Promise에 catch를 추가하거나, 래퍼 함수를 사용해야 한다. ES2020의 Promise.allSettled를 사용하면 이런 패턴이 표준으로 제공되지만, 아직은 직접 구현해서 써야 한다.