자바스크립트 엔진?
자바스크립트는 기본적으로 인터프리터 언어
=> 그러면 자바스크립트 소스코드를 바이트코드로 바꿔주는 인터프리터가 필요하잖아?
자바스크립트 코드를 실행하는 프로그램 또는 인터프리터가 자바스크립트 엔진
브라우저마다 여러 엔진 존재
ex) 스파이더몽키, Chakra, JavaScript Core, V8
V8 엔진은 컴파일도 한다던데?
기본적으로 JS는 인터프리터 언어로 분류되긴 하지만 해석 엔진에서 컴파일을 하기도 함
인터프리터 언어로 분류되는 이유는 console에서 스크립트를 작성해 실행하는 과정에서 컴파일러가 필요하지 않기 때문
하지만 대부분의 JS 엔진은 컴파일이 필요한 경우 컴파일을 진행
가장 익숙한 V8 엔진은 ignition이라는 인터프리터와 JITC, TurboFan을 동시에 사용
Just-In-Time Compiler
JITC는 동적 번역이라고도 불림
이름 그대로 프로그램의 바이트 코드를 실제 실행하는 시점에서 기계어로 번역하는 컴파일 기법
하나씩 읽어가며 실행하는 인터프리터보다는 당연히 빠르지만, 미리 컴파일 하는 정적 컴파일 보다는 성능이 떨어짐
느린 인터프리터를 그럼 왜 써?
JS는 동적 언어이기 때문에 let, const, var에 저장된 타입이 실행 시점에서 결정되고,
한번 결정되었다고 해서 변수의 타입이 바뀌지 않을 것이라는 보장도 없음
=> 에러처리나 예외케이스를 고려하면... 기계어로 변환했을 때 양이 너무 많아짐
이러면 인터프리터 방식과 성능 면에서 큰 차이가 없어진다
하지만 이걸 해결하는 AJITC라는게 또 존재
Adaptive JITC
모든 코드를 일괄적으로 같은 최적화를 적용하지 않고, 반복 수행 정도에 따라 유동적으로 서로 다른 최적화 수준을 적용하는 방식
일단 인터프리터로 수행하다가 자주 반복되는 부분이 있으면 RuntimeProfiler의 판단 하에 그부분에만 JITC를 적용한다는 의미
만약 변수의 타입이 바뀌게 되면 JITC는 최적화 된 코드를 버리게 된다
그럼 V8 엔진의 TurboFan은 언제 사용하죠?
간단하게 V8 엔진의 동작방식을 정리하면
- 자바스크립트 코드가 V8 엔진에 의해 추상구문트리로 모두 변환되고
- 추상구문트리로 변환된 자바스크립트 코드는 인터프리터에 의해 바이트 코드로 변환되는데
- 이때 자주 반복되는 코드가 TurboFan으로 보내지고 최적화 된 코드로 컴파일 된다
=> 자주 반복되는 hot code를 확인하는게 AJITC
TurboFan은 최적화 된 코드로 컴파일 하기 위해서 사용한다
자바스크립트 엔진의 동작 방식
Memory Heap
메모리 할당이 일어나는 곳
동적으로 생성된 자바스크립트 객체가 저장되는 장소
Call Stack
자바스크립트 엔진이 코드 실행을 위해 사용하는 메모리 구조
(코드 실행에 따라 호출 스택이 쌓이는 곳)
원시타입 데이터가 저장되는 장소
만약 함수가 실행이 되면 해당 함수는 호출 스택의 가장 상단에 위치하게 되고,
함수의 실행이 끝날 때 해당 함수를 호출 스택에서 제거 => 스택의 역할
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);

스택 오버플로우
재귀함수를 호출하면 콜스택 위에 계속 함수가 쌓이는데
호출 스택의 실제 크기를 초과하는 경우 Maximum call stack size exceeded 에러 발생
그럼 동시에 호출을 실행 할 수는 없는지?
Call stack 에서는 한번의 하나의 호출만 해결 할 수 있음 => 자바스크립트 엔진은 싱글 스레드...!
하지만 비동기 처리가 아예 불가능 한건 또 아님 언어적 특징이 궁금하다면?
런타임
자바스크립트 코드를 실행하는 환경과 규칙을 정의한 것
자바스크립트 엔진 외적인 요소들의 동작과 함께 웹이 동작하므로 이들도 런타임 구성요소에 포함
=> 브라우저에서 제공하는 Web API들과 이벤트 등과 함께 런타임이 이루어진다
버튼 클릭 같은 이벤트나 DOM 이벤트, http 요청, setTimeout 같은 비동기 함수는 Web API를 호출하며 Web API는 콜백 함수를 Callback Queue에 push

이벤트 루프
비동기 함수들을 적절한 시점에 실행시키는 관리자
비동기 함수 작업을 Web API에 옮기고 작업이 완료되면 콜백 큐에 적재했다가 다시 자바스크립트 엔진에 적재해 수행시키는 '작업을 옮기는 역할'
=> Call Stack과 Task Queue에 대기 중인 작업이 있는지 반복적으로 확인해서 작업을 옮겨주는 형태

- 비동기 자바스크립트 코드를 Web APIs를 통해 작업
- 백그라운드 작업이 끝난 결과를 콜백 함수 형태로 콜백 큐에 push
- 처리 준비가 되면 콜 스택에 넣어서 마무리 작업
결국 동시 호출이 가능하다는 소리인가?
JS는 싱글스레드 언어지만 멀티스레드 환경에서 동작하기 때문에 블로킹 없이 여러 호출을 동시에 처리 가능
멀티스레드 환경이 가능한 이유는 이벤트 루프를 통한 비동기적인 콜백 작업에 따른 결과
스택프레임 호출 스택의 각 단계
Web APIs 브라우저에서 제공하는 API 모음으로, 비동기적으로 실행되는 작업들을 전담하여 처리
Callback Queue 비동기적 작업이 완려되면 실행되는 함수들이 대기하는 공간
Task Queue 비동기로 처리되는 함수들의 콜백함수가 들어가는 큐
Microtask Queue 우선적으로 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐
'FE Study' 카테고리의 다른 글
| [FE] JavaScript에서의 클로저(Closure) (0) | 2024.08.09 |
|---|---|
| [FE] JavaScript에서의 this (0) | 2024.08.09 |
| [FE] Debounce와 Throttle (0) | 2024.08.02 |
| [FE] 이벤트 전파와 이벤트 위임 (0) | 2024.08.02 |
| [FE] Border vs Outline (0) | 2024.08.02 |