학습
JavaScript Promise.all과 Promise.race
JavaScript Promise.all과 Promise.race — 중급
Promise.all과 Promise.race
1. 도입 (왜 배워야 하는가)
JavaScript는 비동기 프로그래밍을 지원하는 언어로, 웹 개발에서 사용자 경험을 높이기 위해 비동기 작업을 효과적으로 처리하는 것이 매우 중요합니다. Promise는 이러한 비동기 작업을 관리하는 데 도움을 주는 객체입니다. 특히 Promise.all과 Promise.race는 여러 개의 Promise를 동시에 처리할 수 있는 방법을 제공합니다.
이 두 가지를 모르면, 여러 비동기 작업을 효율적으로 관리하지 못해 코드가 복잡해지고, 예기치 않은 동작을 초래할 수 있습니다. 예를 들어, 여러 API 호출을 동시에 해야 할 때, 각 호출의 결과를 기다리지 않고 처리하면 시간이 절약되고 성능이 향상됩니다.
2. 핵심 개념 설명
Promise.all
Promise.all은 여러 개의 Promise를 배열로 받아, 모든 Promise가 성공적으로 완료될 때까지 기다립니다. 모든 Promise가 성공적으로 완료되면, 그 결과를 배열로 반환합니다. 하나라도 실패하면 전체가 실패합니다.
비유: 여러 친구와 함께 음식을 주문하는 상황을 상상해 보세요. 모든 친구가 주문한 음식이 도착해야 식사를 시작할 수 있습니다. 하나라도 음식을 잊어버리면 모두 기다려야 하죠.
Promise.race
Promise.race는 여러 개의 Promise 중 가장 먼저 완료된 Promise의 결과를 반환합니다. 다른 Promise들이 완료될 때까지 기다리지 않습니다.
비유: 여러 경주자가 동시에 출발하여, 가장 먼저 결승선을 통과한 선수의 결과만 확인하는 상황입니다. 누가 가장 빨리 도착했는지만 중요하죠.
| 용어 | 설명 |
|---|---|
| Promise | 비동기 작업의 완료 또는 실패를 나타내는 객체 |
| Promise.all | 모든 Promise가 완료될 때까지 기다리며, 모든 결과를 배열로 반환 |
| Promise.race | 가장 먼저 완료된 Promise의 결과만 반환 |
3. 기본 코드 예제
Promise.all 사용 예제
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'foo'));
const promise3 = new Promise((resolve, reject) => setTimeout(reject, 100, 'error'));
Promise.all([promise1, promise2, promise3])
.then((values) => console.log(values))
.catch((error) => console.error(error));
실행 결과:
error
동작 설명:
promise1은 즉시 완료되며 3을 반환합니다.promise2는 100ms 후에 'foo'를 반환합니다.promise3은 100ms 후에 실패하고 'error'를 반환합니다.Promise.all은 하나라도 실패하므로 catch 블록이 실행되고, 'error'가 출력됩니다.promise1은 500ms 후에 'First'를 반환합니다.promise2는 100ms 후에 'Second'를 반환합니다.Promise.race는 가장 먼저 완료된promise2의 결과인 'Second'를 출력합니다.- 잘못된 코드:
- 올바른 코드:
- 잘못된 코드:
- 올바른 코드:
Promise.all: 모든 Promise가 완료될 때까지 기다리며, 하나라도 실패하면 실패.Promise.race: 가장 먼저 완료된 Promise의 결과만 반환.- 비동기 작업을 효율적으로 처리하는 데 매우 유용.
- Promise의 반환값을 잊지 말고
.then()으로 처리해야 함. - 다음에 학습하면 좋은 주제: Async/Await, Error Handling in Promises, Fetch API 사용법.
Promise.race 사용 예제
const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'First'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'Second'));
Promise.race([promise1, promise2])
.then((value) => console.log(value));
실행 결과:
Second
동작 설명:
4. 실전 활용 예제
쇼핑몰 장바구니 예제
쇼핑몰에서 여러 제품의 가격을 동시에 요청할 때 Promise.all을 사용할 수 있습니다.
const product1Price = fetch('/api/products/1/price');
const product2Price = fetch('/api/products/2/price');
Promise.all([product1Price, product2Price])
.then(responses => Promise.all(responses.map(res => res.json())))
.then(prices => {
console.log(Total price: ${prices.reduce((acc, price) => acc + price, 0)});
});
이 코드에서는 모든 제품의 가격을 동시에 요청하고, 모든 가격을 받아서 총합을 계산합니다.
사용자 로그인 예제
로그인할 때 여러 API를 동시에 호출하여 사용자 정보를 가져오는 경우 Promise.race를 사용할 수 있습니다.
const userInfo = fetch('/api/user/info');
const userSettings = fetch('/api/user/settings');
Promise.race([userInfo, userSettings])
.then(response => response.json())
.then(data => {
console.log('User data:', data);
});
이 경우, 사용자 정보 또는 설정 중 가장 먼저 응답하는 것을 받아 사용합니다.
5. 흔한 실수와 주의사항
실수 1: Promise.all의 반환값을 간과
const promises = [Promise.resolve(1), Promise.resolve(2)];
const result = Promise.all(promises);
console.log(result); // Promise { <pending> }
const promises = [Promise.resolve(1), Promise.resolve(2)];
Promise.all(promises).then(result => console.log(result)); // [1, 2]
주의: Promise.all의 반환값은 Promise이므로, .then()을 통해 결과를 받아야 합니다.
실수 2: 모든 Promise의 실패를 잊음
Promise.all([Promise.resolve(1), Promise.reject('error')])
.then(result => console.log(result));
Promise.all([Promise.resolve(1), Promise.reject('error')])
.catch(error => console.error(error)); // 'error'
주의: 하나라도 실패하면 전체가 실패하므로, 반드시 .catch()로 처리해야 합니다.