자바스크립트 "Event Loop"에 대해 정리하고자 합니다.
대답은? " a single-threaded non-blocking asynchronous concurrent language..."
저는 싱글 스레드 논-블록킹 비동기 동적 언어입니다...😅
" I have a call stack, an event loop, a callback queue, some other apis and stuff... "
저는 콜스택과 이벤트 루프, 콜백 큐 그리고 다른 API나 뭐 그런것들을 가지고 있어요...
(이런 단어들에 집착할 필욘 없을 것 같습니다)
이 글을 통해 자바스크립트에서 콜백이 왜 중요한지 이해하고, 런타임 환경에 대해 다시 한번 생각하는 기회가 되었으면 합니다.
크롬의 v8 같은 실제 자바스크립트 런타임을 들여다 보겠습니다.
싱글 call stack
만을 가지고 있다는 말입니다.stack.pop()
)
function foo() {
return foo();
}
foo();
블로킹
이라고 말하게 됩니다.ajax
요청을 동기적으로 실행시키지 않습니다.ajax
요청을 동기적으로 강제시킨다면 브라우저는 모든 리퀘스트가 완료될 때까지 멈출겁니다. (It's stucked)
console.log('Hi');
setTimeout(function() {
console.log('There');
}, 5000);
console.log('!!!');
Hi
!!!
There
여기에서 이벤트 루프와 동시성이 역할을 하게됩니다!!
한번에 하나씩. 꼭 그렇지는 않다는 것만 빼면.
Web API
는 자바스크립트에서 호출할 수 있는 스레드를 효과적으로 지원합니다. 여기에 동시성
이 들어오는 것입니다.아까 사라져버린 setTimeout 콜 스택 상황을 좀더 디깅해봅시다.
setTimeout
은 브라우저에서 제공하는 Web API입니다. v8 소스코드엔 존재하지 않죠.브라우저가 타이머를 실행시키고 카운트 다운을 시작합니다. 이건 setTimeout
자체는 호출 완료되었고 스택에서 함수를 지울 수 있는 상황입니다.
콜 스택에서 setTimeout 호출문은 사라지고 5초가 흐릅니다.
webAPI는 갑자기 콜스택에 끼여 들 순 없습니다. (이제 테스크큐 또는 콜백큐가 활약할 차례입니다.)
모든 web API는 작동이 완료되면 콜백(cb)을 테스크 큐에 밀어넣습니다.
여기까지만으로도 여러분들은 자바스크립트 비동기 함수가 어떻게 작동하는지 알게 되었습니다.
브라우저는 여러분이 자바스크립트로 하는 무언가로 인해 제약을 받습니다.
브라우저는 기본적으로 화면을 매 16.6ms, 즉 1초에 60프레임을 repaint
하는게 이상적입니다. 그게 제일 빠른거죠.
스택에 코드가 있으면, 렌더링을 못합니다. 렌더도 하나의 콜백처럼 행동하니깐요. (스택이 비어질 때까지 기다려야 하는겁니다.)
다른점이라면, 렌더는 여러분의 콜백에 비해 더 높은 우선순위를 갖습니다. 매 16.6ms마다 큐에 들어갑니다 (Render Queue)
렌더가 막히면, 화면의 버튼을 클릭해서 반응을 보는게 불가능합니다.
사람들이 event loop
를 막지 말라고 할 때, 바로 이런 현상을 뜻하는 것입니다.
- 스택에 필요없는 느린 코드를 쌓아서 브라우저가 할일을 못하게 만들지 마라. 유동적인 UI를 구현해라. (Ex. 스크롤 이벤트에서의 렌더링 최적화)