나는 이제 동기와 비동기가 뭔지 헷갈리는 와아아아아앙-초보는 아니다. 근데 이전에는 이것 때문에 짜증이 많이 났었다. 무슨 글을 읽어봐도 다 비슷한 똑같은 소리를 하는데 하나같이 말 자체가 이해가 안됐다.(물론 와아아아앙-초보라서 이해를 못한것이지 좋은 글들이었을 것이다.)
잔말말고,
동기적 실행 : (코드의) 순서를 지키며 실행한다.
비동기적 실행 : (코드의) 순서를 어기며 실행한다.
형용사가 아니다. 서술어인 '실행하다'를 꾸며주는 부사다. 차근차근 한줄씩 실행하면 동기적으로 실행하는거고, 아 필요없고 입맛대로 이것저것 실행하면 비동기적으로 실행하는거다. 기본 개념 설명하는 글에서 '비동기 처리', '동기 처리' 이런식으로 압축된 표현 쓰지 말아주길 바란다, 제발.
한 줄 한 줄, 순서대로 하면(동기적으로 실행하면) 쉽고 좋은데, 왜 일부러 순서를 어기나(비동기적으로 실행하나)? 왜냐면 어떤 코드들은 실행 완료하는데 오래 걸리기 때문이다.
모든 코드가 다 기다릴만한 가치가 있지는 않다. 예를들어 맛집 검색한다고 어떤 블로그에 접속했는데, 초고화질 애드센스 광고를 보여주는 코드가 앞서 모두 완료 될 때까지 진짜 보고싶던 정보를 보여주는 코드가 기다리고만 있으면 사용자는 몹시 괴로울 것이다.
일상 생활을 예로 들어보자. 내가 학생 때 썼던 컴퓨터는 켜지는데 한 세월이었다. 학교 끝나고 집에오면 컴퓨터 전원 누르고, 교복 벗고, 부엌에서 간식 챙겨오면 부팅이 완료됐는데, 딱 1분 컷이었다. 근데 이 과정을 동기적으로 실행한다면 어떨까?
컴퓨터 켠다. (1분)
(↑ 완료 후)교복 갈아입는다. (30초)
(↑ 완료 후)부엌에서 간식 가져온다. (30초)
총 2분, 무려 2배의 시간이 걸리는 것이다.
이같은 코드의 동기적 실행의 단점을 보완하기 위해 비동기적으로 실행하는 방법이 있는 것이다.
앞서 말해두지만 비동기를 사용하는것이 아니다. 비동기는 물건이 아니다. 비동기는 기술이 아니다. 비동기는 사용할수 있는게 아니다. 비동기는 먹는게 아니다. 비동기는 코드가 순서를 무시하고 지 맘대로 실행됨을 이르는 말이다.
용례를 통해 앞으로의 나날에 용어를 명확하게 사용하도록 주의하자. 참고로 비동기적인 실행은 함수 단위로 일어난다.
용례)
"이 함수는 비동기적으로 실행되는구나!"
"http 통신을 쉽게 하도록 도와주는 fetch 모듈이나 axios모듈의 메소드는 비동기적으로 실행되는구나!"
함수가 비동기적으로 실행된다는 것은 달리말하면 함수가 Promise객체를 리턴한다는 것이다. 이 Promise객체는 함수 실행의 상태와 결과 두가지 값이 들어있다. 결국 우리는 이중에 결과를 사용하고 싶은 것이다.
예를 들어보자.
function getAndLogUserInfo() => {
const userInfo = axios.get('http://www.my-website.com/userInfo');
console.log(userInfo)
}
getAndLogUserInfo(); // Promise<pending>
http통신을 요청하는 axios모듈의 get메소드는 비동기적으로 실행된다. 즉, Promise객체를 리턴한다. 위 예시에서 console.log의 결과가 Promise객체인 것은 그래서 매우 당연하다.
위에서 Promise객체가 상태와 결과를 가진다고 했는데, 단어 뜻 그대로 pending 상태인 경우엔 결과가 없다. 상태가 fulfilled 또는 rejected인 경우에만 결과가 있다. console.log가 pending으로 나오는 것은 비동기적으로 실행되는 axios.get(...) 메소드의 결과가 나오기까지 기다리지 않고 너무 빨리 console.log를 실행했기 때문이다.
그러면 간단해진다. axios.get(...) 함수의 결과가 나올 때 까지 기다리게 만들면 된다. 그 방법은 async/await구문을 추가하는 것이다.
아래와 같이 추가해 보자.
async function getAndLogUserInfo() => {
const userInfo = await axios.get('http://www.my-website.com/userInfo');
console.log(userInfo)
}
getAndLogUserInfo(); // [user1Info, user2Info, ...]
이처럼 await 구문은 비동기적으로 실행되는 함수가 실행 완료 될 때까지 기다리게 만들어준다. async 구문은 (async 구문이 붙은)함수 내부에서 await 구문을 사용할 수 있게 만들어주는 역할이다.
기특하구나 ^^