동기 처리와 비동기 처리
함수가 호출되면 함수 코드가 평가되고 함수 실행 컨텍스트가 생성된다. 이 떄 생성된 함수 실행 컨텍스트는 콜 스택에 푸시되고 함수가 실행된다. 실행이 끝나면 함수 실행 컨텍스트가 콜 스택에서 팝되어 제거되고, 다음 함수가 있으면 다음 함수 실행 컨텍스트가 푸시되어 똑같은 과정을 반복하게 된다.
자바스크립트 엔진은 하나의 콜 스택(실행 컨텍스트 스택)을 가진다. 때문에 자바스크립트로 어떤 태스크를 수행할 때 앞 순서의 태스크의 실행 컨텍스트가 콜 스택에서 팝되어야만 다음 순서의 태스크를 수행할 수 있다. 한번에 하나의 일 밖에 할 수 없다는 의미이다.
한 번에 하나의 태스크만 처리할 수 있는 것을 **싱글 스레드(single thread)**라고 하는데, 이 특징으로 인해 처리되는데 시간이 걸리는 태스크를 실행할 떄 뒷에 있는 태스크가 실행되지 못하는 블로킹(blocking) 현상이 발생한다.
이처럼 앞에 있는 태스크가 종료될 때까지 다음 번 태스크가 대기하는 방식을 **동기(synchronous)**라고 한다.
동기 처리 방식은 태스크의 실행 순서가 보장된다는 장점이 있지만, 앞 태스크가 종료될 때까지 다음 태스크가 블로킹된다는 단점이 있다.
동기와는 다르게 현재 실행중인 태스크가 종료되었는지와는 상관없이 다음 태스크를 실행하는 방식을 **비동기(asynchronous)**라고 한다. 비동기는 동기와는 반대로 실행중인 태스크가 종료되기 전에 다음 태스크가 실행되어 블로킹(non blocking)이 발생하지 않는다는 장점이 있지만 태스크의 실행순서가 보장되지 않는다는 단점이 있다.
이벤트 루프와 태스크 큐
자바스크립트의 특징 중의 하나는 싱글 스레드로 동작한다는 것이다. 하지만 브라우저에서의 동작을 보면 태스크들이 동시에 실행되는 것처럼 보인다. 이는 브라우저가 자바스크립트의 싱글 스레드를 보완해주고 있기 때문이다.
자바스크립트 엔진은 크게 힙과 콜 스택으로 나뉜다. 힙에는 콜 스택에서 참조할 실제 객체들이 저장되고, 콜 스택에는 함수 실행 컨텍스트가 쌓인다.
브라우저에는 태스크 큐와 이벤트 루프가 있다. 태스크 큐에는 비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관된다. 이벤트 루프는 현재 콜 스택에 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기중인 함수들이 있는지를 계속 확인한다. 그러다 콜 스택이 비어있고, 태스크 큐에 대기중인 함수가 있으면 대기중인 함수를 순차적으로 콜 스택으로 이동시킨다. 콜 스택으로 이동한 함수는 콜 스택에 의해 실행된다.
비동기 동작 함수가 브라우저 측에 넘어가서 실행되는 동안 자바스크립트 엔진은 콜 스택에 다음 태스크를 쌓고 순차적으로 처리한다. 때문에 브라우저의 동작을 보았을 때 태스크들이 동시에 실행되는 것으로 보이는 것이다.
다시 말해, 자바스크립트는 싱글 스레드이지만, 멀티스레드인 브라우저에서 동작하기 때문에 멀티스레드처럼 동작할 수 있는 것이다.
- 책 모던 자바스크립트 딥 다이브