개발자공부일기

async/await 본문

Javascript

async/await

JavaCPP 2025. 2. 5. 20:38

async/await를 쓰는 이유

자바스크립트에는 비동기 처리 방식이 3가지가 있는데 콜백 함수와 이를 개선한 Promise객체 그리고 async/await가 있다.

콜백 함수를 사용하면 Callback Hell에 빠지기 쉽고 이를 개선한 Promise도 무분별한 then의 사용으로 Promise Hell에 빠지는 상황이 생긴다.

 

 Callback Hell

step1(function (value1) {
    step2(function (value2) {
        step3(function (value3) {
            step4(function (value4) {
                step5(function (value5) {
                    step6(function (value6) {
                        // Do something with value6
                    });
                });
            });
        });
    });
});

 

Promise Hell

fetch('https://example.com/api')
  .then(response => response.json())
  .then(data => fetch(`https://example.com/api/${data.id}`))
  .then(response => response.json())
  .then(data => fetch(`https://example.com/api/${data.id}/details`))
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

 

둘 다 무슨 작업인지 한 번에 알아보기가 힘든데 그래서 우린 async와 await를 사용한다.

 

async function getData() {
    const response = await fetch('https://example.com/api');
    const data = await response.json();
    const response2 = await fetch(`https://example.com/api/${data.id}`);
    const data2 = await response2.json();
    const response3 = await fetch(`https://example.com/api/${data.id}/details`);
    const data3 = await response3.json();
    console.log(data3);
}

getData();

 

좀더 보기가 편해졌다.

 

기억해야 할 점이 async/await가 Promise를 대체하기 위한 기능이 아니라는 것이다. 내부적으로는 여전히 Promise를 사용해서 비동기를 처리하고, 단지 코드 작성 부분을 프로그래머가 유지보수하게 편하게 보이는 문법만 다르게 해줄 뿐이라는 것이다.

 

async/await의 사용법

function 앞에 async를 붙이고 비동기로 처리하는 부분 앞에 await를 붙이면 된다.

function resolveAfter2Seconds() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);
  // Expected output: "resolved"
}

asyncCall();
/*
출력
"calling"
"resolved"
*/

 

보시다시피 await가 붙은 resolveAfter2Seconds가 완료될때까지(2초후) 기다리고 result 로그를 띄웁니다.

 

그리고 async가 붙은 함수의 리턴값은 Promise객체다. resolved가 출력되는걸 볼 수 있다. 그렇다는 말은 .then()도 쓸 수 있다. 하지만 난 안쓸거다.

 

async/await 에러 처리

function resolveAfter2Seconds() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  try {
    console.log('calling');
    const result = await resolveAfter2Seconds();
    console.log(result);
    // Expected output: "resolved"
  } catch (err) {
    console.error(err);
  }
}

asyncCall();
/*
  출력
  "calling"
  "resolved"
  */

 

그냥 async함수 안에 try catch로 감싸서 오류를 잡아내면 된다.

 

생각해봐야 할 것

await는 작업이 완료되기 전까지 대기하는 것이기 때문에 A,B가 a라는 데이터에 접근한다면 필요하겠지만

A는 a에 B는 b에 접근하고있다면 await를 쓰는게 손해가 될 수 있다. 물론 A는 a에 B는 b에 접근하고 있더라도 await를

사용해야할 경우가 있을 수 있는데, 

async function getFruites(){

  let getApplePromise = getApple(); // async함수를 미리 논블록킹으로 실행한다. 
  let getBananaPromise = getBanana(); // async함수를 미리 논블록킹으로 실행한다. 
  
  // 이렇게 하면 각각 백단에서 독립적으로 거의 동시에 실행되게 된다.
  console.log(getApplePromise)
  console.log(getBananaPromise)
  
  let a = await getApplePromise; // 위에서 받은 프로미스객체 결과 변수를 await을 통해 꺼낸다.
  let b = await getBananaPromise; // 위에서 받은 프로미스객체 결과 변수를 await을 통해 꺼낸다.
  
  console.log(`${a} and ${b}`); // 본래라면 1초+1초 를 기다려야 하는데, 위에서 1초기다리는 함수를 바로 연속으로 비동기로 불려왔기 때문에, 대충 1.01초만 기다리면 처리된다.
})

 

이런식으로 이미 받아온 변수를 꺼낼때만 await하도록 분리해두면 쓸 수 있다.

'Javascript' 카테고리의 다른 글

Express  (0) 2025.02.07
Arrow Function(화살표 함수)  (0) 2025.02.05
Promise  (0) 2025.02.04
var, let ,const의 차이 그리고 변수 호이스팅  (0) 2025.02.04
Promise와 forEach의 동작 차이  (0) 2024.12.31