자바스크립트 동기와 비동기 4 - async/await

RN·2024년 6월 24일

자바스크립트

목록 보기
5/11

1. async/await을 사용하는 이유


이전 포스트 막간에서 async, await 를 사용하는 이유를 대충 살펴보았다.

Promise 를 이용해서 콜백 지옥에서 벗어났고, 코드의 가독성도 굉장히 좋아졌었다.

하지만 우리도 봤다시피 이전 포스트의 코드는 솔직히 너무 간단하다. 그러니 가독성이 좋을 수 밖에 없다.

그런데 진짜 프로미스도 콜백 지옥처럼 가독성이 안좋아질까?

위의 코드를 보면 알겠다시피 프로미스가 3중첩 되어 이해하기가 쉽지 않아졌다. 딱히 then 에 전달한 콜백이 하는 것이 별로 없는데도 말이다.

코드의 구조는 간단하게 설명하면

  1. 햄버거만들기() 시작
  2. 빵만들기() 시작 후 빵을 완성. 만든 빵을 아래로 전달
  3. 빵만들기가 완성되었으니 그 다음은 패티를 만들자. 만든 패티를 아래로 전달.
  4. 패티를 만들었으니 다음으로 양상추를 만들자.
  5. 완성된 빵, 패티, 양상추를 한 곳으로 모아 합쳐서 반환하여 햄버거 만들기 완성

아, 위의 코드를 봤으니 프로미스도 콜백 지옥처럼 가독성이 충분히 떨어질 수 있구나.

그럼 async / await 은 어떻게 사용하는 걸까 알아보자.




1.2 async


직접 작성해보니 async 는 오히려 프로미스보다 사용이 더 간편했다.

함수 앞에 async 라는 키워드만 작성해주면 함수의 블록 자체가 프로미스로 변환된다.

그래서 아래와 같이 랜덤웹툰보기()를 출력하면 프로미스 객체가 반환된다는 것을 알 수 있고, .then() 이나 .catch, .finally 를 연결시킬 수 있다.

1.3 await

랜덤웹툰보기 함수에서 웹툰가져오기 함수를 호출할 때 await 을 사용한 것을 볼 수 있다.

await 은 비동기 함수를 호출할 때 await 을 사용하게 되는데,

await 을 사용하게 되면 await으로 가져온 비동기 함수가 끝날 때까지 아래의 코드를 실행하지 않는다.

위의 코드에서 만약 await 을 사용하지 않았다면 await 아래의 console.log 는
" 가져온 데이터 : undefined " 를 출력했을 것이다.

웹툰가져오기가 비동기 작업이기 때문에 2초가 지나기 전에 그 다음줄의 console.log를 실행하기 때문이다.

위의 코드는 아래처럼 동작한다.

  1. 심심하니까 아무 웹툰이나 추천해줘. 랜덤웹툰보기() 실행
  2. 웹툰가져오기에서 랜덤으로 아무 웹툰을 가져온다. 웹툰가져오기() 실행
  3. 웹툰가져오기()가 await 키워드로 작성되었기 때문에 웹툰을 가져오는 2초 동안 기다린다.
  4. 웹툰을 가져왔으니 console.log("가져온 데이터 : ", 웹툰) 을 실행.
  5. 랜덤으로 가져온 웹툰을 반환한다.
  6. 성공적으로 반환을 받았으니 .then() 과 .finally()에 전달된 콜백을 실행한다.

참고로 await 은 async 가 붙은 함수 안에서만 사용이 가능하며,

await을 붙이고 비동기함수를 부르면 Promise 객체가 아니라 값을 반환한다.

const 웹툰 = 웹툰가져오기() 
// 2초 기다려서 웹툰 가져옴.
console.log(웹툰)  	// {Promise : "화산귀환"} 이 출력된다.

const 웹툰 = await 웹툰가져오기()
console.log(웹툰)  	// "화산귀환" 이 출력된다.



1.4 프로미스와의 비교


위의 코드만으로 뭔가 프로미스랑의 차이가 크게 와닿지 않는다.

한 번 위의 코드를 프로미스로 변경해보자.

위는 async/await 으로 아래는 promise의 .then 체이닝으로 구현했고 같은 결과를 만들어낸다.

매우 간단한 코드임에도 async/await 이 가독성이 훨씬 좋아졌다는 것을 알 수 있다.

그냥 위에서 아래로 순서대로, 즉 동기식으로 작성할 수 있어서 매우 쉽게 읽을 수 있다.

랜덤웹툰보기()는 비동기로 동작하지만 마치 우리가 비동기를 사용하지 않는 코드를 작성하던 자바스크립트 초보였을 때 동기식 프로그래밍을 하는 것처럼 코드를 작성할 수 있다는 매우 큰 장점이 있다는 것을 알 수 있게 됐다.




1.5 프로미스로 인한 콜백 지옥에서 벗어나보자.


우리는 맨 위에서 햄버거 만드는 로직을 통해 프로미스로 인해서도 콜백 지옥이 발생할 수 있다는 것을 알았다.

그럼 async/await으로 이 지옥에서 벗어날 수 있을까?

동일한 로직을 async/await으로 수정해보자.

분명 잘바꿨다고 생각했는데 undefined + undefined + undefined로 출력됐다.

undefined로 출력됐다는 것은 빵과 패티, 양상추에 제대로 데이터가 들어가지 않아서 그런 것 같다.

대체 왜...?


이를 해결하기 위하여 우리는 자바스크립트의 동작 방식에 대해 알아야한다.

자바스크립트는 호출스택(Call stack), 태스크큐(Task Queue), 마이크로태스크큐(Microtask Queue), 이벤트루프(Event Loop) 로 동작하는데 다음 포스트에서 이들에 대해 알아보며 위의 코드를 고쳐보겠다.

0개의 댓글