참고영상
https://youtu.be/4Fyv07LrGhc
https://youtu.be/zi-IG6VHBh8
자바스크립트는 하나의 스레드에서 작업들을 처리하기 때문에 블로킹을 하고 하나의 이벤트를 처리하게 되면 그 이벤트가 다 처리될 동안 다른 작업을 할 수 없다.
싱글 스레드라는 건 콜스택이 하나라는 것과 같은 의미이다.
자바스크립트는 싱글 쓰레드지만 논블로킹으로 작업을 한다.
논블로킹을 하게 되면 작업들이 서로 블로킹을 하지 않는다는 의미로 하나의 작업이 실행되고 있는 중에도 다른 작업이 가능한 것을 의미한다.
논 블로킹으로 작업 1이 실행되는 중에 작업 2가 실행될 때 이 작업 2가 실행되는 공간이 아래 자바스크립트 실행 환경 중 브라우저 설명에서 나오는 Web API이다.
우리가 작성한 JS파일은 컴퓨터가 인식할 수 없다. 이 JS파일을 메모리 힙과 콜스택을 이용하여 컴퓨터가 알아들을 수 있게 컴퓨터 언어로 바꿔주는 역할을 하는 것이 자바스크립트 엔진이다.
메모리 힙
우리가 선언한 변수들이 어디에 저장되었는지 기록하는 장치.
콜 스택
콜(function 호출)을 스택처럼 저장하고 실행하는 역할을 담당하여 콜스택을 통해 어떤 함수가 실행되는 중인지를 알 수 있다.
자바스크립트가 실행되는 환경은 OS, 브라우저, Node.JS일 수 있다.
브라우저에서 실행되면 자바스크립트 엔진은 브라우저가 제공하는 Web API(DOM, AJAX, Timeout 등)들을 사용할 수 있다.
자바스크립트는 이벤트를 기반으로, 이벤트 단위로 실행된다는 의미이다.
함수를 실행시키면 해당 함수에 있는 아직 호출(실행)된 게 아닌 콜백함수(어떤 function에 인자로 전달되는 함수, 어떤 일이 완료된 다음 실행되는 함수)들을 Web API에 담고 이 콜백함수들을 바로 호출 스택에 넣어주는 게 아니라 태스크 큐로 보낸다.
이벤트 루프는 호출스택이 비어있을 때 태스크 큐 안에 있는 콜백함수들을 꺼내서 호출스택에 넣어준다.
호출스택에 올라간 함수들은 실행되고 실행을 마치면 스택에서 사라진다.
이렇게 백그라운드 -> 태스크 큐 -> 이벤트 루프에 의해서 호출스택 -> 실행, 스택에서 사라짐 -> 백그라운드 -> 태스크 큐 -> 이벤트 루프에 의해서 호출스택... 반복 되는 것이 비동기 실행 과정이다.
예를들어
console.log("Hi");
setTimeout(function cb1() {
console.log("cb1");
}, 5000);
console.log("Bye");
위 코드가 실행되는 과정은
console.log("Hi"); 가 콜스택에 쌓인 뒤 실행된다.
setTimeout이 콜백함수인 cb1과 함께 콜스택에 쌓인다. setTimeout은 실행되면 Web API의 Timer API를 호출한다.
따라서 여기서 setTimeout이 실행되면 Web API에 Timer가 cb1 이라는 콜백함수를 가지고 등록된다.
setTimeout은 이미 실행 됐으니까 콜스택에서 사라진다.
콜스택은 비어있으면 다음줄에 있는 function을 등록시킨다. 따라서 console.log("Bye")를 콜스택에 쌓고 실행한다.
Web API에 등록된 Timer의 시간이 다 지나면 Timer가 갖고 있던 콜백함수인 cb1을 태스크큐에 저장한다.
태스크 큐가 텅 비면 이벤트 루프가 태스크 큐에 제일 처음 들어온 값을 콜스택으로 올려준다.
콜스택은 이벤트 루프가 올려준 함수를 실행시키고 콜스택은 비게 된다.
태스크 큐는 하나가 아닌 여러개가 있고 백그라운드에 있는 콜백함수들이 각각 다른 태스크 큐에 담긴다. 이벤트 루프는 이런 각 태스크 큐에 담긴 콜백함수들을 우선순위를 정해서 순서대로 호출스택에 올려주는 역할도 한다.
참고할만한 문서들이 많다.
https://ko.javascript.info/event-loop
https://meetup.toast.com/posts/89
https://chanmi-lee.github.io/articles/2020-06/JavaScript-Visualized-Event-Loop
이 문서들을 참고했을 때 그림에 나온 백그라운드는 WebAPI를 의미한다.