자바스크립트 그 기묘함에 대하여...

Outclass·2022년 9월 19일
0

최근 회사에서 브라우저의 렌더링이 블로킹되는 것과 관련된 이슈를 개선하기 위해 자바스크립트의 동작원리, 이벤트 루프 등에 대해 좀 더 공부하게 되었다.

공부를 하며 하게된 생각중 하나는, (내 뇌피셜이지만) 아무래도 자바스크립트라는 것이 급하게 만들어진 언어이며 이후에 계속해서 추가/업데이트가 일어나다보니 아주 복잡한 원리의 괴물(?)이 된 것이 아닌가 하는 생각이었다.

이벤트 루프의 동작 테스트

아래 코드는 자바스크립트의 동작을 검증하기 위해 간단한 함수를 짜본 것이다.

function startFunc () {
  console.log("-----call stack start-----")
  for(let i = 1 ; i <= 10 ; i++){
      innerFunc1(i)
  }
  console.log("-----promise start-----")
}

function innerFunc1 (number) {
  innerFunc2(number)
  Promise.resolve().then(() => {
    console.log(`${number} promise`)
  })
  console.log(`${number} console`)
}

function innerFunc2(number) {
  console.log(`${number} inner console`)
  setTimeout(() => {
    console.log(`${number} inner timeout`)
  }, 0)
  Promise.resolve().then(() => {
    console.log(`${number} inner promise`)
  })
}

setTimeout(() => {
  console.log("-----timeout start-----")
}, 0)

startFunc()

만약 자바스크립트가 순서대로 코드를 읽고 실행한다면, 마땅히 setTimeout안의 함수가 Promise앞에 위치해야 함에도 불구하고, 모든 Promise가 실행된 후 setTimeout이 실행되는 것을 볼 수 있다.

실험실
https://replit.com/@outclassstudio/nodejs-test#index.js

도대체 왜이러는 걸까

자바스크립트는 일단 싱글 스레드로 동작한다. 많이 알려진 것처럼 싱글스레드 논 블로킹 I/O 머시기... 그런데 싱글스레드임에도 비동기 작업이 가능한 것은 이벤트 루프가 있기 때문이다. -라고 이전까지 그냥 어렴풋이 느낌적으로 알고 있었다.

그런데 이벤트 루프의 동작을 더 들여다보면, 골때리는 구성이 보인다. 태스크 큐라고 하는 것에 이벤트 콜백이 등록되었다가 콜스택이 비면 그때 이벤트루프가 돌면서 콜백이 실행되는 모형을 많이 봤을텐데, 여기서 태스크 큐의 종류가 한가지가 아니라는 거다.

태스크큐는 크게 마이크로태스트 큐와 (매크로) 태스트 큐로 나뉘며, 거기에 애니메이션 프레임스 라는 녀석도 있다...

우리가 흔히 알고 있는 태스크 큐는 webapi에 포함된 setTimeout과 같은 친구들이 들어가는 곳이며, 마이크로 태스크 큐는 Promise를 처리한다.

재미있는 점은, 마이크로태스크큐가 태스크큐 대비 우선순위를 갖는다는 점이다. 그리고 프로미스 체이닝을 처리하기 위해, 프로미스가 실행되는 중간에 마이크로태스크큐에 새로운 프로미스가 추가되는 경우가 발생하므로 마이크로태스크큐가 완전히 비워져야 다음 실행으로 넘어간다는 것.

태스크 큐의 우선순위 : Microtask Queue > Animation Frames > (Macro) Task Queue

따라서 대략의 콜스택이 처리되는 흐름은
콜스택에 쌓인 스택 → 마이크로태스크큐 비움 → 태스크큐 이런식이 된다.

따라서 콜스택이나 마이크로태스크큐에 뭐가 잔뜩 쌓여있으면, 결과적으로 렌더링이 블로킹 될 수 있다는 얘기이기도 하다.

기묘함

그런데 마이크로태스크 큐는 ECMAScript의 스펙이 아니다.
HTML 스펙에 기술되어 있다...
따라서 브라우저마다 그 작동 방식이 상이한 경우가 존재한다는.. 괴담....
공포스럽다.

결론

아무튼... 최적화 이슈나, 브라우저와 관련한 깊숙한 이슈들을 접하면 결국 자바스크립트의 동작과 간련한 핵심 문제들을 다룰 수 밖에 없다는 것을 다시금 느끼게 된다. 아직 완벽하게 그 동작원리가 이해되는 것은 아니지만 이런 문제를 해결해나가면서 차근차근 원리에 접근하고 관련한 해결책을 정리해나가다보면 지금보다는 이러한 문제들이 덜 어렵게 다가오지 않을까 한다.

공부한 내용들

첫번째 링크가 굉장히 큰 도움이 되었다.

https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
https://meetup.toast.com/posts/89
https://velog.io/@titu/JavaScript-Task-Queue%EB%A7%90%EA%B3%A0-%EB%8B%A4%EB%A5%B8-%ED%81%90%EA%B0%80-%EB%8D%94-%EC%9E%88%EB%8B%A4%EA%B3%A0-MicroTask-Queue-Animation-Frames-Render-Queue
https://www.jsv9000.app/
https://sculove.github.io/post/javascriptflow/

profile
When you stop having big dreams that’s when you’ve died, despite not being buried yet.

0개의 댓글