Promise.all과 Promise.race 실무 활용 사례
문제 상황
대시보드 페이지에서 사용자 정보, 통계 데이터, 최근 활동 로그 등 5개의 API를 호출해야 했다. 순차적으로 호출하니 초기 로딩 시간이 3초 이상 걸렸다.
Promise.all 적용
const fetchDashboard = async () => {
try {
const [user, stats, logs, notifications, settings] = await Promise.all([
fetch('/api/user'),
fetch('/api/stats'),
fetch('/api/logs'),
fetch('/api/notifications'),
fetch('/api/settings')
]);
return {
user: await user.json(),
stats: await stats.json(),
logs: await logs.json(),
notifications: await notifications.json(),
settings: await settings.json()
};
} catch (error) {
console.error('Dashboard fetch failed:', error);
}
};
병렬 처리로 로딩 시간을 1.2초로 단축했다. 하지만 하나의 API가 실패하면 전체가 실패하는 문제가 있었다.
부분 실패 허용하기
필수 데이터와 선택 데이터를 구분해서 처리했다.
const fetchDashboardSafe = async () => {
const results = await Promise.all([
fetch('/api/user').catch(e => null),
fetch('/api/stats').catch(e => null),
fetch('/api/logs').catch(e => null)
]);
return results.filter(r => r !== null);
};
Promise.race 활용
API 타임아웃 구현에 Promise.race를 사용했다.
const fetchWithTimeout = (url, timeout = 5000) => {
return Promise.race([
fetch(url),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), timeout)
)
]);
};
결론
Promise.all은 성능 개선에 효과적이지만 에러 핸들링을 신중하게 설계해야 한다. 각 Promise에 catch를 붙이거나, allSettled 폴리필을 고려할 필요가 있다.