그래도 프론트엔드 공부한다는 사람인데 자바스크립트 동작원리를 제대로 모르고 있다고 생각이 들어서 한번 공부해봤다.
자바스크립트를 실행하기 위해서는 자바스크립트 엔진이 필요하다
대표적인 엔진으로는 google에서만든 V8엔진이다.
📌 엔진은 Memory Heap, Call Stack으로 구성된다.
아래 사진은 v8엔진의 간단한 그림이다.
❓ 여기서 궁금한 점이 생겼었는데 렉시컬 환경의 환경레코드에는 실행컨텍스트의 값이 저장되어있다고 알고 있었는데 그럼 걔네들은 어디에 있는걸까
❗️ 답은 우선 자바스크립트는 원시값과 객체로 이루어져 있게 되는데 객체는 크기가 동적으로 변하기 때문에 힙 영역에 존재하게 된다.
또한 원시값은 콜 스택 내부의 메모리 영역에 존재하게 된다.
그리고 환경 레코드또한 실행컨텍스트의 일부분이기 때문에 콜 스택에 존재하게 되고
이 환경 레코드에는 원시값이 저장되어 있는 주소 값이 저장되고, 객체의 주소를 알고있는 메모리 공간의 주소가 저장되는 것이라는걸 알게 되었다.
예시는 블로그에 잘나와있어서 가져와 봤다.
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);
스텝별로 확인해보면
printSquare(5)를 Call Stack에 push
printSquare(5)호출 -> 내부의 multiply(x, x)를 Call Stack에 push
2-1. multiply(5, 5) 실행해서 var s에 값 할당. multiply Call Stack에서 pop
console.log(s) Call Stack에 push
3-1. console.log(10) 실행후 Call Stack에서 pop
printSquare(5) 끝났으니 Call Stack에서 pop
이렇게 동작하는걸 확인할 수 있다.
간단하게 정리해 보면 코드에서 객체(변수, 함수)등은Heap Memory에 저장되고
실행할 문장을 Call Stack에 push하고 Heap Memory의 값들을 참조해서 실행하고, 끝나면 pop하고의 과정을 반복한다.
❓ 위 예시만 보면 자바스크립트는 동기적으로만 동작하나? 라는 생각이 들 수 도 있다.
그건또 아니다.
생각해보면 자바스크립트에서 setTimeOut()
을 사용해 본적이 있을텐데
위의 예시를 보면 call Stack이 하나기 때문에 1, 2초쉬고 settimeout, 2가 출력될거라 생각했지만 1, 2, 2초쉬고 settimeout이 출력된다.
💡 이건 자바스크립트엔진 외에 비동기적으로 작업해주는게 또 있는것이다.
그게바로 Event Loop와 Callback Queue이다.
이 개념에 대해 알아보기 전에 기본 개념을 알아보자면
웹 브라우저 혹은 node js 같은 자바스크립트 런타임에서 지원해주는 API이다.
예를 들어 setTimeOut()
, AJAX
같은 애들이다.
런타임은 자바스크립트가 구동되는 환경이다.
나는 컴파일 처럼 코드가 실행되는 시간이라 생각했다. 타임이 들어가서
근데 그냥 환경이라고 한다. 따라서 Nodejs나 브라우저들을 런타임 이라고 하는거다.
📌 Web API나 Event Loop & Callback Queue를 런타임에서 제공해준다고 생각하면 된다.
❗️ 이제 기본 개념들을 알게 되었으니 아래와 같은 자바스크립트 동작 구조가 만들어 졌다.
이제 Event Loop 와 Callback Queue에 대해 알아보자면.
아까 봤던 예제로 동작을 예상해 보면
그림으로 예제를 확인하고 싶으면 아래 참고한 블로그에 가면 있다.
또 이벤트 루프는 우선순위를 따져서 콜 스택으로 보낸다
마이크로태스크 큐, 애니메이트 프레임, 태스크 큐 순으로 우선순위를 가진다.
간단히 설명하면 태스크 큐는 콜백 큐안에 있고 나머지는 따로있다.
그래서 이벤트 루프가 콜 스택이 비면
마이크로태스크 큐 확인 -> 아무것도 없으면
애니메이트 프레임 확인 -> 아무것도 없으면
태스크 큐(콜백 큐)의 값을 순서대로 넣음
의 과정이라고 생각하면 된다.