어쨌든 이벤트 루프는 무엇입니까?

Paul Kang·2022년 9월 3일
0

Javascript

목록 보기
1/1
post-thumbnail

자바스크립트 "Event Loop"에 대해 정리하고자 합니다.

Javascript, What are you?

대답은? " 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나 뭐 그런것들을 가지고 있어요...

(이런 단어들에 집착할 필욘 없을 것 같습니다)

이 글을 통해 자바스크립트에서 콜백이 왜 중요한지 이해하고, 런타임 환경에 대해 다시 한번 생각하는 기회가 되었으면 합니다.

자바스크립트 런타임 (ex. v8)

크롬의 v8 같은 실제 자바스크립트 런타임을 들여다 보겠습니다.

  • 자바스크립트는 싱글 스레드 프로그래밍 언어입니다. (싱글 스레드 런타임을 가지고 있다는 말)
  • 이것은 결국 한번에 하나의 싱글 call stack만을 가지고 있다는 말입니다.
  • 싱글 스레드 = 하나의 프로그램은 동시에 하나의 코드만 실행할 수 있다는 것!

Call Stack 그림으로 이해하기

콜스택

  • 무엇인가를 리턴할 때마다 스택 맨 위에 있는 값을 꺼내게 됩니다. (stack.pop())

function foo() {
  return foo();
}

foo();

maximum-call-stack

  • 이 에러는 개발을 하시다가 한번쯤은 만나 보셨을텐데요.
  • 이제야 조금 명확한 이유를 알 것 같습니다.
  • 계속되는 foo 함수의 호출로 call stack이 꽉 차버려서 크롬 v8 엔진은 "이 녀석들을 중지 시킬게요 버그를 고쳐주세요!" 라고 말하고 있습니다.

blocking (What happens when things are slow?)

  • 느린 동작이 스택에 남아있는 것을 보통 블로킹이라고 말하게 됩니다.
  • 브라우저는 실제로 ajax요청을 동기적으로 실행시키지 않습니다.
  • 브라우저에서 ajax요청을 동기적으로 강제시킨다면 브라우저는 모든 리퀘스트가 완료될 때까지 멈출겁니다. (It's stucked)
  • 멈춰있는 동안 콜스택에 쌓여있던 코드들이 후에 실행되겠죠?
  • 유려한 UI를 만드려고 한다면, 콜스택을 멈추게 해서는 안됩니다.

해결방법은? 비동기 콜백!

  • 브라우저 혹은 노드에는 블로킹 함수가 거의 없습니다. 대부분 비동기로 만들어졌습니다.
  • 어떤 코드를 실행하면 결국 콜백을 받고 이걸 나중에 실행한다는 말입니다.

console.log('Hi');

setTimeout(function() {
  	console.log('There');
}, 5000);

console.log('!!!');
Hi
!!!
There
  • 이 순서로 출력합니다.
  • 콜 스택에선 console.log('Hi'); 가 먼저 쌓이고 동기적으로 실행됩니다.
  • 그다음엔 setTimeout인데 갑자기 어디론가 사라져 버리고 console.log('!!!'); 가 쌓이고 실행됩니다.
  • 그리고 5초 뒤에 마법처럼 there 가 스택에 나타납니다.

여기에서 이벤트 루프와 동시성이 역할을 하게됩니다!!

동시성 & 이벤트루프 (Concurrency & Event Loop)

한번에 하나씩. 꼭 그렇지는 않다는 것만 빼면.

  • 자바스크립트 런타임은 한번에 하나만 할 수 있습니다.
  • 하지만 브라우저에서의 Web API는 자바스크립트에서 호출할 수 있는 스레드를 효과적으로 지원합니다. 여기에 동시성이 들어오는 것입니다.

아까 사라져버린 setTimeout 콜 스택 상황을 좀더 디깅해봅시다.

  • setTimeout은 브라우저에서 제공하는 Web API입니다. v8 소스코드엔 존재하지 않죠.

webapis

  • 브라우저가 타이머를 실행시키고 카운트 다운을 시작합니다. 이건 setTimeout 자체는 호출 완료되었고 스택에서 함수를 지울 수 있는 상황입니다.

  • 콜 스택에서 setTimeout 호출문은 사라지고 5초가 흐릅니다.

  • webAPI는 갑자기 콜스택에 끼여 들 순 없습니다. (이제 테스크큐 또는 콜백큐가 활약할 차례입니다.)

  • 모든 web API는 작동이 완료되면 콜백(cb)을 테스크 큐에 밀어넣습니다.

task-queue

  • 그리고 드디어 이벤트루프가 할 일이 생겼습니다.

이벤트 루프의 역할은 콜 스택과 테스크 큐를 주시하는 것입니다.

  • 스택이 비어있으면, 큐의 첫번째 콜백을 스택에 쌓아 효과적으로 실행할 수 있게 해줍니다.

여기까지만으로도 여러분들은 자바스크립트 비동기 함수가 어떻게 작동하는지 알게 되었습니다.

실제 브라우저 repaint 또는 렌더링 상황에서의 비동기 함수가 어떤 영향을 미치는지

  • 브라우저는 여러분이 자바스크립트로 하는 무언가로 인해 제약을 받습니다.

  • 브라우저는 기본적으로 화면을 매 16.6ms, 즉 1초에 60프레임을 repaint하는게 이상적입니다. 그게 제일 빠른거죠.

  • 스택에 코드가 있으면, 렌더링을 못합니다. 렌더도 하나의 콜백처럼 행동하니깐요. (스택이 비어질 때까지 기다려야 하는겁니다.)

  • 다른점이라면, 렌더는 여러분의 콜백에 비해 더 높은 우선순위를 갖습니다. 매 16.6ms마다 큐에 들어갑니다 (Render Queue)

  • 렌더가 막히면, 화면의 버튼을 클릭해서 반응을 보는게 불가능합니다.

  • 사람들이 event loop를 막지 말라고 할 때, 바로 이런 현상을 뜻하는 것입니다.
    - 스택에 필요없는 느린 코드를 쌓아서 브라우저가 할일을 못하게 만들지 마라. 유동적인 UI를 구현해라. (Ex. 스크롤 이벤트에서의 렌더링 최적화)

profile
뭐든 기록하면 자산!

0개의 댓글