새소식

SW 개발

[NodeJS] 자바스크립트 비동기 연산을 다루는 async/await

  • -

 

자바스크립트의 비동기를 다루는 async/await

 

콜백함수의 콜백지옥을 탈출하게 해주는 Promise, 그리고 또 Promise의 단점을 보완해주는 async/await.

async/await은 Promise와 다른 개념이 아니고 Promise를 사용하는 패턴이니 Promise의 이해가 선행되어야 합니다.

Promise 포스팅 참고하기

 

 

인간의 욕심은 끝이 없고 보완의 보완을 거듭하는 패턴은 계속 나옵니다.

현재 비동기 연산을 다루는 패턴 중 가장 쉽게 접근할 수 있는 방법인 async/await는 비동기 처리의 꽃 이라고 할 수 있습니다.

 

 

왜 callback, promise로도 비동기 처리가 가능한데, async/await까지 알아야 할까요?

 

가장 큰 이유는 여전히 Promise도 가독성이 썩 좋지 않다는 점입니다. 코드가 깔끔하고 가독성이 좋아야 눈으로 로직 파악이 가능하고 디버깅이 쉬워지기 때문이죠. 그리고 또 async/await로 코드의 양도 줄일 수 있습니다.

 

 


 

const makeRequest = () =>
    getJSON()
    .then(data => {
        console.log(data);
        return "done";
    })
    
makeRequest();

먼저 Promise로 작성된 makeRequest()라는 함수를 살펴봅시다.

 

 

const makeRequest = async () => {
    console.log(await getJSON());
    return "done";
}

makeRequest();

그리고 이건 async/await으로 작성된 똑같은 코드입니다. 이 쪽이 훨씬 더 깔끔하고 직관적이지 않나요.

 

 

 

 


 

async 사용하기

 

function workP(sec) {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
          resolve(new Date().toISOString());
      }, sec*1000);
  });
}

function justFunc() {
  return 'just Function';
}

async function asyncFunc() {
  return 'async Fucntion';
}

console.log(justFunc());
console.log(asyncFunc());
console.log(workP());

여기 3가지의 함수가 있습니다. 

 

  • workP() : Promise로 구현된 함수
  • justFunc() : 일반 함수
  • asyncFunc() : async를 사용한 함수

 

이 세 함수의 정보를 로그에 찍어보면 이와 같습니다.

 

일반 함수인 justFunc()은 리턴으로 준 문자열 'jusf function'이 그대로 리턴되지만,

asyncFunc()과 workP()는 둘 다 Promise 객체를 리턴하는 것을 확인할 수 있습니다.

 

async는 Promise객체를 리턴하기 때문이죠.

 

 

async function asyncFunc() {
  return 'return value';
}

asyncFunc().then((result) => {
  console.log(result)
});

Promise객체를 리턴하기 때문에 .then()을 연결해 다음 동작을 넣을 수 있습니다. 여기서 .then의 파라미터로 넘겨준 result는 asyncFunc()에서 리턴하는 값이고, 이를 Promise의 then으로 받게됩니다.

 

 

async는 함수를 선언할 때 앞에 붙이고 그 함수를 Promise를 리턴하는 함수로 만들어줍니다. 그 전에는 new Promise()를 통해서 Promise 객체를 만들어주고 Promise를 리턴했지만, 그 과정을 숨길 수 있게 되어 코드가 짧아졌습니다. 또 Promise에서 사용했던 resolve는 async/await에서 return과 동일합니다.

 

 

 


 

await 사용하기

 

function workP(sec) {
  return new Promise((resolve, reject) => {

      setTimeout(() => {
          resolve('workP function');
      }, sec*1000);
  });
}

async function asyncFunc() {
  const result_workP = await workP(3);
  console.log(result_workP);
  return 'async function';
}

asyncFunc().then((result) => {
  console.log(result)
});

asyncFunc()을 보면, 여기서 workP()의 결과가 나중에 리턴된 것을 볼 수 있고 이는 비동기식으로 함수가 실행되었다는 것을 의미합니다. 여기서 workP()의 결과를 받은 후에 asyncFunc()을 실행하고 싶다면 어떻게 해야할까요? 이때 사용하는 것이 바로 await입니다.

 

 

 

async function asyncFunc() {
  await workP(3);  
  return 'async function';  
}  

workP()함수를 호출하기 전에 await만 걸어 실행해 봅니다. 그러면 3초 뒤에 'aync function'  문자열이 콘솔에 찍히게 되는데, 이는 workP()실행 후 asyncFunc()이 실행되었고 동기적으로 코드가 실행된 것을 확인할 수 있습니다.

 

 

function workP(sec) {
    return new Promise((resolve, reject) => {

        setTimeout(() => {
            resolve('workP function');
        }, sec * 1000);
    });
}

async function asyncFunc() {
    const result_workP = await workP(3);
    console.log(result_workP);
    return 'async function';
}

asyncFunc().then((result) => {
    console.log(result)
});

await을 붙이면 await이 붙은 함수의 실행이 끝나는 동안 기다리게 되므로 다음 코드를 실행할 수 없게 됩니다. 그리고 await을 붙인 함수의 결과 값을 변수에 넣어 위 예제처럼 출력할 수 있고 then을 이용해 다음 로직을 연결해 주어도 됩니다.

 

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.