[Computer Science] promise vs async & await

동기 vs 비동기 ?

비동기 통신을 비교하기에 앞서 동기와 비동기가 어떤 차이가 있는지 간단하게 알아보자.

동기는 말 그대로 동시에 일어난다는 뜻이다. 요청과 그 결과가 동시에 일어난다는 약속인데 바로 요청을 하면 시간이 얼마가 걸리던지 요청한 자리에서 결과가 주어져야 한다.

비동기는 동시에 일어나지 않는다를 의미하는데 요청과 결과가 동시에 일어나지 않을거라는 약속이다.

동기방식은 설계가 매우 간단하고 직관적이지만 결과가 주어질때까지 아무것도 못하고 대기해야 한다는 단점이 있고, 비동기방식은 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있다는 장점이 있다.


javascript는 비동기적 언어?

js는 동기적인 언어이지만, 때로는 비동기적으로 처리한다.
만약 자바스크립트에 많은 양의 데이터를 요청하면, 응답을 받기위해 많이 대기를 해야한다.
이 경우에는 데이터 응답을 받기 전까지 다른 작업을 수행할 수 없는 문제가 발생한다.
이러한 경우에는 자바스크립트는 비동기적으로 작업을 처리한다.


promise

1) promise 란?

  • promise는 비동기 처리를 위해 사용되는 객체이다.
  • promise를 사용하면 비동기 메소드를 동기 메소드로 처리할 수 있다.

2) promise의 3가지 상태

  • 대기(pending) : 처리 대기 상태
  • 이행(fulfilled) : 비동기 처리를 성공하여 결과를 반환해 준 상태
  • 거부(reject) : 비동기 처리를 실패하여 오류가 발생한 상태

A. 대기 상태

  • new Promise()를 이용해 promise 객체를 생성한 시점이다.
new Promise();

B. 이행 상태

  • 비동기 처리가 성공하여 resolve()가 실행된 상태로, 이를 이행 상태라고 한다.
function printNumber(n) {
  return new Promise((resolve, reject) => {
    const number = n + 1;
    resolve(number);   // resolve == 비동기처리 성공!
  })
}
  • resolve()에 전달한 파라미터는 then()에서 사용할 수 있다.
printNumber(1).then((n) => console.log(n));  // 2

C. 거절 상태

  • 비동기 처리가 실패하여 reject()가 실행된 상태로, 이를 거절 상태라고 한다.
  • catch()에서 에러원인을 확인할 수 있다.
  • 아래 코드는 의도적으로 number가 3일 때 reject()를 실행했다.
function printNumber(n) {
  return new Promise((resolve, reject) => {
    const number = n + 1;
    if (number === 3) {
      let error = new Error();
      error.name = 'ValueIsThreeError';
      return reject(error);
    }
    resolve(number);
})}
printNumber(2).catch(e => console.error(e));  // error: ValueIsThreeError

3) promise 사용 예시

  • getApartmentInfo()를 사용해 아파트 정보를 받고, 결과를 출력하고자 한다.
  • 처리가 성공했을 때는 resolve()에 응답값을 넘기고, 실패했을 시 reject()에 에러 메시지를 넘겨준다.
function getApartmentInfo() {
  return new Promise(function(resolve, reject) {
    $.get('url주소', (response) => {
      if (response) resolve(response);               // 성공시 응답값을 넘김
      reject(new Error("InValid Request Error"));    // 실패시 에러메시지를 넘김
    })
  })
}
  • promise 처리가 성공하고 난 뒤, then()에서 그 응답 결과를 사용할 수 있다.
  • 만약 promise 처리가 실패했다면, catch()를 사용하여 에러 메시지를 확인할 수 있다.
getApartmentInfo()
  .then((data) => {   // 성공시 응답값을 출력
    console.log(data);
  })
  .catch((error) => { // 실패시 에러 메시지를 출력
    console.error(error);
  })

async & await

1) async & await 란?

  • async & awaitpromise처럼 비동기 처리를 위해 사용된다.
  • promise를 더 쉽게 사용할 수 있는 방법이다.

2) async & await 사용법

  • 동기처리를 할 함수 앞에 async를 비동기 대상 앞에 await를 붙여주면 된다.
function getData() {
  // 서버에서 데이터를 요청하는 함수
}
async function printData() {       // 1. 동기적으로 처리할거야
  const data = await getData();    // 2. getData 처리를 기다릴거야
  console.log(data);               // 3. getData처리 성공 후 실행할 코드이지!
  })
}
  • 만약 비동기 처리 중 발생하는 에러에 대처하고 싶다면 try~catch문을 사용하면 된다.

promise vs async & await

1) async & await는 간결하다

  • promise를 사용한 비동기 처리
function printAnimals() {
  return getAnimals()
    .then(data => {
      if (data.property) {
        return sampleFunc1(data)
          .then(anotherData => {
            console.log(anotherData)
          })
      }else {
        console.log(data)
      }
    })
}
  • async & await를 사용한 비동기 처리
async function printAnimals() {
  const animals = await getAnimals();
  if (animals.property) {
    const sampleData = await sampleFunc1(animals);
    console.log(sampleData);
  }else {
    console.log(animals);
  }
}

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

  • 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)
  }
}
  • async & await를 사용하게 되면 하나의 catch만 해주면된다.
async function printAnimals() {
  try {
      const data = await JSON.parse((getAnimals())
    console.log(data);
  }
  catch(err) {
    console.log(err)
  }
}

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

  • promise를 연속으로 호출한다고 가정했을 때 어느 지점에서 에러가 발생하면 어떤 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;
}

좋은 웹페이지 즐겨찾기