자바스크립트.. 너 어떻게 동작하니? (+ V8 엔진)

yesme·2022년 8월 25일
0
post-thumbnail

본 게시글은 How Does JavaScript Really Work? (Part 1) 내용을 번역한 내용입니다.
오역 및 의역이 있을 수 있습니다 🥲 (있으면 알려주세요!)

Bit

모듈 JavaScript 애플리케이션을 빌드할 수 있게 도와주고, 컴포넌트를 프로젝트나 팀과 쉽게 공유할 수 있는 툴

프로그래밍 언어는 어떻게 동작할까?

일단 JS를 시작하기 전에, 프로그래밍 언어들은 어떻게 동작하는지부터 이해해봅시다.

컴퓨터는 마이크로프로세서로 이루어져있고, 우리는 (아주 작지만 강력한) 코드로 이것을 조작할 수 있죠. 하지만 언어를.. 어떻게 마이크로프로세서가 이해할 수 있을까요?

기계의 enterprise 레벨 코드나, 어셈블리어를 작성하는 것은 사실상 불가능 하기때문에, 우리는 고수준언어(Java나, Python 같은)가 필요합니다. 그리고 이 언어로 작성된 것을 기계어로 바꿔주는 컴파일러나 인터프리터도 (당연히) 필요할 것 입니다.

Compilers and Interpreters

컴파일러/인터프리터는 프로세스나 다른 언어가 작성한 것들을 기계어로 변경해줍니다.

Interpreter: 즉석에서 파일을 한 줄씩 읽고 번역. 초기에는 이것이 JS가 작동하는 방식이였습니다.
Compiler: 내가 넣은 파일을 기계어가 해석할 수 있는 새로운 파일을 미리 만듦.

다시말해, 우리가 작성한 JS 코드를 기계어로 바꿀 수 있는 두가지 방법이 있습니다.

  1. 코드가 컴파일 되면, 컴퓨터는 코드가 실행되기전에 무엇이 시작되고 어떤 결과를 만들어 낼 것인지 미리 알 수 있지만 프로세스 하기에 앞서 시간이 소요된다는 단점이 있습니다.
  2. 인터프리터를 사용하면, 즉시 실행되고 빠르다는 장점이 있지만 최적화가 좋지않아 큰 애플리케이션의 경우 느리다는 단점이 있습니다.

ECMAScript를 만들어낸 똑똑한 사람들은 두 프로세스의 장점을 섞어 JIT(Just-in-time) 컴파일러를 만들어냅니다. Javascript는 인터프리터처럼 실행되지만 실제 구현과 실행은 엔진에 의존하죠. 이제 V8에서 사용하는 전략에 대해 살펴볼까요?

Javascript to Machine code

Javascript는 기계어로 바꾸어주는 머신(엔진)이 존재합니다. 다른 언어들과 유사하게, (이 엔진은 모든 언어를 사용해 구축할 수 있으므로) 엔진이 하나만 있는 것은 아닙니다.

  • V8은 크롬 브라우저를 위해 구글에서 구현한 엔진
  • SpiderMonkey는 Netscape Navigator에서 처음으로 사용된 엔진이며, 현재는 FireFox에서 사용
  • JavaScriptCore는 애플이 사파리를 위해 만든 엔진

이 엔진들은 상당히 중요하기 때문에 Internet Explorer 뒤의 엔진이 궁금하다면 이 Wikipedia page를 참고하세요.

ECMAScript

나만의 엔진은 어떻게 만들 수 있을까요?
생각보다 간단합니다! javascript의 ECMAScript 규격을 따라하면 돼요.

만약 우리가 번역기를 만든다면, 양 쪽 언어에서 통용되는 단어들을 먼저 알아야겠죠? 이미 우리는 확실한 기계어를 알고 있지만, JavaScript는 표준화가 필요합니다. (기계어와 통용될 단어말이예요!)

이 JavaScript의 표준화는 바로 ECMAScript(Ecma International in a specification) 또는 ES라 불리는 조직에서 처리해줍니다. 그러니까, 이제 블로그/유투브등에서 “ES7에서 업데이트 된 것”에 대한 내용을 보면, ‘아! ECMAScript 표준에 JS에 기능이 추가되었군!’ 라고 생각하면 됩니다.

