관리 메뉴

Jerry

async await 이란? 본문

Front/JavaScript

async await 이란?

juicyjerry 2021. 4. 14. 23:07
반응형

이번 주제는 async await이다!

이 키워드를 주제로 정하게 된 이유는 async await에 대해 배운지 오래 되어 개념이 가물가물해서 이번 기회를 통해 다시 개념을 정리하고자 하였다. 시작해봅시다 :)))

 

출처: 구글 이미지

 

async await이라는 문법은 비동기 처리를 하기 위해서 사용했던 프로미스(promise)라는 문법을 좀 더 편하게 사용하기 위해 async await까지 생겼다고 한다. 

 

먼저, async 함수에 대해서 알아보자

async function 선언은 AsyncFunction 객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 Promise를 사용하여 결과를 반환합니다. 그러나 비동기 함수를 사용하는 코드의 구문과 구조는, 표준 동기 함수를 사용하는 것과 많이 비슷합니다.

 

 

mdn에서 이야기하는 정의는 위와 같다. async는 AsyncFunction이라는 생성자를 반환하여 해당 함수를 만들어 비동기 처리를 하도록 한다. 그런데, AsyncFunction이라는 게 무얼까해서 mdn에서 또 찾아보았다. 

 

 

AsyncFunction 생성자는 새로운 async function 객체를 만든다. 자바스크립트에서 모든 비동기 함수는 사실상 AsyncFunction 객체이다.

 

 

어려워보인지만, 특별하게 이 부분에 관해 추가적으로 알아야 async function을 사용할 수 있는 것은 아니다.

 async는 사용법이 쉽다. function 앞에 위치시킨다. 끝이다!

 

async function f() {
  return 1;
}

 


 

어떻게 사용하는지 확인해보자!

async가 붙은 함수는 반환 값으로 Promise를 반환된 값으로 반환하거나 async함수 내에서 발생하는 캐치되지 않는 예외로 거부되는 값을 반환한다. (참고로, 예외처리에 관한 내용은 내용 하단부에 위치해있다!)

 

#1
async function f() {
  return 1;
}

f().then(alert); // 1

 

#1에서 alert로 인해 1인 이행(resolved) 프라미스가 반환된다.

(참고로, 필자는 개인적으로 이행 프라미스라고 말하는 사람을 본 적이 없다. 프로미스 앞에 이행이라고 붙여 말하는 어감이 어색하다.)

 

#2
async function f() {
  return Promise.resolve(1);
}

f().then(alert); // 1

 

#2에서는 명시적으로 작성한 코드다.

#1과 동일한 값을 반환한다.

 

즉, async가 붙은 함수는 반드시 프라미스를 반환한다는 것과 프로미스가 아닌 것은 프로미스로 감싸서 반환한다는 것을 알 수 있다. 이렇게 간편하게 비동기 처리를 할 수 있게 해주는 async에게는 짝꿍이 있다!!

예상하고 있겠지만.. 바로, await이다!!

 

 

다음으로, await 함수에 대해서 알아보자

await은 async 함수 안에서만 동작하는 키워드이다.

만약, 함수 바깥에서 사용하면 SyntaxError가 발생한다.

 

 

아래는 mdn에서는 무엇이라고 이야기할까?

await연산자는 Promise를 기다리기 위해 사용됩니다. 연산자는 async function 내부에서만 사용할 수 있습니다.

 

 

'Promise를 기다리기 위해 사용' 라는게 무슨 말일까?

await문은 Promise가 fulfill 되거나 reject 될 때까지 async함수의 실행을 일시 정지하고, Promise가 fulfill 되면 async함수를 일시 정지한 부분부터 실행합니다. 이때 await문의 반환 값은 Promise에서 fulfill 된 값이 됩니다. 만약, reject가 되면, await 문은 reject 된 값을 throw 합니다.

 

 

즉, await 키워드는 프라미스가 처리될 때까지 기다려 그 후 해당하는 결과값을 반환하는 것이다. 

아래 #1 코드 예시를 살펴보자!

 

#1
function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolveAfter2Seconds(10);
  console.log(x); // 10
}

f1();

 

#1의 f1 함수 안에 변수 x가 await이 사용되었다. 

해당 함수가 실행되면서 변수 x가 있는 줄에서 실행이 잠시 중단되었다가 Promise가 이행(resolved) 될 때까지 기다렸다가 실행이 됩니다.  이때 변수 x에 값이 할당되게 되어 2초 뒤에 콘솔에 10이 찍히게 됩니다. 

 

 

즉, await의 기능은 프라미스가 처리되길 기다리는 동안엔 엔진이 다른 일(다른 스크립트를 실행, 이벤트 처리 등)을 할 수 있기 때문에, CPU 리소스가 낭비되지 않습니다

 

 

await는 promise.then보다 좀 더 세련되게 프라미스의 result 값을 얻을 수 있도록 해주는 문법입니다. promise.then보다 가독성 좋고 쓰기도 쉽습니다.

 

 

에러핸들링

프라미스가 정상적으로 이행되면 await promise는 프라미스 객체의 result에 저장된 값을 반환합니다. 반면 프라미스가 거부되면 마치 throw문을 작성한 것처럼 에러가 던져집니다.

 

아래 #1, #2, #3은 에러 핸들링 처리 코드 예시입니다. 

#1
async function f() {
  await Promise.reject(new Error("에러 발생!"));
}

 

#1과 #2는 동일한 결괏값을 반환합니다!

 

 

#2
async function f() {
  throw new Error("에러 발생!");
}

 

#3은 try... catch문을 이용해 에러 핸들링을 합니다.

 

#3
async function f() {

  try {
    let response = await fetch('http://유효하지-않은-주소');
  } catch(err) {
    alert(err); // TypeError: failed to fetch
  }
}

f();

 

 

추가로,

만약 아래처럼 여러 개의 비동기 처리해야 하는 경우에는 Promise.all로 해당 프라미스를 감싸고 await를 붙여 한 번에 처리할 수 있습니다! 

// 프라미스 처리 결과가 담긴 배열을 기다립니다.
let results = await Promise.all([
  fetch(url1),
  fetch(url2),
  ...
]);

 

 

여기까지 async과  await에 대해 배워보았고 이것들을 이용해서 가독성 있고 사용하기 편한 비동기 코드를 작성할 수 있습니다! 

 

 

출처: MDN | mzl.la/2QlW3K3

출처: MDN | mzl.la/2OL9Jxw

출처: JAVASCRIPT.INFO | bit.ly/3mN8n1K

반응형

'Front > JavaScript' 카테고리의 다른 글

async 예외처리(의 까다로운점?)  (0) 2021.04.15
자바스크립트 원시값?  (1) 2021.04.14
One Paper: Understanding Prototype  (0) 2020.11.07
One Paper: Inheritance Pattern  (0) 2020.11.07
One Paper: Object Oriented Programming  (0) 2020.11.01