자바스크립트 핵심 개념과 동작 원리[1] – 자바스크립트 엔진, 런타임, 실행 컨텍스트, 콜 스택

지금까지는 자바스크립트의 기본까지 알아봤고 이제는 한 단계 더 나아갈 차례이다. 자바스크립트의 동작 원리에 관한 주요 토픽에 대해 공부해 본다.

자바스크립트의 9가지 특징

파이썬을 공부한 적이 있기에 이름은 익숙한 개념들이 많지만 볼 때마다 새롭게 느껴지는 놀라운 지점…^^;;;;;

  • 고수준(High-level)
  • 가비지 컬렉터(Garbage-collected)
    • 자바스크립트 엔진은 내부에서 가비지 컬렉터를 끊임없이 동작시킨다.
  • 인터프리터 또는 JIT(Interpreted or just-in-time(JIT) compiled)
    • 자바스크립트는 인터프리터 언어였지만, 모던 자바스크립트는 JIT 컴파일을 사용한다.
  • 멀티 패러다임(Multi-paradigm)
  • 프로토타입 기반 객체 지향(Prototype-based object-oriented)
    • 자바스크립트는 원형 객체(프로토타입)를 복제하여 새로운 객체를 생성하는 프로토타입 기반 객체 지향 언어이다.
    • 자바스크립트에서 단순 원시 타입(simple primitive)인 문자열, 숫자, 불리언, null, undefined를 제외한 모든 타입은 객체다.
    • 자바스크립트의 객체는 원형 객체(Object.Prototype)로 부터 생성되며, 생성된 객체는 원형에 대한 프로토타입 링크(__proto__)를 갖게 된다.
  • 일급 함수(First-class Function)
    • 자바스크립트에서 함수는 일급 객체이므로 함수의 파라미터로 사용하는 등의 동작이 가능하다.
  • 동적(Dynamic)
    • 자바스크립트는 변수 선언시 데이터 타입을 지정할 필요가 없고, 변경도 가능한 동적 언어이다.
  • 싱글 스레드(Single-threded)
    • 자바스크립트는 싱글 스레드 기반으로 동작한다.
  • 논블로킹 이벤트 루프(Non-blocking event loop)
    • 자바스크립트는 여러 작업이 동시에 진행되도록 하기 위해 이벤트 루프를 사용한다.

자바스크립트 엔진(JavaScript Engine)과 런타임(Runtime)

  • 자바스크립트 엔진은 자바스크립트 코드를 실행하는 프로그램을 의미한다.
  • 각각의 브라우저는 저마다 자바스크립트 엔진을 가지고 있다.
    • e.g. google V8 engine은 크롬과 노드에서 사용됨
  • JS 엔진은 콜스택(Call Stack)과 힙(Heap)을 가지고 있다.
    • 콜스택은 JS 코드가 실행되는 공간이다.
    • 힙은 메모리상에서 JS 객체들이 존재하는 공간이다.

JIT란?

  • 코드가 실행되는 방식은 크게 두가지로 나눠볼 수 있다.
    • 1. 컴파일(Compilation)
      • 소스코드 ➡️ 머신코드 파일(portable binary file) ➡️ 프로그램 실행
      • 소스코드를 머신코드로 변환하는 컴파일링 과정을 거친 후에 코드를 실행한다.
    • 2. 인터프리터(Interpretation)
      • 코드를 한줄씩 읽어가며 (여전히 머신코드로 변환하여야 함) 실행한다.
      • 자바스크립트가 처음 등장했을 때는 인터프리터 언어였다.
  • 인터프리터 언어는 컴파일 언어보다 느릴 수 밖에 없다. 더 빠른 웹을 위해서는 새로운 방식이 필요했다.
  • 모던 자바스크립트는 JIT(Just-in-time) 컴파일 방식(컴파일과 인터프리터의 믹스)으로 동작한다.
    • 소스코드 ➡️ 머신코드(not a portable file) ➡️ 실행
  • JS 엔진의 컴파일과 실행 과정
    • Parsing: AST로 변환 ➡️ Compilation: 머신코드로 컴파일 ➡️ Execution
    • 실행 중에도 최적화(Optimization)를 거치며 다시 컴파일을 진행한다.
    • 최적화는 특별한 스레드에서 진행되어 우리가 코드를 통해 접근할 수 없다.
  • 따라서 JS가 인터프리터 언어라고 말할 수는 없다.

런타임

  • 런타임이란 자바스크립트를 실행하기 위해 필요한 모든 것들이 포함된 컨테이너를 의미한다.
    • e.g. 브라우저
  • 브라우저의 런타임에는 엔진(Call Stack, Heap), Web API(DOM, Timers, Fetch API…/브라우저 제공), Callback Queue(click, timer, data…) 등이 포함되어 있다.
  • Event Loop
    • 콜백 큐에서 이벤트를 꺼내 콜스택에 넣어줘서 코드를 실행하게 하는 프로세스
  • node.js 와 같이 브라우저 외에도 자바스크립트 런타임이 존재할 수 있다.
    • node.js 런타임에는 브라우저가 제공하는 Web API가 포함되어 있지 않다.
    • 대신 C++ bindings과 쓰레드 풀이 존재한다.

실행 컨텍스트(Execution Contexts)

  • 자바스크립트가 실행되는 추상적인 환경을 의미한다.
  • 소스코드가 실행되기 위해 필요한 모든 정보(소스코드, 변수, 인자…)들이 들어 있다.

컴파일 후의 실행 순서

  • 1. Creation of global execution context(for top-level code)
    • function 안에 있지 않은 코드들(변수 선언 등)
    • 오직 하나의 global execution context (EC) 존재
      • Default Context
  • 2. Execution of top-level code(inside global EC)
  • 3. Execution of functions and waiting for callbacks
    • One execution context per functions
    • 함수의 콜마다 새로운 EC가 생성된다.
    • 모든 EC는 콜 스택에 들어간다.

실행 컨텍스트에 포함된 것들

  • Creation phase에 생성되는 것들
    • Variable Environment
      • let, const, var, functions, arguments objects
    • Scope chain
    • this keyword
  • Arrow 함수는 자체적인 arguments, this 를 갖지 않는다. (가장 가까운 레귤러 함수의 것을 가짐)

콜 스택(The Call Stack)

  • 콜 스택은 Execution Context들이 쌓이는 공간을 의미한다.
  • 스택의 가장 위에는 현재 실행되고 있는 EC가 존재한다.
  • 하나의 EC 실행이 끝날 때 마다 스택에 쌓인 컨텍스트가 제거되고 아래 위치한 EC로 이동
  • 결국 Global EC가 마지막에 실행된다.
    • 브라우저 탭을 종료시키기 전까지 대기(stay) 상태
    • 탭을 종료시키면 Global EC도 제거된다.

Leave a Reply

Your email address will not be published. Required fields are marked *