쉽게말해, ECMAScript는 ECMA-262 기술 규격에 의해 정의된 범용 스크립트 언어로, Javascript는 이 ECMAScript 사양을 준수하는 범용 스크립팅 언어입니다.

좀 더 세부적인 내용은 이 블로그를 참고해보세요.

The V8 engine

  1. V8의 과거

    구글이 많은 프로세스를 처리해야하는 구글 맵 브라우저를 만들었던 때로 돌아가봅시다. 그 당시 JavaScript 구현은 그 거대한 구글맵을 빠르게 처리할만큼 좋지 않았습니다. 구글은 빨리 사람들이 구글맵을 보고 광고를 팔아 💰돈을 벌어야하는데💰, 이런 문제가 있다보니 결국 서비스를 더 빠르고 강력하게 만들자는 생각을 하게됩니다.

    그리고 2008년, 구글은 C++로 (그 빠르다고 하는) V8 엔진을 만들게 됩니다.

  2. Parsing과 트리 만들기

    Javascript 파일이 엔진으로 들어오면, parser가 내가 쓴 코드의 의미를 알아내기 위해 코드를 토큰으로 분해하여 분석합니다. 그 토큰들은 AST(Abstract Syntax Tree)를 만들어 냅니다.

    AST들은 컴파일러가 언어 요소와 키워드의 사용을 검증하는 각각의 의미분석 시에 매우 중요한 역할을 합니다. 나중에는 AST가 실제 바이트코드나 기계어를 생성하는데 사용됩니다.

  3. 엔진의 심장

    • 아까 짧게 말한 것 처럼, Javascript는 TurboFan이라고 하는 JIT 최적화 컴파일러에 의해 컴파일되고, Ignition 인터프리터를 사용합니다.
    • 이전 단계에서 생성된 AST가 인터프리터에 최적화 되지 않은 기계어도 빠르게 생성하고, 지연없이 실행 할 수 있도록 해줍니다.
    • Profiler는 코드를 지켜보면서 최적화 할 수 있는 부분을 찾습니다. (예를 들어, 동일한 결과를 100번 반복하는 for loop 같은..)
    • profiler를 사용하면, 최적화 되어 있지 않던 코드는 컴파일에 전달되어 최적화 되고, 기계어를 실행해 이전에 인터프리터에서 (최적화X) 실행되었던 코드를 바꾸어 줍니다.
    • profiler와 comfiler는 지속적으로 변화하기 때문에, JavaScript 실행능력은 갈수록 개선됩니다.
  4. 그 이후의 이야기

    5.9버전이 릴리즈되기 전에는 두개의 최적화 컴파일러와, 기준 컴파일러를 사용했었습니다.

    • Baseline coompiler(기준 컴파일러)는 full-codegen이라고도 불리며, 최적화 되지않은 기계어를 빠르게 생성
    • 두 개의 최적화 컴파일러(Crankshaft와 TurboFan)은 코드 최적화에 사용

    JavaScript에 몇 가지 기능 추가와 함께, 구조 복잡성 증가로 인해 V8 팀에서는 동일한 파이프라인을 유지하는 것이 힘들어졌고, 이에따라 새로운 파이프라인으로 변경하게 됩니다.
    (이전 접근방식과, 새로운 파이프라인으로 변경 이유에 대해 더 궁금하다면 이곳을 확인해보면 좋아요!)

  5. 미래에는

    V8엔진은 더 좋은 성능을 위해 여전히 개선중입니다. 웹 어셈블리가 형태를 갖추기 시작하면, 파이프라인에 단계가 더 추가될 수도..

결론

수많은 ECMAScript 엔진이 있고, V8은 그 중 구글이 만들어낸 인기있는 엔진 중 하나입니다. 이 블로그 글이 도움이 되었기를 바라며, ..(생략).. 만약 V8 팀와 더 자세한 내용이 궁금하다면 이곳을 참고하세요.

profile
코드 깎는 개발자..

0개의 댓글