[동기, 비동기 2] 비동기 처리를 위한 자바스크립트 엔진

김헤일리·2022년 12월 10일
1

Runtime이란 프로그래밍 언어가 구동되는 실행 환경을 의미한다.

  • 자바스크립트 런타임의 종류 중 하나가 바로 웹 브라우저인데, 웹 브라우저 내부에서 자바스크립트가 구동되기 때문에 브라우저가 JS Runtime이 되는 것이다.
  • 브라우저에는 자바스크립트 개발자가 사용하는 거의 모든 API가 있다. (예: setTimeout ).
  • 이런 API 들은 브라우저 엔진에서 제공해준 API가 아니다.
  • DOM, AJAX, setTimeout 등의 브라우저에서 제공하는 Web API라고 하는 것들이 있고, 이런 Web API의 호출을 통제하기 위한 Event Queue와 Event Loop도 존재한다.

그리고 자바스크립트가 데이터를 어떻게 비동기 처리하는지 이해하려면 이런 외부 환경(Runtime)과 내부 환경(Engine)을 이해해야 한다.


1. 자바스크립트 엔진

  • 자바스크립트의 엔진은 크게 두 가지로 구성되어 있는데, 바로 "콜 스택 (Call Stack)" "메모리 힙 (Memory Heap)" 이다.

  • 그리고 자바스크립트 엔진을 그림으로 표현하면 이런 느낌이다.

❗️ 콜 스택 (Call Stack)

  • JS에선 코드가 실행될 때 콜 스택에 하나씩 콜(호출)이 쌓인다.

  • 자바스크립트는 싱글 스레드 프로그래밍 언어이기 때문에 한번에 한가지의 코드만 실행할 수 있다.

    • 자바스크립트는 기본적으로 코드를 동기식으로 처리한다.
  • 콜 스택이란 프로그램에서 우리가 어디에 있는 기록하는 데이터 구조이고, 함수가 실행될 때 해당 함수의 기록이 스택에 하나씩 쌓이는 가상의 공간을 의미한다.

    • 하나씩 순차적으로 쌓이기 때문에 Last In, First Out 의 구조를 갖고 있다.
    • 즉 가장 나중에 push된 실행 컨텍스트부터 종료되면 콜스택에서 제거된다.
    • 모든 실행 컨텍스트가 push/pop 거치며 스택이 비어있으면 모든 실행이 끝난 것이다.

❗️ 메모리 힙 (Memory Heap)

  • 객체가 선언될 때, 객체에 대한 값이 저장되고 특정 "주소"로부터 참조해서 사용한다.

    • 이때 주소 자체는 콜 스택에 저장되고, 참조되어 오는 값이 다른 곳에 저장된다.
    • 이때 이 객체의 값들의 저장되는 공간은 구조화되지 않은 특정 메모리 영역이고, 이 메모리 영역이 바로 메모리 힙이다.
  • 값이 정해진 원시값(int, char, boolean...) 등과는 달리 객체는 크기를 정할 수 없다.

    • 할당 크기가 런타임 시 결정되고, 결정될 때 힙에 저장하고 참조하는 방식으로 사용된다.
      • 원시 값의 경우, 주소와 값이 전부 콜 스택에 저장되고, 배열, 객체, 함수 같은 자료들은 값은 따로 저장되고 그 값을 지닌 주소만 콜 스택에 저장된다.
      • 그래서 배열, 객체, 함수를 참조형 데이터라고 하는 것!


2. 자바스크립트 브라우저 환경

  • 자바스크립트 런타임에서 제공하는 비동기 콜백을 만드는 것은 이벤트 루프이다.
  • 앞에서 웹 브라우저에 Web APIs 에는 setTimeout, DOM, AJAX(HTTP 요청)이 있다고 했다.
  • 자바스크립트 자체는 비동기적으로 요청을 처리할 수 없고, 런타임 안에 지원하는 API로 비동기로 요청을 처리할 수 있게 하는 것이다.
    • 그리고 이 API에 "이벤트 루프 (Event Loop)" "태스크 큐 (Task Queue)"가 있다.

❗️ 이벤트 루프 (Event Loop)

  • 이벤트 루프의 역할은 Call Stack과 Task Queue를 주시하는 것이다.

  • Call Stack이 비워지면 Task Queue에 쌓여있던 Task를 새로 콜 스택에 쌓는다.

    • Web API에서 함수가 완료되면, 이 함수가 Task Queue에 쌓이는 것.
  • 이 과정이 바로 비동기 함수가 호출되는 방식이고, 싱글 스레드인 자바스크립트가 비동기적으로 데이터를 처리할 수 있는 이유다.


❗️ 태스크 큐 (Task Queue)

  • 태스크 큐는 콜백 함수들이 대기하는 Queue ( First In, First Out ) 형태의 배열이다.

    • setTimeout() 이나 setInterval() 같은 비동기 함수의 콜백 함수, 이벤트 핸들러가 일시적으로 보관되는 영역인 것이다.
  • 모든 비동기 API들 (Web API 같은)은 작업이 완료되면 콜백 함수를 태스크 큐에 추가한다.

  • 이벤트 루프는 '현재 실행중인 태스크가 없을 때' ( 주로 호출 스택이 비워졌을 때 ) 태스크 큐의 첫 번째 태스크를 꺼내와 실행한다.


마크로태스크 큐 (Macrotask Queue) & 마이크로태스크 큐 (Microtask Queue)

  • 마이크로 태스크들은 실행하면서 새로운 마이크로 태스크를 큐에 추가할 수도 있다.

    • 새롭게 추가된 마이크로 태스크도 큐가 빌 때까지 계속해서 실행된다.
  • 반대로, 이벤트 루프는 매크로 태스크 큐에 있는 것을 실행시키기 시작할 때 있는 매크로 태스크만 실행시킨다.

    • 매크로 태스크가 추가한 매크로 태스크는 다음 이벤트 루프가 실행될 때까지 실행되지 않는다.


3. 결론: 자바스크립트의 비동기 데이터 처리 방식

  • 결론적으로 자바스크립트가 비동기 함수를 호출할 수 있는 것은 런타임 환경으로 인한 것이다.

  • 이벤트 루프는:

    1. 매크로 태스크 큐에서 가장 오래된 태스크 를 꺼내서 실행시킨다.
    2. 마이크로 태스크 큐에 있는 모든 태스크를 실행시킨다.
    3. 렌더링 작업을 실행한다.
    4. 매크로 태스크 큐에 새로운 매크로 태스크가 나타날 때까지 대기한다.
    5. 1번으로 돌아간다.



아직 전부 정리하진 못 했지만... ☠️
적어도 자바스크립트에서 비동기 처리를 하기 위해 어떠한 과정이 일어나는지 조금 알 것 같았다.

앞으로 공부를 하면서 더 알게되면 업데이트 해야겠다.

출처:

profile
공부하느라 녹는 중... 밖에 안 나가서 버섯 피는 중... 🍄

0개의 댓글