Promise.all 사용 시 일부 실패 처리 패턴

문제 상황

대시보드 페이지에서 여러 통계 API를 동시에 호출하는 코드를 작성했다. Promise.all을 사용했는데, 한 API가 실패하면 전체 페이지가 에러 상태가 되는 문제가 발생했다.

const results = await Promise.all([
  fetchUserStats(),
  fetchSalesData(),
  fetchTrafficData()
]);

통계 중 하나가 실패해도 나머지는 보여주는 게 사용자 경험상 더 나았다.

해결 방법

1. Promise.allSettled 폴리필

Node 10에서는 아직 지원하지 않아서 직접 구현했다.

const allSettled = promises => 
  Promise.all(
    promises.map(p => 
      Promise.resolve(p)
        .then(value => ({ status: 'fulfilled', value }))
        .catch(reason => ({ status: 'rejected', reason }))
    )
  );

const results = await allSettled([
  fetchUserStats(),
  fetchSalesData(),
  fetchTrafficData()
]);

const succeeded = results
  .filter(r => r.status === 'fulfilled')
  .map(r => r.value);

2. 기본값 제공

각 Promise를 catch로 감싸서 실패 시 기본값을 반환하도록 했다.

const [userStats, salesData, trafficData] = await Promise.all([
  fetchUserStats().catch(() => null),
  fetchSalesData().catch(() => ({ total: 0, items: [] })),
  fetchTrafficData().catch(() => null)
]);

if (userStats) {
  renderUserStats(userStats);
}

선택 기준

  • 필수 데이터: Promise.all 사용, 하나라도 실패하면 에러 처리
  • 선택 데이터: allSettled 패턴이나 catch로 기본값 제공
  • 로깅 필요: allSettled로 실패 이유 기록

대시보드처럼 여러 독립적인 데이터를 보여주는 경우 두 번째 방식이 간단하고 실용적이었다.

Promise.all 사용 시 일부 실패 처리 패턴