자바스크립트 기초 - 1 (자바스크립트 엔진)

김범현·2020년 5월 26일
3

웹 기초

목록 보기
6/8
post-thumbnail

자바스크립트 엔진이란?

자바스크립트 엔진은 자바스크립트 코드를 해석하고 실행하는 인터프리터이다.
대중적으로 알려진 엔진은 구글의 V8엔진인데, 아무래도 가장 많이 사용되는 크롬에서 사용되고, Node.js에서 사용되는 엔진이기도 하기 때문인 듯 하다.

텍스트하지만 렌더링 엔진과 마찬가지로 브라우저마다 다른 엔진을 사용한다.

  • SpiderMonkey : 파이어폭스
  • V8 : 크롬
  • Webkit : 사파리
  • Chakra : 익스플로러, 엣지

자바스크립트 엔진은 메모리 힙과 호출 스택으로 이루어져 있다.

  • 메모리 힙 : 변수와 객체의 메모리 할당이 발생하는 곳
  • 콜 스택 : 코드가 실행될 때마다 호출 스택이 쌓이는 곳

런타임

자바스크립트 엔진에서 제공해주지 않지만 자바스크립트 개발자가 사용하는 setTimeout 과 같은 API들이 있다. 이러한 API들은 브라우저에서 제공하는 Web API이다. 그리고 이런 Web API 의 호출을 제어하기 위한 콜백큐와 이벤트 루프가 있다.

콜스택

자바스크립트는 싱글 쓰레드 언어이기 때문에, 한번에 한가지 작업만 실행하게 된다.
콜 스택이란 프로그램에서 우리가 어디 있는지를 기록하는 자료 구조이다. 함수를 실행하면, 그 함수가 콜 스택의 가장 상단에 위치하게 된다. 그리고 함수의 실행이 종료 되면 그 함수는 스택에서 제거(Pop) 된다.
그리고 호출 스택의 각 항목을 스택 프레임이라고 한다.

스택 오버플로우

function foo() {
  foo();
}
foo();

위와 같은 함수를 호출하게 되면 콜스택 위에 계속 함수가 쌓일 것이다. 그리고 호출 스택의 실제 크기를 초과하게 되면 브라우저는 Maximum call stack size exceeded 라는 에러를 발생시키고 함수를 종료시킨다.

이벤트 루프

호출 스택에 처리 시간이 굉장히 오래 걸리는 함수가 있으면 어떻게 될까? 자바스크립트는 싱글 쓰레드 이기 때문에 함수가 종료될 때까지 다른 작업들이 모두 대기 상태가 될 것이다.
그리고 결국 브라우저는 웹 페이지를 종료할지 여부를 무든 오류메시지를 표시할 것이다.

이런 상황을 제어하기 위해 사용하는 것이 비동기 콜백이다.
즉, 코드 일부를 실행하고 나중에 실행될 콜백 함수를 제공하는 것이다. 비동기 콜백은 즉시 콜스택에 올라가는 것이 아닌, 특수한 시점에 실행이 되므로 스택안에 바로 올라가지 않는다.

그리고 이 콜백 함수들의 스케쥴을 관리하는 것이 이벤트 큐이다.

콜백 큐

자바스크립트 런타임은 콜백 큐를 가지고 있다. 이는 처리할 메시지 목록과 실행할 콜백 함수들의 리스트이다.

setTimeout 를 포함하고 있는 함수가 실행된다고 하면, 함수는 콜스택에 올라갈 것이고, setTimeout 은 콜백 큐에 밀어 넣어진다.
이벤트 루프는 콜스택과 콜백 큐를 감시하면서, 콜스택이 비워지게 되면 콜백 큐에 대기 중인 항목이 있는지 확인하고, 있으면 스택에 올린다.

자바스크립트 삽입 위치

브라우저는 렌더링 도중 자바스크립트를 만나게 되면 이에 대한 해석과 실행이 완료될 때까지 렌더링을 멈춘다. 그렇기 때문에, 렌더링이 정상적으로 끝난 후 실행하기 위해 바디 하단에 스크립트를 두는게 안정적이라는 말을 한다.

  1. head에 삽입되는 경우
  • 무거운 스크립트가 실행되는 경우 렌더링에 방해가 될 수 있다.
  • 제이쿼리와 같은 설정을 위한 스크립트들이 사용된다.
  • DOM이 필요할 경우 document.onload 를 사용하여, load 이벤트 발생 시, 실행되도록 할 수 있다.
  1. 바디 하단에 삽입되는 경우
  • 브라우저의 렌더링이 완료 된 후 실행되기 때문에, DOM을 조작할 수 있다.

하지만! 헤드 태그에서 발생할 수 있는 문제를 해결하기 위해 추가된 속성이 있다.
바로, asyncdefer이다.

<script async src="myAsyncScript.js" onload="myInit()"></script>
<script defer src="myDeferScript.js" onload="myInit()"></script>

위와 같이 async 또는 defer 속성이 추가된 스크립트는 렌더링을 방해하지 않는다.
async 속성은 외부 스크립트에만 사용할 수 있으며, 스크립트를 내려받는 즉시 실행된다.

defer 속성은 비동기적으로 스크립트를 다운로드 하며, 렌더링이 완료된 후 스크립트를 실행한다.

참조

https://blog.asamaru.net/2017/05/04/script-async-defer/
https://junhobaik.github.io/js-script-position/
https://new93helloworld.tistory.com/358

profile
프론트엔드 개발자 입니다.

0개의 댓글