그렇기 때문에 코드를 병렬로 처리할 수가 없습니다.
이를 보완하기 위해 자바스크립트 런타임인 브라우저에서 이벤트루프가 도입되었습니다.
자바스크립트의 setTimeout
같은 비동기 함수는 Web API
스레드에서 별도로 처리됩니다.
이벤트 루프는 콜스택을 감시하다가 콜스택이 비워지면 Task Queue
에 있는 콜백 함수를 콜스택에 Push
하는 것으로 알려져 있습니다.
그렇다면 이벤트 루프 또한 별도의 스레드가 존재하는걸까요?
그런데 어떻게 싱글 스레드에서 2가지 일(코드 실행 + 콜스택 비었는지 감지)을 한번에 할 수 있을까요?
사실 한번에 하는 것처럼 보이지만 그렇지 않습니다.
이벤트 루프가 콜스택을 감시한다는 것 부터가 잘못된 말입니다.
흔히 '감시한다'는 표현은 브라우저의 이벤트와 같습니다.
클릭, 스크롤 등의 입력 이벤트들은 브라우저의 별도의 스레드에서 이벤트를 감지하여 콜백함수를 Task Queue
에 넣는 방식으로 구현되어있습니다. (브라우저의 입력 이벤트 동작 원리는 해당 링크를 참조해주세요 )
하지만 이벤트 루프는 콜스택(V8)과 같은 메인스레드에서 동작하기 때문에 따로 이벤트를 등록하여 감시할 수 없습니다.
즉, 콜스택을 주시한다, 감시한다 라는 표현은 사실 옳지 않습니다.
그럼 이벤트 루프는 어떻게 구현되어 있을까요?
void MessagePumpDefault::Run(Delegate* delegate) {
AutoReset<bool> auto_reset_keep_running(&keep_running_, true);
for (;;) {
#if defined(OS_APPLE)
mac::ScopedNSAutoreleasePool autorelease_pool;
#endif
Delegate::NextWorkInfo next_work_info = delegate->DoWork();
bool has_more_immediate_work = next_work_info.is_immediate();
if (!keep_running_)
break;
if (has_more_immediate_work)
continue;
has_more_immediate_work = delegate->DoIdleWork();
if (!keep_running_)
break;
if (has_more_immediate_work)
continue;
if (next_work_info.delayed_run_time.is_max()) {
event_.Wait();
} else {
event_.TimedWait(next_work_info.remaining_delay());
}
// Since event_ is auto-reset, we don't need to do anything special here
// other than service each delegate method.
}
}
Chromium
의 이벤트루프 코드 중 일부입니다. (이벤트 루프 구현은 브라우저마다 다르고 매우 복잡합니다.)
keep_running
이라는 플래그 변수를 통해 이벤트 루프의 반복문을 break
하는 것을 볼 수 있습니다.
이걸로 유추할 수 있는 사실은 이벤트 루프는 무한으로 돌아가지 않는다는 겁니다.
이처럼 이벤트 루프는 무한으로 돌아가면서 콜스택이 비어있는지 감시하는 것이 아닌, 콜스택이 비워질때 실행되며, 특정 조건에 의해 종료됩니다.
이벤트 루프는 V8
엔진에 포함되어 있지 않습니다. 그렇기 때문에 ECMAScript
명세에도 존재하지 않습니다.
V8
과 이벤트 루프는 모두 Blink
엔진 안에 있습니다. Blink
의 하나의 메인스레드에서 콜스택과 이벤트 루프가 관리됩니다.
그렇기 때문에 콜스택이 전부 비워져야만 이벤트 루프에서 콜백함수를 콜스택에 push
하도록 설계된 겁니다.
결론 => 이벤트 루프는 별도의 스레드가 아닌 메인스레드에서 특정시점마다 작동하는 Loop입니다.
이처럼 이벤트 루프는 무한으로 돌아가면서 감시하는게 아니라니.. 충격이네요..
어찌 보면 당연한 얘긴데 깊게 생각하지 못했던 부분이었던 것 같습니다. 짚어주셔서 감사합니다.
Blink 엔진이라는 좋은 키워드를 얻었으니 한 번 더 공부해봐야겠네요.
항상 좋은 글 감사합니다.