[기술면접] JavaScript 런타임 작동방식, 비동기와 이벤트 루프

윤후·2022년 6월 21일
13

기술면접

목록 보기
7/28

JacaScript 엔진과 런타임


JavaScript와 웹 브라우저

크롬 웹 브라우저는 V8엔진이 탑제된 자바스크립트 런타임이다.

JavaScript 런타임이란?

  • 런타임이란, 프로그래밍 언어가 구동되는 환경을 말한다.
  • JavaScript 런타임이란 JavaScript가 구동되는 환경을 말한다.
  • 이러한 JavaScript 런타임의 종류로는 웹 브라우저(크롬, 파이어폭스 등)프로그램과 NodeJS라는 프로그램이 있다.
  • 이러한 프로그램들에서 JavaScript가 구동되기 때문에 JavaScript 런타임이라고 한다.

V8엔진이란?

  • V8은 오픈 소스 JavaScript엔진중 하나이다.
  • JavaScript와 *웹어셈블리(WebAssenbly) 엔진이다.
  • 크롬 웹 브라우저와 NodeJs에서 사용되고 있다.
  • V8은 JavaScript를 바이트코드로 컴파일하고 실행하는 방식을 사용한다.

*웹어셈블리란?

  • C나 C++와 같은 프로그래밍 언어를 컴파일해서 어느 브라우저에서나 빠르게 실행되는 형식으로 바꿔주는 기술을 뜻한다.
  • 보통 웹 애플리케이션 개발시에는 JavaScript 프로그래밍 언어를 사용해 동적인 부분을 개발하는데 C나 C++언어들에 비해서는 느리다.
  • 게임이나 동영상 편집 등과 같은 고성능 웹 애플리케이션을 개발할 때 브라우저의 동작을 빠르게 하기위해서 C나 C++과 같은 언어로 개발할 수 있게 하는 것이다.
  • 고성능 웹 애플리케이션 개발 시 JavaScript와 같이 사용되고 JavaScript를 대체하는 것이 아닌 보완하는 기술인 것이다.

V8 엔진의 구성

  • JavaScript V8엔진 소스안에는 하나의 힙과 하나의 콜 스택만이 있다.
  • setTimeout, DOM, AJAX 등과 같은 비동기 메소드가 없다.

JavaScript 런타임 웹 브라우저의 Web APIs

  • setTimeout, DOM, AJAX 등과 같은 비동기 메소드가 있다.
  • 이벤트 루프와 콜백 큐를 가지고 있다.

JavaScript와 비동기

JavaScript와 싱글 스레드

JavaScript는 싱글 스레드 프로그래밍 언어이다.

싱글 스레드와 멀티 스레드

  • JavaScript는 전통적인 단일 스레드이다.
  • 코어가 여러개 있어도 메인 스레드라고 하는 단일 스레드에서만 작업을 수행할 수 있다.
  • 이러한 싱글 스레드는 하나의 힙 영역과 하나의 콜 스택을 가진다.
    하나의 콜 스택을 가진다는 의미는 한 번에 한 가지 일 밖에 못한다는 의미이다.
  • 아래의 예시처럼 싱글 스레드는 일을 동기적으로 처리한다.
function SignThreadTest() {
  console.log(1);
  for( let i=0; i<10000; i++ ) {
    console.log('자바스크립트는 싱글 스레드 프로그래밍 언어이다.');
  }
  console.log(2);
}
// '자바스크립트는 싱글 스레드 프로그래밍 언어이다.'가 10,000번 실행이 완료 될 때까지
// 콘솔 창에 '3' 이 찍히는 것을 기다려야한다.
SignThreadTest();

힙과 콜 스택

  • JavaScript V8엔진에는 두 가지 주요 구성 요소가 있다.
  • 힙은 변수와 객체의 메모리할당에 사용되는 비정형 메모리이다.
  • 콜 스택은 코드를 읽고 함수가 실행된는 순서를 기억하고 있다.
  • 함수를 실행하려면 스택의 가장 위에 해당 함수를 넣게 되고 함수에서 리턴이 일어나면 스택의 가장 위쪽으로 함수를 꺼낸다.
  • V8 엔진에서 오류가 발생하면 스택 추적을 콘솔에 인쇄한다.
    콜 스택 / 메모리 힙 구조

JavaScript 동기와 블로킹

동기와 비동기

  • 동기와 방식은 서버에서 요청을 보냈을 때 응답이 돌아와야 다음 동작을 수행할 수 있다. 즉, A작업이 모두 진행 될 때까지 B작은 대기해야하는 것이다.
  • 비동기 방식은 반대로 요청을 보냈을 때 응답 상태와 상관없이 다음 동작을 수행할 수 있다. 즉, A작업을 시작하면서 동시에 B작업이 실행되는 것이다. A작업은 결과값이 나오는대로 출력되게 된다.

싱글 스레드는 블로킹을 만든다.

  • 싱글 스레드는 동기적으로 처리되기 때문에 블로킹을 만든다.
  • 동기적으로 AJAX 요청을 보내면 브라우저는 모든 응답이 완료될 때까지 멈춰있다.
  • 동기적으로 실행되는 네트워크 요청이 콜 스택을 블로킹하여 브라우저는 다른 일을 할 수 없다. 여기서 주의할 점은 "동기적으로 네트워크 요청을 보내면" 그렇다는 것이지 웹 브라우저가 제공하는 API가 동기적으로 요청을 보낸다는 것이 아니다.

