이전 포스트 막간에서 async, await 를 사용하는 이유를 대충 살펴보았다.
Promise 를 이용해서 콜백 지옥에서 벗어났고, 코드의 가독성도 굉장히 좋아졌었다.
하지만 우리도 봤다시피 이전 포스트의 코드는 솔직히 너무 간단하다. 그러니 가독성이 좋을 수 밖에 없다.
그런데 진짜 프로미스도 콜백 지옥처럼 가독성이 안좋아질까?


위의 코드를 보면 알겠다시피 프로미스가 3중첩 되어 이해하기가 쉽지 않아졌다. 딱히 then 에 전달한 콜백이 하는 것이 별로 없는데도 말이다.
코드의 구조는 간단하게 설명하면
- 햄버거만들기() 시작
- 빵만들기() 시작 후 빵을 완성. 만든 빵을 아래로 전달
- 빵만들기가 완성되었으니 그 다음은 패티를 만들자. 만든 패티를 아래로 전달.
- 패티를 만들었으니 다음으로 양상추를 만들자.
- 완성된 빵, 패티, 양상추를 한 곳으로 모아 합쳐서 반환하여 햄버거 만들기 완성
아, 위의 코드를 봤으니 프로미스도 콜백 지옥처럼 가독성이 충분히 떨어질 수 있구나.
그럼 async / await 은 어떻게 사용하는 걸까 알아보자.

직접 작성해보니 async 는 오히려 프로미스보다 사용이 더 간편했다.
함수 앞에 async 라는 키워드만 작성해주면 함수의 블록 자체가 프로미스로 변환된다.
그래서 아래와 같이 랜덤웹툰보기()를 출력하면 프로미스 객체가 반환된다는 것을 알 수 있고, .then() 이나 .catch, .finally 를 연결시킬 수 있다.

랜덤웹툰보기 함수에서 웹툰가져오기 함수를 호출할 때 await 을 사용한 것을 볼 수 있다.
await 은 비동기 함수를 호출할 때 await 을 사용하게 되는데,
await 을 사용하게 되면 await으로 가져온 비동기 함수가 끝날 때까지 아래의 코드를 실행하지 않는다.
위의 코드에서 만약 await 을 사용하지 않았다면 await 아래의 console.log 는
" 가져온 데이터 : undefined " 를 출력했을 것이다.
웹툰가져오기가 비동기 작업이기 때문에 2초가 지나기 전에 그 다음줄의 console.log를 실행하기 때문이다.
위의 코드는 아래처럼 동작한다.
- 심심하니까 아무 웹툰이나 추천해줘. 랜덤웹툰보기() 실행
- 웹툰가져오기에서 랜덤으로 아무 웹툰을 가져온다. 웹툰가져오기() 실행
- 웹툰가져오기()가 await 키워드로 작성되었기 때문에 웹툰을 가져오는 2초 동안 기다린다.
- 웹툰을 가져왔으니 console.log("가져온 데이터 : ", 웹툰) 을 실행.
- 랜덤으로 가져온 웹툰을 반환한다.
- 성공적으로 반환을 받았으니 .then() 과 .finally()에 전달된 콜백을 실행한다.
참고로 await 은 async 가 붙은 함수 안에서만 사용이 가능하며,
await을 붙이고 비동기함수를 부르면 Promise 객체가 아니라 값을 반환한다.
const 웹툰 = 웹툰가져오기()
// 2초 기다려서 웹툰 가져옴.
console.log(웹툰) // {Promise : "화산귀환"} 이 출력된다.
const 웹툰 = await 웹툰가져오기()
console.log(웹툰) // "화산귀환" 이 출력된다.
한 번 위의 코드를 프로미스로 변경해보자.

위는 async/await 으로 아래는 promise의 .then 체이닝으로 구현했고 같은 결과를 만들어낸다.
매우 간단한 코드임에도 async/await 이 가독성이 훨씬 좋아졌다는 것을 알 수 있다.
그냥 위에서 아래로 순서대로, 즉 동기식으로 작성할 수 있어서 매우 쉽게 읽을 수 있다.
랜덤웹툰보기()는 비동기로 동작하지만 마치 우리가 비동기를 사용하지 않는 코드를 작성하던 자바스크립트 초보였을 때 동기식 프로그래밍을 하는 것처럼 코드를 작성할 수 있다는 매우 큰 장점이 있다는 것을 알 수 있게 됐다.
우리는 맨 위에서 햄버거 만드는 로직을 통해 프로미스로 인해서도 콜백 지옥이 발생할 수 있다는 것을 알았다.
그럼 async/await으로 이 지옥에서 벗어날 수 있을까?
동일한 로직을 async/await으로 수정해보자.

분명 잘바꿨다고 생각했는데 undefined + undefined + undefined로 출력됐다.
undefined로 출력됐다는 것은 빵과 패티, 양상추에 제대로 데이터가 들어가지 않아서 그런 것 같다.
대체 왜...?
이를 해결하기 위하여 우리는 자바스크립트의 동작 방식에 대해 알아야한다.
자바스크립트는 호출스택(Call stack), 태스크큐(Task Queue), 마이크로태스크큐(Microtask Queue), 이벤트루프(Event Loop) 로 동작하는데 다음 포스트에서 이들에 대해 알아보며 위의 코드를 고쳐보겠다.