본문 바로가기

JavaScript

[Javascript] Promise와 async/await의 비동기 처리

저번 글에서 말했듯이 자바스크립트는 비동기 방식으로 동작합니다.
비동기 코드에서 작업의 순서를 보장하기 위한 방법 중 하나는 콜백이 있습니다.

하지만 순서를 지켜야 할 작업이 여러 개라면 어떨 것 같나요?
호출한 콜백은 또다른 콜백을 호출하고 그 콜백은 또 다른 콜백을...

이렇게 가독성을 떨어뜨리는 문법을 해결할 또 다른 방법이 있습니다.
이번에는 Promise와 async/await의 비동기 처리에 대해서 알아보겠습니다.


🐸 Promise

Promise라는 객체에는 작업에 대한 상태를 가지고 있습니다.
가지고 있는 상태의 종류는 다음과 같습니다.

  • Pending(대기)
  • Fulfilled(이행) 
  • Rejected(거부)
const promise = new Promise((resolve, reject) => {
  if (/* 작업 성공 */) {
    resolve('작업 성공');
  } else {
    reject('작업 실패');
  }
}

위의 예제처럼 resolve와 reject라는 콜백 함수를 기본으로 제공합니다.
Promise 객체는 생성하는 순간 대기 상태를 가지며,
resolve를 호출하면 이행, reject를 호출하면 거부 상태로 변화합니다.

 

🐸 Promise chaining

그럼 아까 언급한 콜백 지옥을 Promise는 어떻게 해결할 수 있을까요?

then()은 매개변수로 Promise가 이행했을 때와 거부했을 때를 위한 콜백 함수를 가지고 Promise 객체를 반환합니다.
덕분에 체이닝 문법을 사용하여 순차적으로 작업을 수행할 수 있습니다.

예를 들어, 산타를 위해 주소를 가져와서 포장을 하고 배달하는 코드를 작성한다면 이렇게 할 수 있습니다.

findAddressFromDB(userId)
  .then((address) => {
    console.log('착한 아이의 주소: ', address);
    return pack(address);
  }).then((gift) => {
    console.log('포장 완료', gift);
    return deliver(gift);
  }).then(() => {
    console.log('배달 완료');
  }).catch((error) => {
    console.log('오류가 발생했습니다.', error);
  });

 

🐸 async/await

앞에서 나온 체이닝을 사용해도 체인이 길어진다면 가독성이 떨어질 것입니다.
이러한 단점을 async와 await를 통해 보완할 수 있습니다.

예를 들어, 위 체이닝 예제를 async/await 형식으로 다시 작성하면 아래와 같습니다.

async function delivery() {
  try {
    const address = await findAddressFromDB();
    console.log('착한 아이의 주소: ', address);
    
    const gift = await pack(address);
    console.log('포장 완료', gift);
    
    const deliver = await deliver(gift);
    console.log('배달 완료');
  } catch (error) {
    console.log('오류가 발생했습니다.', error);
  }
}

await는 Promise가 완료될 때까지 기다렸다가 결과를 저장할 수 있습니다.
async로 만들어진 함수 안에서만 await를 사용할 수 있습니다.
async가 앞에 붙여진 함수는 항상 Promise 객체를 반환하는 함수가 됩니다.


이 글을 끝까지 봐주셔서 감사합니다.
틀린 내용이 있다면 댓글로 지적 부탁드립니다.