새소식

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으로 작성된 똑같은 코드입니다. 이 쪽이 훨씬 더 깔끔하고 직관적이지 않나요.

 

 

 

 


 

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과 동일합니다.

 

 

 


 

 

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을 이용해 다음 로직을 연결해 주어도 됩니다.

 

 

 

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

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