이 글은 콜백함수와 Promise에 이은 비동기 시리즈의 마지막편입니다.
오늘은 드디어 비동기 처리의 마지막 편이다. Async와 Await은 promise를 좀 더 편하게 사용할 수 있는 비동기의 꽃! 비동기의 보물!이다.
async와 await은 promise를 기반으로 만들어진 것이다. 따라서 하나의 새로운 기능이 아니라, promise라는 비동기 처리 위에 있는 간편한 API와 같다는 것을 알고 넘어가자.
await은 메소드의 실행을 일단 중지시킨다. promise의 값이 실행되기 전까지 '기다려!'라는 뜻이다.
promise는 하나의 '예약 시스템'이었다. '내가 준 콜백함수는 시간이 되었을 때 다시 불러줘~'하는 것처럼 작업을 실행해야하는 순간이 왔을 때 콜백함수를 실행해준다.
위의 코드처럼 resolve나 reject를 호출하지 않을 경우에는 콘솔에 찍히는 것처럼 계속 pending상태로 출력이 된다. 결과값도 없는 것이 보인다.
따라서 다음처럼 resolve나 reject를 호출해줘야 결과값이 나온다.
resolve를 호출한 결과, fulfilled 상태로 변하고 결과는 'success'로 변한 것을 볼 수 있다.
위처럼 user.then(console.log)로 then까지 써주면 콘솔에 success라는 결과 값이 출력된다.
아래처럼 async를 넣고 promise를 빼면 더 편리하게 비동기 코드를 작성할 수 있다.
이렇게 똑같이 promise로 출력이되는 것을 알 수 있다!
Await은 async가 붙은 함수에서만 쓸 수 있다.
위의 코드처럼 await은 메소드를 체이닝하지 않고도 편리하게 쓸 수 있다.
자 위와 같은 비동기 함수를 만들었다고 하자. 정상적으로 사과를 받아오고 난 뒤에 바나나를 받아오는 promise이다. 하지만 체이닝된 함수의 형태를 보면 콜백 지옥과 같이 로직이 보다 이해하기 어렵고 디버깅하기 어려운 형태가 된다. 이처럼 프로미스도 중첩을 여러번 시키면 콜백 지옥과 같은 문제점이 발생한다.
따라서 async와 await으로 리팩토링을 해보자.
이렇게 async와 await을 넣어 간편하게 리팩토링 해줄 수 있다.
그렇다면 에러 핸들링의 경우엔 어떻게 할까?
이렇게 try, catch문을 활용해서 error 핸들링을 해줄 수 있다.
하지만 이 함수에서도 문제점이 보인다. getApple()과 getBanana()는 순차적으로 이뤄지고 6초나 걸린다. 하지만 이 둘은 딱히 순차적으로 이뤄질 필요가 없는 독립적인 함수이다. 이 둘을 동시에 처리할 수 있게 할 순 없을까..?
이것을 개선하려면 위처럼 applePromise와 bananaPromise를 만들어서 promise가 바로 실행되도록 해줄 수 있다. 이렇게 실행하면 병렬적으로 실행되어 3초만에 결과값이 나온다.
하지만 이 방법도 옳은 방법은 아니다.
이 때 사용하는 아주 유용한 API는 바로 Promise.all() 이다.
이 함수는 배열 안에 있는 promise들을 병렬적으로 실행해서 모든 결과값이 나올 때까지 기다려주는 함수다.
이렇게 해도 결과값은 같다.
또 다른 유용한 promise API는 Promise.race()다. 이 API를 이용하면 배열에 전달된 promise 중에서 가장 먼저 전달된 데이터만 호출한다.
위처럼 바나나가 1초만에 전달되었기 때문에 바나나가 호출이 된 것을 알 수 있다.
여기까지.... 그동안 비동기 처리를 하면서 정확히 이해하지 못한 부분에 대해 정리할 수 있어서 좋았다.
이제껏 then then 구문을 애용해왔었는데, async와 await을 보다 써보고 싶고 무심코 지나쳤던 error handling까지 완벽하게 구현하도록 해야겠다고 반성해보며... 이번 비동기 시리즈를 마친다!
참고자료 //
https://joshua1988.github.io/web-development/javascript/js-async-await/
드림코딩 by 엘리