[JS] 비동기처리 Promise와 async await

안치영·2022년 12월 30일
0

JavaScript

목록 보기
3/3

Javascript에서 비동기처리가 필요한 이유?

Promise, async/await를 알기 전에 JS에서 비동기처리가 왜 필요한지에 대해 먼저 알아야 할 필요성이 있다.

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

function printData() {
  const data = getData(); // 서버의 데이터를 요청 (비동기)
  console.log(data); // 우선 실행
}
printData();  // undefined

위의 코드처럼 데이터를 요청하는 작업 보다 콘솔 출력이 먼저 발생하고, undefined가 출력된다.

이러한 문제들을 해결하고자 나온 방법으로 주로 callback, Promise, async/await 를 사용한다.

그 중에서도 요즘 특히 많이 사용되는 Promise, async/await의 특징 및 간단한 사용 예시와 차이점에 대해 얘기해 보고자 한다.


Promise

그 유명한 콜백지옥이다.

콜백 지옥(callback hell)이란 콜백 함수를 익명 함수로 전달하는 과정에서 또 다시 콜백 안에 함수 호출이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상을 말한다.
주로 이벤트 처리나 서버 통신과 같은 비동기 작업을 제어하기 위해서 사용되는데 이러한 프로그래밍은 가독성이 떨어지고 코드 수정을 어렵게한다.

이런 문제를 해결하기 위해 나온게 Promise이다.

Promise는 자바스크립트에서 비동기 처리에 사용되는 객체이다.
내용은 실행 되었지만 결과를 아직 반환하지 않은 객체라고 이해해도 좋다.

Promise 에는 아래의 3가지 상태가 존재한다.

  • Pending (대기)
  • Fulfilled (이행)
  • Rejected (실패)

비동기 처리가 완료 되지 않았다면 Pending, 완료 되었다면 Fulfilled, 실패하거나 오류가 발생하였다면 Rejected 상태를 갖는다.

Promise 사용법

function printData() {
  getData().then((data) => {
    console.log(data);
    // 이부분에서 받아온 data를 통해 원하는 작업을 수행할 수 있다.
  }).catch(err) => {
    console.log(err)
    // 에러 핸들링 부분
  }
}

콜백지옥을 해결하기 위해 나왔던 Promise 또한 콜백지옥과 같은 현상을 완전히 피하기는 어려웠다. 예를들자면 then안에 promise안에 then안에 promise안에 ... 이런식으로 진행되었기에 이를 완전히 개선하고자

async / await이 나오게 된 것이다.

async / await

ES2017에 나온 문법으로 위의 설명한것과 같이 callback, promise의 단점을 해소하기 위해 나왔다.

async / await은

  • 간결하고
  • 에러헨들링에 유리하며
  • 에러 위치를 찾기 쉽다

Promise의 코드와 비교를하면 확연히 눈에 띌 수 있을 것이다.

// Promise의 비동기 처리
function printData() {
  try {
      getData()
      .then((res) => {
      const data = JSON.parse(res); // 여기서 에러 발생한다고 가정
      console.log(data);
    })
    .catch((err)=> {   // 추가적인 에러
      console.log(err)
    })
  }
  catch(err) {
    console.log(err)
  }
}

위의 경우 JSON.parse에서 에러가 발생한다고 가정했기에 catch문을 중첩해서 써줘야하는 불편함을 볼 수 있다.

// async / await의 비동기 처리
async function printData() {
  try {
    const data = await JSON.parse((getData())
    console.log(data);
  }
  catch(err) {
    console.log(err)
  }
}

보시다시피 코드도 매우 간결해졌고, catch문을 중첩하지 않아도 try의 에러부분을 모두 접근할 수 있어진다.

0개의 댓글