-
Async/AwaitTIL/ES6+ 2021. 2. 7. 22:25
저번 포스트 Promise에 이어 ES6+에서 비동기 처리를 할 때 사용하는 Async/Await에 대해 알아봅시다. 💪
Async/Await란
Async와 Await는 단순히 말해 Promise의 업데이트된 버전으로, 편리하고 깔끔한 비동기 코드를 작성할 수 있습니다. 먼저 MDN Document에서 Async와 Await를 어떻게 설명하고 있는지부터 살펴볼까요?
Async
Async를 MDN Document에서 찾아보면 이렇게 설명하고 있습니다.
async function 선언은 AsyncFunction객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 Promise를 사용하여 결과를 반환합니다.
간단히 한 줄로 정리하자면, Async 함수는 Promise 객체를 반환하는 함수인 것입니다. 즉,
async function test() { return 1; }
이 코드는
function test() { return Promise.resolve(1); }
이 코드와 같습니다.
Async를 사용하는 방법은 함수 앞에
async
키워드를 붙여주는 것입니다. 아래처럼요!const getMoives = async() => { // action }; // 혹은 async getMovies function() { // action }
Await
이번엔 Async와 짝처럼 함께 다니는 Await를 MDN Document에서 찾아보면 다음과 같이 설명합니다.
await 문은 Promise가 fulfill 되거나 reject 될 때까지 async 함수의 실행을 일시 정지하고, Promise가 fulfill 되면 async 함수를 일시 정지한 부분부터 실행합니다. 이때 await 문의 반환 값은 Promise에서 fulfill 된 값이 됩니다.
이해가 가시나요? 즉,
await
문장은 Promise가 resolve되든 reject 되든 Promise의 작업이 끝날 때까지 기다립니다.위의 두 내용을 조합해보면, 우리는 async function과 await 구문을 이용해
Promise
와.then()
,.resolve()
와 같은 구문 없이 비동기 작업을 처리할 수 있다는 뜻입니다! 그럼 코드를 볼까요? 💻Async/Await 자세히 보기
먼저, Promise의 업데이트된 버전이라는 것을 보기 위해 Promise 버전과 Async/Await 버전으로 같은 코드를 작성해보겠습니다.
Promise
API 링크
URL
을fetch
해서 response 데이터들을 콘솔에 출력하는 기본적인 Promise 구문입니다.then()
함수와catch()
로fetch
에서 리턴된 Promise의 fulfilled 상태와 rejected 상태에 대한 처리를 실행합니다. 문제가 없다면res
와json
이 콘솔에 출력되겠죠?const getList = () => { fetch(URL) .then(res => { console.log(res); return res.json(); }) .then(json => console.log(json)) .catch(e => console.log(e)); }
그럼 이 코드를 똑같이 Async/Await 버전으로 작성해봅시다.
Async/Await
const getList = async() => { try{ const res = await fetch(URL); const json = await res.json(); }catch(e){ console.log(e); } };
짠! 어떤가요? 훨씬 더 보기 좋고 깔끔해보이지 않나요? 코드를 차근차근 살펴봅시다.
Promise와 비교하기
await
가장 큰 차이점은
then
과catch
가 없다는 점입니다. 대신fetch
구문과json
구문 앞에await
키워드가 붙어있고 함수가 async 함수입니다. 위에서 보았듯,await
키워드는 Promise의 작업이 끝날 때까지 기다리는 역할을 수행합니다. 따라서fetch
가 리턴한 Promise가 끝날 때까지 기다리고 그 결과를res
에 저장res.json()
이 리턴한 Promise가 끝날 때까지 기다리고 그 결과를json
에 저장
이런 순서로 비동기 처리가 실행되는 겁니다. 단, 이
await
를 사용하려면 반드시 함수를 async 함수로 만들어줘야하는 걸 잊지 마세요!try-catch
또다른 점은
catch()
메서드를 사용하지 않고 평범한try-catch
구문을 사용한다는 점입니다. Promise가 fulfilled 상태가 되면try
블럭 안의 내용을 실행하고 실행되던 중 오류가 발생하면catch
블럭에서 처리하는 것입니다. Promise의catch()
메서드처럼catch
블럭에서는 Promise가 rejected 되는 상태와 Promise와 관련 없이try
블럭에서 발생하는 오류 모두를 잡아냅니다.finally는?
Promise에서도
finally
가 있었던 것을 기억하시나요? 다시 한번 복기하자면,finally
는 Promise가 resolve 되든 reject 되든 상태에 관계없이 무조건 실행되는 메서드입니다. Async/Await를 사용할 때finally
메셔드는try-catch
의finally
로 사용하면 됩니다.const getList = async() => { try{ const res = await fetch(URL); const json = await res.json(); }catch(e){ console.log(e); }finally{ console.log('TA-DA 🥳') } };
이렇게요! 그럼
try
블럭 안에서 오류가 나든 성공적으로 작업이 진행되든 마지막에는console.log('TA-DA 🥳')
가 실행됩니다.Parallel Async/Await
만약, 여러 비동기 처리를 병렬적으로 진행하고 싶다면 어떻게 해야 할까요?
Promise.all()
의 도움을 받으면 할 수 있습니다! 두 API를 fetch해서 response의 json을 얻는 코드를 작성해보겠습니다.const getLists = async() => { try{ const [list1, list2] = await Promise.all([fetch(URL1), feetch(URL2)]); const [list1Json, list2Json = await Promise.all([list1.json(), list2.json()]); console.log(list1Json, list2Json); }catch(e){ console.log(e); } };
어떤가요? Array의 구조 분해 할당을 이용해
Promise.all()
에서 리턴되는 response 배열을list1
,list2
에 저장했습니다. 그런 다음, 다시Promise.all()
을 이용해json
메서드를 호출했습니다. 물론await
키워드로 비동기 처리가 끝날 때까지 기다리고try-catch
를 사용해줬습니다.
현재 업무 코드에서도 사용하고 있는 Async/Await에 대해 정리했습니다! 이전 포스트인 Promise와 함께 봐주시면 더 좋을 것 같네요! 오류나 오타 수정 등의 댓글은 언제나 감사합니다!
'TIL > ES6+' 카테고리의 다른 글
Promise (0) 2021.01.26 Default Value & Destructuring (0) 2021.01.02 Array Function2 (0) 2020.12.10 Array Function (0) 2020.12.07 For Loop (0) 2020.12.05