클라이언트 측에서 보내는 2가지 요청이 있다. 첫번째는 맥주를 달라는 것이고 두번째는 숙취를 보내고 알약을 받아오는 것이다.
두 함수 모두 async / await 를 사용했다. 차이는 무엇일까?
getBeer의 setState는 앞에 await 가 붙고, postHangover에는 붙지 않았다. 어떤게 맞는 것일까?
결과를 먼저 이야기하자면 setState에는 await를 사용할 수 없다.
async / await 의 기반은 promise 다. async 함수는 promise를 반환하고 promise가 함수로부터 반환할 값을 resolve 한다.
setState는 promise를 리턴하지 않기에 await와 함께 사용할 수 없다.
그렇다면 setState는 어떤식으로 작동할까?
setState는 항상 즉시 컴포넌트를 업데이트 하지 않는다. 비동기적으로 작동하기 때문에 setState() 를 호출하고 바로 다음에 this.state를 읽으려하면 원하는 결과가 나오지 않는다.
componentDidUpdate 나 setState 콜백을 사용해야 원하는 결과를 얻을 수 있다.
위 코드를 실행하면 beer를 얻을 수 없다.
하지만 콜백을 사용하면 beer를 얻을 수 있다.
*지금은 간략하게 정리하고 setState가 비동기적으로 처리되는 이유에 대해서는 다른 포스팅에서 풀어보고자 한다.
await 와 setState가 버무려진 다른 예를 살펴보자
위 코드를 돌려보면 결과는 아래와 같다.
마치 setState가 awiat와 함께 동작하는 것 처럼 보인다.
하나씩 살펴보자.
changeAndValidate을 호출하면 await 가 붙은 this.handleChange가 실행된다. handleChange 에서 setState가 호출되면서 setState는 업데이터를 부른다. 위에서 말했던 것 처럼 비동기적으로 처리되기 때문에 바로 업데이트는 되지 않는다. 이어서 console.log(synchronous code)가 찍히게 된다.
최종적으로 handleChange는 undefined를 리턴하게 된다. await 는 undefined를 받아 Promise.resolve(undefined)를 사용해 event queue 로 undefined를 넘겨준다.
event loop에서는 먼저 들어왔던 setState의 업데이터를 실행시킨다. 이제 콘솔에 updated component 가 찍힌다.
이어서 event loop가 undefined를 집어들고 Promise.resolve() 가 드디어 종료된다. 더 이상 await 가 기다릴 것이 없으니 나머지 코드가 진행된다.
드디어 콘솔에 asynchronous validation code가 찍히며 끝이난다.
방금 예제는 stack overflow에서 관련 자료들을 찾다가 발견했다. 재미있는 자료같아서 간단히 정리했다. 자세한 내용은 아래 링크를 통해 살펴볼 수 있다.
이번 포스팅을 하게 된 계기가 있는데, 별다른 생각없이 사용하고 있던 async / await 에 대해, setState에 대해 조금 더 알아갈 수 있는 기회가 된것 같아 기쁘다. 부족함은 부끄러운게 아냐 부족함을 알면서도 채워갈 생각이 없는게 부끄러운거지(라고 나를 토닥여본다).
잘못된 부분이나 추가할 부분들에 대한 의견은 언제나 환영입니다.
참고자료