비동기(asynchronous)- 4 (async / await)

태로샐러드·2021년 11월 14일

javascript 비동기

목록 보기
4/4
post-thumbnail

🍫 Why async / await ?

지난 파트에서 Promise에 대해 살펴보았다. Promise는 Callback Hell을 깔끔하게 해결해주는 고마운 녀석이었지만, 얘도 chaining을 계속하다 보면 코드가 조금 난잡해질 수 있다.

이때 async와 await이라는 특별한 문법을 사용하면 Promise를 조금 더 깔끔하게 사용할 수 있다.
마치 동기식으로 코드를 작성하는 것처럼 간편하게 코드를 작성할 수 있도록 도와준다.

요약 : Promise를 깔끔하게 사용하게 해준다!

🍫 되짚어보자. (비동기와 Promise)

async와 await에 대해 알아보기 전에 비동기 처리의 필요성과 Promise의 간단한 사용법을 되짚어보자.
코드 출처 : 드림코딩 by 엘리 유튜브

function fetchUser() {
  // 10초 정도 걸리는 서버에서 사용자 데이터를 받아오는 코드가 있다고 가정.
  return 'complete'
}

const user = fetchUser();
console.log("user 데이터 가져오기 완료");
console.log("Page UI 표시!");

javascirpt 엔진은 기본적으로 순서대로 위에서부터 아래로 한 줄씩 코드를 실행시킨다. 이는 바로 동기적인 처리를 하고 있는 것이다.
위 코드에서 그 어떤 비동기 처리도 하지 않으면 10초가 지난 뒤에야 console에 "page UI 표시!"가 출력될 것이다.
즉 실제 어떤 서비스를 제공하는 웹페이지라고 치면, 데이터를 받아오는 10초 동안 사용자는 그 어떤 UI요소도 렌더링 되지 않은 텅빈 지루한 화면을 보고 있을 것이다.
이게 비동기처리의 필요성이었다.

function fetchUser() {
  return new Promise((resolve, reject) => {
   // 10초 정도 걸리는 서버에서 사용자 데이터를 받아오는 코드가 있다고 가정.  
    resolve('complete')
  })
}

const user = fetchUser();
user.then(console.log("user 데이터 가져오기 완료"))
console.log("Page UI 표시")

우리는 이런 비동기 처리를 위해 지난번에 위와 같이 Promise api를 사용했었다.

🍫 async

async는 위에서 말했던 대로 위와 같은 Promise를 조금 더 깔끔하게 쓸 수 있게 도와주는 syntactic sugar이다. 사용법은 놀랍게도 간단하다.

async function fetchUser() {
  // 10초 정도 걸리는 서버에서 사용자 데이터를 받아오는 코드가 있다고 가정. 
  return 'complete'
}

const user = fetchUser();
user.then(console.log("user 데이터 가져오기 완료"))
console.log("Page UI 표시")

위에서 봤던 예제와 동일한 코드이다. 대충봐도 Promise보다 훨씬 더 간결해진걸 알 수 있다.
이는 function 앞에 async라는 키워드를 붙여주는 것만으로도 가능하다.
저렇게 async를 붙여주면 해당함수 코드블록은 Promise를 반환한다!

🍫 await 사용법

awaitasync 키워드가 붙은 함수내에서만 동작하는 키워드다.
(일반함수에서 사용하게 되면 Syntax error가 발생한다.)

기본적으로 await을 만나면 Promise가 처리(settled)될 때까지 함수 실행을 기다린다.
Promise가 처리되면 그 결과와 함께 실행이 재개된다. 처리되는 동안에는 비동기적으로 엔진이 다른 일을 할 수 있게 만들어준다.

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve,ms));
}

async function test() {
  await delay(3000);
  console.log('완료');
}

test();

위 코드를 보자.
단지 delay라는 Promise 앞에 await를 붙여주는 것 만으로도 3초를 기다렸다가 완료라는 문자열을 콘솔에 출력하는 Promise가 만들어졌다.
Promise에서 then의 역할을 대신한다고 생각하면 편할 것 같다.

아래는 Promise의 then을 사용한 코드이다.

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve,ms));
}

function test() {
  return delay(3000)
  .then(console.log('완료'))
}

test();

사실 코드가 짧아서 잘 느껴지지 않을 수도 있지만 await가 조금 더 직관적인 느낌이고,
긴 코드를 짠다고 가정했을 때 Promise를 사용한다면 코드가 꽤나 복잡해질 것이다.

🍫 에러 처리

Promise에서는 .catch를 체이닝하는 것으로 에러를 잡을 수 있었다.
async await에서는 javascript가 제공하는 try..catch문을 사용할 수 있다.

try {

  // 코드...

} catch (err) {

  // 에러 핸들링

}

try..catch는 다음과 같이 동작한다.
1. 먼저, try {...} 안의 코드가 실행되고,
2. 에러가 없다면 try 블록 안의 마지막 줄까지 실행되고 catch 블록은 건너 뛴다.
3. 에러가 있다면 try 안 코드의 실행이 중단되고 catch(err)블록으로 넘어간다. 변수 err에는 어떤 에러인지에 대한 설명이 담긴 객체가 포함된다.

따라서 이 형태에 맞게 try 코드를 감싸고, 나머지 에러를 적절하게 핸들링하면 된다.

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve,ms));
}

async function test() {
  try {
    await delay(3000);
    console.log('완료');
  }
  catch(err) {
    console.log(err);
  }
}

test();
profile
기획, 개발공부, 그 외 잡다한 여정 기록 (SEMI로)

0개의 댓글