JavaScript 비동기 흐름 제어: Promise.all, Promise.race 활용법

비동기 프로그래밍은 현대 JavaScript 개발에서 필수적인 요소입니다. 특히, 여러 비동기 작업을 동시에 처리해야 할 때 Promise.all과 Promise.race는 매우 유용합니다. 이번 글에서는 이 두 메서드의 활용법을 자세히 살펴보겠습니다.

 

Promise.all

Promise.all은 여러 개의 프로미스를 병렬로 처리하고, 모든 프로미스가 완료되면 하나의 프로미스를 반환합니다. 다음은 Promise.all의 기본적인 사용 예제입니다:

const promise1 = fetch('/api/data1');
const promise2 = fetch('/api/data2');
const promise3 = fetch('/api/data3');

Promise.all([promise1, promise2, promise3])
  .then((responses) => {
    return Promise.all(responses.map(response => response.json()));
  })
  .then((data) => {
    console.log('All data fetched:', data);
  })
  .catch((error) => {
    console.error('Error fetching data:', error);
  });

위 예제에서 fetch로 데이터를 가져오는 세 개의 비동기 작업을 Promise.all로 묶어서 처리합니다. 모든 요청이 완료되면 응답을 JSON으로 파싱 하여 결과를 출력합니다. 하나의 프로미스라도 실패하면 catch 블록으로 이동합니다.

 

Promise.race

Promise.race는 가장 먼저 완료된 프로미스를 반환합니다. 주로 타임아웃 설정이나 여러 소스 중 빠른 응답을 선택할 때 사용됩니다.

const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'Fast'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 1000, 'Slow'));

Promise.race([promise1, promise2])
  .then((result) => {
    console.log('First completed:', result);
  })
  .catch((error) => {
    console.error('Error:', error);
  });

이 예제에서는 두 개의 타이머 프로미스를 사용하여 먼저 완료된 프로미스의 결과를 반환합니다. promise1이 더 빠르게 완료되므로 "First completed: Fast"가 출력됩니다.

 

실전 활용 예제

다음은 Promise.all과 Promise.race를 결합하여 API 요청을 더 효율적으로 처리하는 예제입니다:

const fetchWithTimeout = (url, timeout = 3000) => {
  const fetchPromise = fetch(url).then(response => response.json());
  const timeoutPromise = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Timeout')), timeout)
  );

  return Promise.race([fetchPromise, timeoutPromise]);
};

const urls = ['/api/data1', '/api/data2', '/api/data3'];

Promise.all(urls.map(url => fetchWithTimeout(url)))
  .then((data) => {
    console.log('All data fetched within timeout:', data);
  })
  .catch((error) => {
    console.error('Error fetching data:', error);
  });

여기서는 fetchWithTimeout 함수를 통해 각 요청에 타임아웃을 설정하고, Promise.all을 사용하여 모든 요청이 완료될 때까지 기다립니다. 타임아웃 내에 모든 요청이 완료되면 데이터를 출력하고, 하나라도 실패하면 에러를 처리합니다.

 

결론

Promise.all과 Promise.race는 비동기 작업을 효과적으로 관리할 수 있는 강력한 도구입니다. 각 메서드의 특성을 잘 이해하고 적절히 활용하면 더 견고하고 효율적인 코드를 작성할 수 있습니다. 다양한 상황에서 이 두 메서드를 사용해 보고, 자신의 프로젝트에 맞는 최적의 비동기 흐름 제어 방법을 찾아보세요^^.