개발 기술/개발 이야기

promise와 async await의 차이점

by GicoMomg (Lux) 2021. 11. 17.

이번 포스팅에서는 promise, async await의 차이점에 대해 알아보았다.
혹시 promise, async await을 모른다면 이 포스팅을 참고해보자!

1. js에서 비동기 처리는 왜 필요할까?

  • js는 동기적인 언어이지만, 서버에 데이터를 요청하는 등 대기시간 긴 작업의 경우 비동기 작업을 한다.

  • 하지만 이 때문에 발생하는 문제가 있는데, 아래 예시를 살펴보자

  • getAnimals()는 서버에서 동물의 데이터를 받아오는 함수이다.

  • 그리고 우리는 getAnimals()의 응답값을 받아 출력하고 싶다.

  • 아래와 같이 작성하면 animals()의 값이 출력될까? 답은 아니다.

function printAnimals() {
  const animals = getAnimals();
  console.log(animals);
}

  • js는 동기적인 언어이지만, 대기시간 긴 작업의 경우 비동기로 작업 한다.
  • 그렇기 때문에 getAnimals()보다 콘솔 출력이 먼저 발생하고, undefined가 출력되는 것이다.
function printAnimals() {
  const animals = getAnimals(); // 대기시간이 기네?
  console.log(animals);         // 우선 실행합니다~
}

printAnimals();  // undefined

  • 그럼 만약 우리가 getAnimals()의 응답값(response)를 사용하고 싶다면 어떻게 해야할까?
  • 비동기 처리방식인 promise, async await를 사용하는 것이다.

잠시만요! promise와 async await 둘 다 비동기 처리를 위해 사용되는데, 똑같은 거 아닌가?

  • 용도는 똑같지만 다른 점이 분명 존재한다.
  • 그럼 promise,async await에는 어떤 차이점 있는지 알아보자!

2. promise vs async await

(1) async는 간결하다

  • 앞선 예시를 다시 사용해보자.
  • 우리는 getAnimals()를 호출하여 응답값을 받고, 이 응답값을 출력하고 싶다.
  • promisethen방식이라면 아래와 같이 작성할 것이다.
function printAnimals() {
  getAnimals().then((data) => {
    console.log(data);
  })
}

  • 그럼 async await로 어떻게 표현할까?
  • 함수에 async 키워드를 적고, 비동기 대상에 await를 추가해주면 된다.
  • 비동기 대상 함수에 await를 추가하면, '이 함수의 처리를 기다려!' 라는 의미가 되기에
  • await 함수 아래에 해당 함수의 응답값을 사용하는 구문을 추가해주면 된다.
async function printAnimals() {
  const animals = await getAnimals();  // 이 함수처리 끝날때까지 기다려!
  console.log(animals)                 // 응답값이 출력됨!
}

어? 그런데 간결성 측면에서 둘 다 큰 차이가 없는 거 같은데요?

  • 짧은 예시로만 봤을 때 큰 차이를 못 느낄 것이다.
  • 그렇다면 데이터를 요청하여 처리까지 한다면? promisethen을 사용하면 아래와 같다.
function printAnimals() {
  return getAnimals()
    .then(data => {
      if (data.property) {
        return sampleFunc1(data)
          .then(anotherData => {
            console.log(anotherData)
          })
      }else {
        console.log(data)
      }
    })
}
  • then방식을 보면 라인 수가 많은 것은 물론 들여쓰기도 많아 복잡한 느낌이 든다.
  • 그럼 async await를 쓰면 어떨까?
async function printAnimals() {
  const animals = await getAnimals();
  if (animals.property) {
    const sampleData = await sampleFunc1(animals);
    console.log(sampleData);
  }else {
    console.log(animals);
  }
}
  • then에 비해 많은 들여쓰기는 물론 라인도 차지 않는다.
  • 또한 응답값을 명시적인 변수에 담아 사용하므로 직관적으로 변수를 인식할 수 있다.
  • 이처럼 async awaitthen 방식에 비해 간결하다는 장점을 가지고 있다.

(2) async는 에러 핸들링에 유리하다

  • 서버에 데이터를 요청하는 작업을 하다보면, 에러가 발생할 수 있다.
  • 이 때문에 우리는 에러 핸들링도 해주어야 한다.
  • 이번에는 printAnimals()에서 에러가 발생한 게 아니라, JSON.parse에서 에러가 발생했다고 가정하자.
  • 이 경우, then을 사용하면 내부에 추가적인 catch문을 적어줘야한다.
function printAnimals() {
  try {
      getAnimals()
      .then((response) => {
      const data = JSON.parse(response); // 여기서 에러 발생한다고 가정
      console.log(data);
    })
    .catch((err)=> {   // 추가적인 에러
      console.log(err)
    })
  }
  catch(err) {
    console.log(err)
  }
}
  • 이 방식은 직관적이지 않을 뿐더러 에러를 처리하는 catch문이 중복된다ㅜ

  • 하지만 async await를 사용하게 되면 하나의 catch만 해주면된다!
  • 해당 catch문에서는 try 내부에서 발생하는 모든 에러를 접근할 수 있다.
async function printAnimals() {
  try {
      const data = await JSON.parse((getAnimals())
    console.log(data);
  }
  catch(err) {
    console.log(err)
  }
}

(3) async는 에러 위치를 찾기 쉽다

  • 만약 프로미스를 연속으로 호출한다고 해보자.
  • 이때 만약 어느 지점에서 에러가 발생하면 어떤 then에서 에러가 발생했는지 찾기가 어렵다.
function sample() {
  return sampleFunc()
    .then(data => return data)
    .then(data2 => return data2)
    .then(data3 => return data3)
    .catch(err => console.log(err))  // 결과적으로 문제가 발생했다
}

  • 하지만 async를 사용하게 되면, 어떤 지점에서 에러가 발생했는지 쉽게 찾을 수 있다.
async function sample() {
  const data1 = await sampleFunc();      // 문제 발생시 data1값이 유효치 않음
  const data2 = await sampleFunc2(data1);
  return data2;
}



이처럼 promise의 then, async await는 용도는 같지만, 간결성, 에러 핸들링, 에러 위치 확인 측면에서 차이가 있음을 알게 되었다. 이외에도 async await은 디버그를 할 때 then과 달리 정확한 위치를 지정할 수 있는 장점이 있다.

반응형

댓글