💡 블로킹이란?

  • 느리게 동작되는 코드. 느린 동작이 스택에 남아있는 것을 블로킹이라고 한다.
  • 웹 브라우저에서 코드가 실행되는데 코드가 종료될 때까지 유저가 클릭을 해도 어떠한 반응을 하지 않는 상태가 된다.
  • Call Stack이 멈춘 상태, 이 상태를 블로킹 상태라고 한다.

JavaScript 비동기와 논 블로킹

동기적 처리의 문제점 때문에 브라우저는 AJAX 요청을 비동기적으로 실행한다.

웹 브라우저의 Web APIs는 비동기로 처리한다.

  • 앞에서 웹 브라우저네 Web APIs에는 setTimeout, DOM, AJAX 요청이 있고, 이벤트 루프와 콜백 큐를 가지고 있다고 했다.
  • JavaScript 자체는 비동기적으로 요청을 처리할 수 없다. JavaScript 런타임 안에 지원하는 API로 비동기 요청을 처리할 수 있게 하는 것이다.

비동기 콜백으로 싱글 스레드 프로그래밍 언어에서 블로킹을 해결할 수 있다.

  • 웹 브라우저와 NodeJs에는 동기로 처리하는 블로킹 메소드가 거의 없다.
  • 대부분 지원 메소드가 비동기 처리를 하게끔 만들어졋다.
  • 그렇다면 웹 브라우저와 NodeJs에서 요청을 비동기로 어떻게 처리할 수 있는 것일까?
  • 이는 어떤 코드를 실행하면 결국 콜백을 받고 이걸 나중에 실행한다는 말이다.
  • 자세하게 이야기하면 함수 호출 시 당장 실행하는 것이 아니라(동기→블로킹), 일단 어느 곳에 쌓아두고 동시에 요청을 처리하고(비동기→논 블로킹) 요청이 완료된 순서대로 처리(스택 이용)한다는 말이다.

JavaScript 런타임에서 비동기 처리 방법

비동기 콜백을 만드는 이벤트 루프

JavaScript 런타임에서 제공하는 비동기 콜백을 만드는것은 이벤트 루프이다.

비동기 콜백을 만드는 것은 이벤트 루프와 동시성이다.

  • JavaScript는 한번에 하나의 일만 할 수 있다.
  • JavaScript는 다른 코드를 실행시키는 동안 AJAX, setTimeout 요청을 실행할 수 없다.
  • 웹 브라우저는 단순 런타임 이상을 의미한다.
  • 웹 브라우저에서는 Web API를 제공한다.
  • 웹 브라우저의 Web API는 JavaScript에서 호출할 수 있는 스레드를 효과적으로 지원한다.
  • 여기서 동시성(비동기 처리)이 들어오는 것이다.

Web API

  • Web API는 JavaScript가 실행되는 런타임 환경에 존재하는 별도의 API이다.(V8 소스코드에는 존재하지 않는다.)
  • setTimeout의 인자로 콜백함수와 지연시간을 입력해서 호출한다.
  • 스택에 setTimeout()함수가 스택에 올라가고 브라우저는 타이머를 실행시키고 카운트 다운을 시작한다.
  • 이는 setTimeout() 호출 자체는 완료되었다는 의미이고 스택에서 함수가 지워진다.
  • Web API는 갑자기 작성된 코드에 끼어들 순 없다.
  • stask과 콜백 큐가 활약하게 된다.
  • Web API는 작동이 완료되면 콜백을 stask에 푸쉬한다.

콜백 큐

  • 콜백 큐는 Web API 결과값을 쌓아두는 큐이다.
  • 예를 들어 JavaScript에서 setTimeout(cd, 5000)을 호출하게 되면 Web API는 타이머를 동작 시켜 5초 후에 콜백 큐에 cd를 쌓는다.

이벤트 루프란? → 🔄 ← 이거다.

  • 이벤트 루프는 이 전체 시스템에서 아주 단순한 일을 하는 작은 파트이다.
  • 이벤트 루프의 역할은 콜 스택과 콜백 큐를 주시하는 것이다.
  • 콜 스택이 비어있으면 큐의 첫 번재 콜백을 스택에 쌓아 효과적으로 실행할 수 있게 한다.
  • 이벤트 루프는 콜 스택이 비어질 때까지 기다린 후 콜백 큐에 있는 콜백을 콜 스택에 넣어주는 역할을 한다.
  • Web API의 콜백이 완료되었다면 콜백은 큐에 쌓이게 되고, 이벤트 루프에 의해서 실행된다.
  • 모든 종류의 Web API는 동일한 방식으로 동작한다.
  • 이 과정은 비동기 함수가 호출되는 방식이다.
  • AJAX 요청은 URL로 호출할 때 콜백을 함께 실행하게 된다.

이벤트 루프를 막지 말라는 것의 의미

  • 스택에 필요없이 느린코드를 쌓아 브라우저가 할 일을 못하게 만들지 말라는 뜻이다.
  • 이미지처리나 애니메이션이 너무 잦아졌을 때, 큐 관리에 주의를 기울이지 않으면 이러한 일이 일어나게 된다.

profile
궁금한걸 찾아보고 공부해 정리해두는 블로그입니다.

0개의 댓글