(21.09.05) Promise에 관하여

도깨비젤리

·

2021. 9. 6. 00:21

작은 지식이라도, 하루에 하나씩.


 

한 줄 요약


🦄Promise란 자바스크립트 비동기 작업을 더 편하게 처리할 수 있도록 ES6에 도입된 기능🦄
🦄굳이 서버로 API 요청을 보내는 작업이 아니더라도 사용 할 수 있음🦄
🦄호출 시 콜백함수를 선언. 성공시 : resolve / 실패 시 : reject 실행🦄
🦄Promise의 상태는 Pending(유예중), Fulfilled(이행중), Rejected(거부중)의 3가지 상태를 가진다.🦄

 

본문


앞서 말했듯, Promise란 자바스크립트의 비동기 작업을 더 편하게 처리하기 위한 기능이다.

 

* 비동기 작업 : 실행 요청과 실행 결과가 동시에 일어나지 않는 작업 (동시에 일어나지 않는 작업으로 생각)

 

호랑이 담배피던 시절에는 비동기 작업을 처리하기 위해서 콜백 함수라는 걸 썼는데, 이 콜백이 많아질 수록 코드가 매우 흉측해졌기에, 이를 좀 더 예쁘게 만들기 위해서 Promise라는 개념이 도입되었고, 최근에는 async/ await라는 기능이 도입되어, 비동기 작업을 동기 작업과 동일한 스타일로 처리할 수 있게 되었다.

 

그럼 가장 최근에 만들어진 async/ await 만 쓰면 되지 않냐 싶은데, 언제나 그렇듯 모든 상황에 들어맞는 황금열쇠는 없다. Promise로 만들었을때 더 효과적인 순간이 있기에, promise도 알아둬야할 필요가 있는 것이다. 그 대표적인 예가 병렬 처리를 위한 Promise.all 메서드인데, 이걸 설명하기 전에 먼저 promise 객체가 어떤 친구인지 알아봅시다.

 

 

Promise 객체는 비동기 작업이 맞이할 미래의 완료 / 실패 상태 그리고 그 결과 값을 나타낸다.

 

mdn 문서에 적혀 있는 Promise 객체의 정의입니다. 어떤 값이든 Promise로 만든 순간, 이 값은 현재의 값이 아니라 미래에 도래할 값이 되어버리고, 여기서 성공과 실패를 분리해서 메서드를 수행합니다.

 

다음 예시를 보면서 성공/ 실패 분리가 무슨 뜻인지 알아봅시다.

 

const condition = true;
const promiseSample = new Promise((resolve, reject) => {
  if (condition) {
    resolve('resolved');
  } else {
    reject('rejected');
  }
});

promiseSample.then((res) => {
    console.log(res);
  })
  .catch((error) => {
    console.error(error);
  });

 

위 코드는 condition의 참 거짓 여부에 따라 promise의 반환 값을 결정 짓습니다.

 

값이 참이라면 resolve를 호출하고, 아닐시에는 reject를 호출한다.

promise의 resolve로 나온 값은 then()으로 받고, reject로 나온 값은 catch()를 통해 받는다.

 

이렇게 resolve와 reject, then과 catch문의 체이닝을 통해 비동기 로직의 성공 여부에 따른 분기 처리가 가능합니다.

 

 

 

Promise.all(iterable)


Promise.all 메서드는 여러 개의 비동기 처리를 병렬로 수행하고 싶을 때 선택할 수 있는 대표적인 메서드입니다.

통상 async/ await를 사용하여 여러 개의 비동기 처리를 수행한다면, 하나의 비동기 처리가 끝날때 까지 대기하고, 그 다음 처리를 시행하는데, promise.all을 사용한다면 안에 있는 모든 비동기 처리가 동시에 실행됩니다.

 

아래 코드를 보면서 설명하겠습니다.

 

async function anna () {
  const sampleAsync = async (text,time) =>{
    console.log(text) // 들어간 순서 확인용
	return new Promise((resolve,reject)=>{
    setTimeout(()=>typeof text === 'string'? resolve("string"): reject('notString'))
    })}

console.time('걸린 시간')
await Promise.all([
  sampleAsync('처리가',2000),
  sampleAsync('병렬로',1000),
  sampleAsync('됩니다',4000)
])
console.timeEnd('걸린 시간')

}

anna()

 

promise.all의 특징은 iterate한 개체 안에 있는 promise들의 순서에 관계 없이 ( 사실 promise가 아니여도 동작은 함) 동작이 마친 순서대로 결과 값을 뱉어냅니다. 그러나, 이 메서드의 특징은 병렬적으로 동작한다는 것입니다. 순차적으로 처리된다면 걸린 시간은 2s + 1s + 4s = 6s가 될 텐데, 실제 확인해 본 결과는 아래와 같이 3s가 나왔습니다

 

 

병렬로 요청을 처리하는 promise all

 

그럼 동일한 코드를 await를 사용해서 구성해봅시다.

 

async function anna () {
  const sampleAsync = async (text,time) =>{
    console.log(text)
	return new Promise((resolve,reject)=>{
    setTimeout(()=>typeof text === 'string'? resolve("string"): reject('notString'))
    })}

console.time('걸린 시간')
await sampleAsync('순차적',2000)
await sampleAsync('처리가',1000)
await sampleAsync('됩니다',4000)
console.timeEnd('걸린 시간')

}

anna()

 

await 로 처리한 결과

 

 

보시다시피, 순차적으로 요청을 처리하여, 처리 시간이 오래걸렸습니다. 이렇듯, promise.all은 비동기처리를 병렬적으로 수행하여 요청을 더 빠르게 수행할 수 있다는 장점이 있습니다. 만약 비동기 처리가 실패한다면, 그 즉시 실패를 반환하기에, 사용자와 즉각적인 대화가 필요한 앱인 경우, promise.all을 적극적으로 사용해야할 것입니다.

 

 

그럼 마지막으로, asyc-await와 promise.all의 동작이 어떻게 되는지 그림으로 다시 한번 확인해보고 글을 마무리 짓겠습니다.

 

 

 

레퍼런스


https://code-masterjung.tistory.com/91

 

언제 Promise.all을 사용해야 될까?

async await는 Promise를 가독성 좋게 사용하는 한 가지 방법에 불과합니다. 이미 앞에 글에서 봤듯이 자바스크립트를 통해 비동기 코드를 처리하는 가장 기본적인 방법은 콜백 함수, 프라미스(Promise)

code-masterjung.tistory.com

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

 

Promise.all() - JavaScript | MDN

Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환합니다. 주어진 프로미스 중 하나가 거부하는 경우, 첫

developer.mozilla.org

 

'TIL' 카테고리의 다른 글

(21.09.07) Moment.js의 moment는 mutable하다  (0) 2021.09.07
(21.09.07)React fast-reload  (0) 2021.09.07
(21.09.05) ParseInt vs Number  (0) 2021.09.05
(21.09.01) Moment.js  (0) 2021.09.01
(21.08.31)ES6 Class  (0) 2021.08.31