컴퓨터는 우리가 작성한 JavaScript
파일을 이해하지 못합니다. 따라서 위 그림처럼 JavaScript Engine
이 JavaScript
파일을 컴퓨터가 이해할 수 있는 형태로 변환시켜 줍니다.
JavaScript Engine
의 종류는 다양하지만 그 중 크롬 브라우저에서 사용되는 V8
엔진을 예시로 JavaScript Engine
을 살펴보겠습니다.
💻 Engine
👨💻 Parser
작성한 코드를 분석(lexical analysis)해 ‘토큰(token)’이라는 작은 단위로 코드를 분해하는 역할을 합니다.
👨💻 AST (Abstract Syntax Tree)
만들어진 토큰들을 기반으로 Parser
는 추상 구문 트리(AST)를 만듭니다.
AST
는 이름에서 알 수 있듯이 트리 형태를 띄고 있습니다. 또한 원래 구문의 모든 세부사항이 표현되지 않기 때문에 추상(Abstract)이라는 이름이 붙었습니다. AST
는 이곳에서 테스트해 볼 수 있습니다.
👨💻 Interpreter, Compiler
🖊 Interpreter VS Compiler?
V8
엔진에서Interpreter
와Compiler
가 어떤 역할을 하는지 알아보기 전에 각각이 무엇인지 어떤 특성을 가지고 있는지를 먼저 살펴보겠습니다.
Interpreter
는 코드를 즉석해서(on the fly) 읽고Bytecode
로 변환해 실행합니다. 따라서 초기 속도가 빠르다는 장점이 있습니다.
하지만 많은 코드를 실행시킬수록 느려질 가능성이 있습니다. 아래의 예시를 살펴보겠습니다.
1 2 3 4 5 6 7 function multiply(a, b) { return a * b; } for (let i = 0; i < 1000; i++) { multiply(5, 4); }위 코드는
multiply
라는 함수를 반복문을 통해 여러번 실행시키는 코드입니다.
interpreter
는multiply
라는 함수가 항상 같은 값을 반환하더라도 매번 실행하게 됩니다. 이는 비효율적이 작업으로, 이런 작업이 여러군데에서 발생하게 되면 성능저하로 이어지게 됩니다.
Compiler
는Interpreter
와 반대되는 특성을 가지고 있습니다.
Compiler
는 코드가 실행되기전, 사전에 모든 코드를 읽어Machine Code
로 변환합니다.
따라서Interpreter
보다 초기 속도가 느리다는 단점이 있지만, 전체 코드를 변환하는 과정에서 최적화가 되어interpreter
에서 발생하는 비효율적인 작업을 피할 수 있다는 장점이 있습니다.위에서 서술한 특징을 정리하면 아래와 같습니다.
Interpreter Compiler 초기 속도 사전 변환 단계 없이
한줄씩 읽어 가며 변환 및 실행하므로 빠름사전 변환 단계를 통해 모든 코드를
변환한 후 실행하므로 상대적으로 느림성능 최적화 과정이 없기 때문에 성능 저하가 발생할 수 있음 사전 변환 단계에서 최적화 과정이
포함되어 성능적으로 유리함
V8
엔진에서는 위에서 살펴본 두가지 방식의 장점을 합친 JIT(Just In Time) Compiler
방식으로 코드를 변환해 실행합니다.
먼저 ignition
이라고 불리는 V8
엔진의 interpreter
가 AST
를 읽어 bytecode
로 변환하여 실행시킵니다.
이 과정에서 profiler
는 코드를 모니터링하면서 최적화 될 수 있는 부분을 찾습니다.
만약 최적화 할 수 있는 부분이 있다면 interpreter
는 turbofan
이라 불리는 compiler
로 코드를 보냅니다. compiler
는 해당 코드를 최적화해 machine code
로 변환합니다.
최적화된 코드가 상대적으로 덜 쓰이게 된다면 compiler
는 다시 interpreter
로 코드를 전달하게 됩니다.
이렇게 두가지 방식의 장점을 합쳐 V8
엔진은 JavaScript
파일을 실행시킵니다.