카테고리 없음

[ JavaScript ] Event Loop

흰색남자 2023. 4. 22. 14:14

회사에서 자바스크립트를 사용해야하는데 이왕 하는 김에 더 깊게 이해하고자 이 글을 작성한다.
작동원리를 정확하게 파악하고 있어야 버그가 적게 나오고 단단한 코드를 작성할 수 있다.
단순 코더로 남지 않고 고오급 개발자가 되기 위해 공부를 계속한다.

 

목적

자바스크립트의 이벤트루프에 대해서 설명할 수 있다.

 

자바스크립트와 자바의 차이

자바는 멀티 스레드 언어이고 자바스크립트는 단일 스레드 언어이다. 그래서 자바스크립트는 자체적으로는 새로운 스레드를 생성할 수 없어 메인 스레드가 종료되지 않게 주의해야한다. 이름만 비슷할 뿐이지 전혀 다른 언어라 비교 대상이 되지 않는다.

또한 자바스크립트는 파이썬과 같은 인터프리터언어이다.

자바스크립트와 브라우저 환경 구조

 

자바스크립트의 동작 원리와 이벤트 루프

자바스크립트는 브라우저에서 동작한다. 자바스크립트가 내부적으로 동작하는 원리에는 호출 스택, 테스크 큐, 백그라운드 스레드, 메인 스레드를 이해하고 비동기, 동기, 콜백이라는 용어를 숙지하고 있어야 한다.

호출 스택과 힙

자바 JVM의 스택과 힙이랑 똑같다. // 다른 글에 너무 많이 적어 또 적지는 않는다.

테스크 큐 ( 매크로 테스크 큐 ) + WebAPI& 마이크로 테스크 큐 

자바스크립트는 비동기 처리가 많은 언어이다. 
이 비동기 처리에도 우선순위가 있기 때문에 알아 두는 것이 좋다.
리액트에서 많이 사용하는 Async & await, Promise는 동일한 비동기 우선순위를 갖지만, WebAPI를 이용하는 비동기인 setTimeout, setInterval은 한단계 낮은 우선순위를 갖기 때문에 잘 알고 사용하는 것이 좋다.
테스크 큐는 마이크로 테스크 큐에 있는 테스크들을 모두 실행하고 실행하게 된다.

예를 들면,

해설

더보기

해설.

 

async는 동시에 코드를 실행하게 되고, async 블럭안에 await가 붙어 있으면 해당 코드를 모두 실행하고 결과값을 리턴한 후 다음 코드가 실행되게 된다.

아래에서 각 큐에 대한 우선 순위를 설명했었는데, setTimeout을 0초로 두고 실행한다 해도 바로 실행되는 것은 안니기 때문에 다른 마이크로 서비스에 먼저 들어간 큐에 대한 테스크를 모두 실행하고 setTimeout(~~~,0); 코드가 실행되기 때문에 before가 마지막에 찍힌다.

 

async와 promise는 동작은 같은데 문법이 다르다. 

html

<div>
  <p id="paragraph">start</p>
</div>

1번.

const addValue = (value) => {
  let elem = document.getElementById("paragraph");
  elem.innerHTML = elem.innerHTML + ` > ${value}`;
};

const foo = async () => {
  addValue('foo');
};

const bar = () => {
  addValue('before bar');
  foo();
  addValue('after bar');
}

setTimeout(() => {
  addValue('before');
  bar();
  addValue('after');
}, 3000);

2번.

const addValue = (value) => {
  let elem = document.getElementById("paragraph");
  elem.innerHTML = elem.innerHTML + ` > ${value}`;
};

const foo = async () => {
  addValue('foo');
};

const bar = async () => {
  addValue('before bar');
  await foo();
  addValue('after bar');
}

setTimeout(async () => {
  setTimeout(() => addValue('before'), 0);
  await bar();
  addValue('after');
}, 3000);

3번

const addValue = (value) => {
  let elem = document.getElementById("paragraph");
  elem.innerHTML = elem.innerHTML + ` > ${value}`;
};

const foo = async () => {
  addValue('foo');
};

const bar = async () => {
  addValue('before bar');
  await foo();
  addValue('after bar');
}

setTimeout(async () => {
  addValue('before');
  await bar();
  addValue('after');
}, 3000);

위와 같은 예제가 있다.

async, 테스크 큐, 마이크로 테스크 큐에 대한 이해가 있으면 위의 문제를 풀 수 있다.

아래의 그림을 이해하고 풀어보는 것이 좋을 것 같다.