자바스크립트 엔진은 싱글 스레드 방식으로 동작하지만, 브라우저는 멀티 스레드로 동작한다.
23장 포스트에서 사용했던 스택 구조에 대한 이미지다.
스택은 LIFO 구조를 가지며 실행된다.
const foo = () => {};
const bar = () => {};
foo(); // 1함수
bar(); // 2함수
위 예제는 다음 방식으로 실행된다.
즉, 호출된 순서대로 실행 컨텍스트 스택에 푸시되어 실행된다.
자바스크립트 엔진은 싱글 스레드로 동작하고 단 하나의 실행 컨텍스트 실행을 가진다는 말은, 한 번에 하나의 태스크만 실행할 수 있다는 것이다.
그러면 1함수가 실행되는 동안은 다른 함수들은 블로킹이 발생한다.
이와 같이 현재 실행 중인 태스크가 종료할 때까지 다음에 실행될 태스크가 대기하는 방식을 동기 처리
라고 한다.
그렇다면 비동기 처리는 무엇일까.
현재 실행 중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행하는 방식이다.
통상적인 예로는 타이머 함수인 setTimeout, setInterval, HTTP 요청, 이벤트 핸들러가 있다.
이전 포스팅에서 설명했던 이벤트 루프, 태스크 큐, 콜 스택의 구조에서 동기와 비동기 방식이 어떻게 이루어지는 알아보자.
function foo() {
console.log('foo');
}
function bar() {
console.log('bar');
}
setTimeout(foo, 0); // 0초(실제로 4ms) 후에 foo 함수가 호출됨
bar();
4-1 [브라우저] 타이머의 만료를 기다리고, 타이머가 만료되면 콜백 함수 foo가 태스크 큐에 푸시된다.
4-2 [자바스크립트 엔진] bar 함수가 호출되어 실행 컨텍스트가 생성되고 콜 스택에 푸시되어 현재 실행 컨텍스트가 된다. 이 때 브라우저가 타이머를 설정한 후 만료됐다면 foo 함수는 아직 태스크 큐에서 대기중이다.
이처럼 자바스크립트 엔진과 브라우저는 협력하여 비동기 함수를 실행한다.