동기
: 한 작업이 실행되는 동안 다른 작업은 멈춘 상태를 유지하고 자신의 차례를 기다리는 것.
비동기
: 어떠한 요청을 보내면 그 요청이 끝날 때까지 기다리는 것이 아니라, 응답에 관계없이 바로 다음 동작이 실행되는 것.
JS는 한 번에 하나의 작업
을 수행하는 동기식 언어이다. 단일 스레드(Single Thread)라고도 한다.
JS의 엔진을 구성하는 Memory Heap과 Call Stack 때문.
변수와 객체의 메모리 할당을 담당하는 곳
함수가 호출이 되면 쌓이는 곳
JS에서는 먼저 호출한 함수부터 Call Stack에 쌓이고 반환한 이후에는 사라진다.
그리고 다음 함수를 다시 Call Stack에 쌓는다. 이를 LIFO 구조라고 한다. (선입선출)
그런데 특정한 상황에서 이러한 동기식 언어의 특성이 유저에게 불편을 줄 수 있다. 유저에게 빠른 응답을 보낼 수 있도록 JS가 비동기적으로 동작할 수 있어야 한다.
브라우저의 JS Runtime에서는 엔진이 제공하지 않는 일부 기능인 DOM
조작이나 AJAX
같은 비동기 처리를 위한 web API를 제공한다. 이를 제어하기 위해 이벤트 루프(Event Loop)
, 이벤트 큐(Callback Queue 혹은 task Queue)
로 문제를 해결할 수 있다.
Call Stack에서 비동기 함수가 호출되면 Call Stack에 먼저 쌓였다가 Web API(혹은 백그라운드라고도 한다)로 이동한 후 해당 함수가 등록되고 Call Stack에서 사라진다.
Web API(백그라운드)에서 비동기 함수의 이벤트가 발생하면, 해당 콜백 함수는 Callback Queue에 push(이동) 된다.
이제 Call Stack이 비어있는지 이벤트 루프(Event Loop)가 확인을 하는데 만약 비어있으면, Call Stack에 Callback Queue에 있는 콜백 함수를 넘겨준다.(push)
Call Stack에 들어온 함수는 실행이 되고 실행이 끝나면 Call Stack에서 사라진다.