우선 동기(synchronous : 동시에 일어나는)에 대해서 알아보자. 동기식 처리 모델(Synchronous processing model)은 순서대로 일을 처리한다. 일들이 순차적으로 실행되며 어떤 작업이 수행중이면 다음 작업은 그 다음에 실행된다.
일상에서 계산대 앞에 줄을 서면 한명씩 응대하고 한 사람이 끝나면 그 다음 사람을 주문 받는 것 처럼 순차적으로 이루어지는 행위를 말한다. 이런 상황을 프로그래밍에 가져와서 생각해보자면, 코드는 보통 위에서 아래로 내려가면서 순차적으로 작동한다.
비동기식 처리 모델(Asynchronous processing model 또는 Non-Blocking processing model)은 병렬적으로 태스크를 수행한다. 병렬적으로 수행 된다(?) 처음에는 이 말이 와닿지 않을 수도 있다.
보통 프론트엔드 에서는 data를 서버에서 fetch(서버로 네트워크 요청을 보내고 응답을 받는 행위)를 자주 하게 된다. 또 다른 예시로는 콜백 함수, Promise, async await, setTimeout 등과 같은 비동기 함수를 만나면 일을 잠시 미루어둔다.
왜 일을 미루는 걸까? 서버에 요청-응답 받는 시간동안 실행이 지연되기 때문이다. 만약에 fetch를 하는 동안에 화면이 멈춰 있다면 사용자들은 좋은 경험을 갖지 못하고 서비스 이탈을 할 확률이 높아질 것이다.
그래서 자바스크립트는 시간이 얼마나 걸릴지 모르는 비동기 작업을 가장 후 순위로 미루어두고 가장 마지막에 처리한다. 이렇게 하면 태스크들은 서버에 데이터를 요청하고 데이터가 응답될 때까지 기다리지 않아도 된다.
비동기 처리를 이해하기 위해서는 자바스크립트 엔진의 동작과정을 이해하는게 좋다고 생각합니다 :)
동기적인 코드는 call stack에 쌓인다. 비동기 코드는 call stack에 쌓인 모든 코드들이 제거되었을때 event queue에서 다시 call stack으로 넘어가서 실행된다.
작업이 요청되면(함수가 호출되면) 요청된 작업은 순차적으로 Call stack에 쌓이게 되고 순차적으로 실행된다. 자바스크립트는 단 하나의 Call stack을 사용하기 때문에 해당 task가 종료하기 전까지는 다른 어떤 task도 수행될 수 없다.
Web API는 브라우저에서 제공하는 API로 DOM, Ajax, TimeOut 등이 있다.
Call stack에서 실행된 비동기 함수는 Web API를 호출하고, Web API는 콜백 함수를 Task Queue에 넣는다.
비동기 처리 함수의 콜백 함수, 비동기식 이벤트 핸들러, Timer함수(setTimeout(). setInterval())의 콜백 함수가 보관되는 영역으로 이벤트 루프(Event Loop)에 의해 특정 시점(Call Stack이 비어졌을때)에 순차적으로 call stack으로 이동되어 실행된다.
Call stack 내에서 현재 실행중인 task가 있는지 그리고 Event Queue에 task가 있는지 반복하여 확인한다. 만약 Call Stack이 비어있다면 Event Queue 내의 task가 Call stack으로 이동하고 실행된다.
실습 링크 >> http://latentflip.com/loupe
'백문이불여일견 百聞不如一見' 백 번 듣는 것보다 한 번 보는 것이 낫다는 뜻 처럼 이론만 익히고서는 이해가 부족할 수 있습니다.
코드와 이벤트를 반복적으로 보면서 이해해보도록 합시다. (+ 💡 추가로 이벤트 핸들러의 동작과정도 이해 할 수 있다.)