동기와 비동기 #3 EventLoop / Web API

최정환·2022년 3월 11일
0

동기와 비동기

목록 보기
3/3
post-thumbnail

JS engine

JS code를 읽고 해석해서 실행을 담당하는 일종의 인터프리터.
가장 큰 특징은 단일 쓰레드로 동작하기에 스택 영역도 하나만 사용한다.

주요 구성요소

Memory Heap : 변수와 객체의 메모리 할당 담당
Call Stack : 함수를 호출하면 이곳에 쌓이고 Stack(LIFO)으로 반환한다.


Web API

  1. web API란
    웹 서버 혹은 브라우저를 위한 API이다.
    Ajax, setTimeout, 이벤트 핸들러 등 브라우저에서 제공하는 기능들이다.

    이런 요청들의 처리는 JS엔진의 쓰레드와 다른 쓰레드에서 이뤄진다.

Call Stack

프로그램에서 우리가 어디에 있는지를 기록하는 자료 구조
자료구조 Stack(LIFO)을 따른다.

  1. 함수를 실행
  2. 해당 함수의 기록 맨 위에 push
  3. 함수가 결과 값 return시 함수 pop
const plus = (x,y) => x + y;

const log = (x) => {
	let re = plus(x,x);
  	console.log(re);
}

log(3);

JS는 동기적이며 단일 쓰레드이기 때문에 결과를 기다리는 함수나 함수의 양이 엄청 많다면 stack이 초과될 경우가 있다.
이럴때 비동기 콜백을 사용한다.
이 비동기 콜백은 또 콜백/태스크 큐라는 새로운 개념을 가져온다.


Task queue / Event Loop

Task Queue

비동기로 실행된 콜백 함수가 보관되는 영역
Queue의 자료 구조를 따라 FIFO으로 동작한다.

Event Loop

자바스크립트의 단일 스레드 환경에 맞춰서 비동기 처리와 이벤트 핸들링을 수행하는데 사용되는 제어방식

call stack과 task queue의 상태를 체크하며
call stack이 비면 task queue의 첫번째 콜백을 call stack으로 밀어준다.

이런 반복적인 행동을 tick이라고 한다.

이벤트 루프가 큐에서 함수를 콜스택으로 밀어줄때 우선순위가 구현된다.

  1. 마이크로 테스크 큐
  • Promise callback
  1. 애니메이션 콜백 큐
  • requestAnimationFrame
  1. 매크로 테스크 큐
  • event handler, setTimeout 등 webAPI를 통해 넘겨진 콜백이 담긴 큐

위의 순서대로 조회를 하면서 순위에 존재하는 큐 내용물이 지워지기 전까지 다음 순위의 큐를 처리하지 않는다.

Example Code

내가 제일 헷갈렸던 callback인 addEventListener을 이용해 예제를 짜보겠다.

const el = document.querySelector(".el")

const sayHi = () => {
	console.log("hi")
}

console.log("call stack")

// 여기에서 콜백의 위치인 두번째 인자는 항상 왜 객체 형태나 익명함수로 묶어 줘야했는지 궁금했다.
el.addEventListener("click", sayHi)

순서

  1. el이라는 상수에 document.method의 결과값을 선언시켜준다.
    → 메모리 힙

  2. sayHi라는 함수를 선언한다.
    → 메모리 힙

  3. el이라는 상수의 값에 method를 연결시켜준다.
    → 콜 스택에 존재 후

  4. console.log("call stack")
    → 콜 스택

  5. el이라는 상수의 값에 method를 연결시켜준다.
    → 콜 스택에 존재 후 → web api에 콜백을 전달한 후 out

  1. el에 붙은 method의 callback
    → callback의 조건에 맞는 이벤트 발생시 → Task Queue로 이동 후 콜스택으로 쌓인 후 함수를 실행한다. → 누를 때마다 web api에 콜백을 전달 한 후 전과 같은 동작이 반복된다.



그래서 콜백에서 왜 함수를 바로 실행시키면 안될까

동작원리를 정리하면서 이제야 이게 당연하다는 생각인걸 알게되었다.
코드 한줄 한줄이 바로 콜 스택이나 메모리 힙으로 들어가기 때문에 이벤트를 연결시키는 순간부터 바로 method가 콜 스택에 올라가게 되기때문에 이벤트가 발생하는 순간이 아니라 이벤트를 연결시키는 순간에 콜백에 들어간 함수를 읽게될것이다.

따라서 만약 콜백의 위치에서 함수를 바로 실행시키도록 작성한다면 콜백은 taskqueue에 쌓이지 않고 바로 콜 스택으로 올라가기 때문에 함수를 바로 실행시키도록 하는게 아니라 콜백 함수라는 이름에 맞도록 함수가 함수를 실행할 수 있게 or 이벤트가 발생한다면 실행 가능하도록 작성해야한다.















참고:

https://resilient-923.tistory.com/308
https://codingmoondoll.tistory.com/entry/이벤트-루프

0개의 댓글