티스토리 뷰

728x90

async와 await

 


비동기 구조

 

공공 데이터 api를 요청하고 이 데이터셋을 전역변수인 data에 넣어 ejs에 인자로 넘겨주려고 했는데 

request.get의 콜백함수에서 아무리 변수값을 바꾸어봐도 console.log를 찍어보면 undefined만 출력되었다. 

그래서 원인을 찾아보니 JS의 비동기 구조 때문에 이러한 현상이 일어나는 것이었다.

 

비동기구조란 특정 코드가 종료되지 않았어도 대기하지 않고 다음 코드를 실행하는 자바스크립트의 특성이다.

 

간단한 예시를 들어보자면,

 

console.log("시작");
setTimeout(function(){
    console.log("3초후 실행");
}, 3000);
console.log("끝");



// 시작
// 끝
// 3초후 실행

 

위와 같은 코드를 실행했을 때 동기적으로 동작하는 경우 시작, 3초후 실행, 끝 의 순으로 출력될 것이다.

그러나 비동기구조에서는 순서대로 실행하되 이전 함수의 종료를 기다리지 않고 다음 함수가 실행된다.

따라서 시작, 끝이 출력되고 3000ms, 즉 3초를 기다리고 실행되는 setTimeout이 뒤늦게 실행되는 것이다.

 

나한테 발생한 문제도 이와 비슷했다.

 

 

 

콜백 함수에서 아무리 전역변수로 선언한 data에 값을 삽입해도 실제로 출력하면 undefined가 출력되는 것이다.

 

이제 원인을 알았으니 해결방법을 찾아보자

 


async와 await

 

async와 await는 자바스크립트의 비동기 처리 패턴 중 최근에 나온 문법이라고 한다. 자바스크립트는 싱글스레드로 동작하는 언어이기 때문에 비동기식 처리가 필수적 요소라고 한다. 또한, 비동기식 처리는 내가 겪었던 문제와 같이 결과에 어떤 문제가 생길지 예측할 수 없으므로 동기적인 처리를 할 수 있게 해주어야 한다. 이 방법이 promise와 callback이라고 하는데 callback은 알고 있으니 promise를 먼저 알아보아야 할 것 같다.

 

 

promise란?

 

프로미스는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용한다.

일반적으로 우리가 웹 애플리케이션을 구현할 때 서버에서 데이터를 요청하고 받아오기 위해 아래와 같은 API를 사용한다.

$.get('url 주소/products/1', function(response) {
  // ...
});
 

위 API가 실행되면 서버에다가 ‘데이터 하나 보내주세요’ 라는 요청을 보내게 된다. 그런데 여기서 데이터를 받아오기도 전에 마치 데이터를 다 받아온 것 마냥 화면에 데이터를 표시하려고 하면 오류가 발생하거나 빈 화면이 뜨게 된다. 이러한 문제점을 해결하기 위해 나온 개념이 promise이다.

 

 

다시 async와 await

 

async는 promise의 코드를 깔끔하게 줄여주기 때문에 가독성을 높혀주는 효과가 있다. 사용법은 function 앞에 async만 붙여주면 되고 비동기로 처리되는 부분 앞에 await만 붙여주면 된다. 그리고 한가지 알아둬야 할 점은 await 뒤에 오는 부분은 반드시 promise를 반환해주어야 하고, async가 붙은 function도 promise를 반환해야 한다는 점이다. 사용법의 예시는 아래와 같다. 

 

async function test() {
    // logic
}

변수 = async() => {
	// logic
}

그러면 이번에는 promise와 async & await를 사용했을 때 어떤 차이가 있는지를 알아보자.

let asyncFunc1 = (msg) => {
    new Promise((resolve) => {
        setTimeout(() => {
            resolve(`func1 : ${msg}`);
        }, 1000);
    })
};

let asyncFunc2 = (msg) => {
    new Promise((resolve) => {
        setTimeout((resolve) => {
            resolve(`func2 : ${msg}`);
        }, 1000)
    })
}

위와 같이 promise를 반환하면 함수 2개가 있다고 가정하자. 아래는 promise를 썼을 때의 예시이다.

function promiseMain() {
    asyncFunc1('Hello').then((result) => {
        console.log(result);
        return asyncFunc2('world')
    }).then((result) => {
        console.log(result);
    })
}

이번에는 async & await를 사용하였을 때의 코드이다.

async function asyncMain() {
    let result = await asyncFunc1('Heello');
    console.log(result);
    result = await asyncFunc2('world');
    console.log(result);
}

이렇게 짧은 코드로만 비교하여도 확실히 async & await을 사용하는 것이 promise보다 가독성이 좋다는 것을 알 수 있다. 

 


 

 

데이터 받아오기

 

문제를 해결하기 위해 async와 await를 함수 앞부분에 넣어주었고,  async함수는 promise 객체를 반환하게 하였다.

 

 

이렇게 구현하고 다시 data를 출력해보니

 

 

이렇게 원하는 결과물이 담겨있는 변수를 얻게 되었다.

 

 

참고 :

 

https://joshua1988.github.io/web-development/javascript/js-async-await/

https://pythonq.com/so/node.js/156047

https://devlog-wjdrbs96.tistory.com/163

320x100
댓글
© 2022 WonSeok, All rights reserved