다시 정리하는 JS의 구동 원리

Ethan Yu·2023년 6월 10일
1
post-thumbnail

자바스크립트 엔진은 인터프리터라구요? 컴파일도 하는데요...

자바스크립트를 다시 공부하면서 구동 원리를 정리해봅니다.

자바스크립트는 이렇게 동작해요.



(출처: https://curryyou.tistory.com/237 )

1. 자바스크립트 입력

  • 고급 언어인 자바스크립트 코드가 엔진에 의해 처리되기 시작합니다.
  • 궁극적으로는 기계어로 변환되어야 합니다. 컴퓨터가 이해할 수 있어야 하니까요.

2. 토크나이징

  • 고급 언어를 받아 토큰으로 토크나이징을 시작합니다.
  • 이때 토큰은 의미를 가진 최소 단위입니다.
  • 이러한 오브젝트 형식을 떠올리면 좋을 것 같아요.
	/* 놀랍게도 let이었던 것 */
	{
    	type: "keyword",
        value: let
    }
    /* 놀랍게도 value였던 것 */
    {
    	type: "name",
        value: num
    }
    /* 놀랍게도 = 였던 것 */
    {
    	type: "=",
        value: "="
    }

3. 파싱

  • 토큰을 분석하여 문법적으로 의미를 갖는 트리 구조 형태로 만듭니다.

  • 이를 AST라고 합니다!

  • 이때 트리의 각 노드는 소스코드에서 발생되는 어떤 구조들을 의미합니다.

  • [위키백과] 에서는 컴파일의 한 단계로서 파싱을 명시하고 있는데요, 자바스크립트에서의 파싱은 컴파일 단계가 아닌 인터프리팅의 전 단계에서 발생한다고 볼 수 있을 것 같아요. ( 위키백과의 컴파일은 다소 거시적인 차원의 컴파일을 말하는 것 같아요. )

  • 요랬던 코드가...

  • 요렇게 바뀝니다.

  • https://astexplorer.net/ 에서 추상문법트리의 파싱 결과물을 확인할 수 있더라구요!


4. 인터프리팅

  • AST를 바이트 코드로 변환합니다.
  • 자바스크립트는 소스코드의 한줄 한줄을 읽고 인터프리팅합니다 -> 과연??!

5. 기계어 변환

  • 가상머신은 바이트 코드를 CPU가 이해할 수 있는 기계어로 변환합니다.
  • 가상머신은 CPU별로 최적화된 기계어를 만들어냅니다.
  • 변환된 기계어는 이제 컴퓨터가 소화할 수 있어요.

아니 컴파일을 안하는데요?


토크나이징 -> 파싱 -> 인터프리팅 -> 기계어 변환 과정에서 컴파일이 없는데요?

자바스크립트는 파싱을 끝내고 결과로 도출된 AST를 인터프리팅하려 합니다. 이때, 인터프리터에 전달되는 AST는 컴파일 후보가 됩니다.

🔥 V8엔진의 이야기 : 인터프리팅을 감시하는 Profiler 🔥

  • 오늘도 V8은 인터프리팅을 시작합니다.
  • 끊임없이 밀려들어오는 코드에 V8은 환멸을 느낍니다.
  • console.log()는 왜이리 많이 호출하는 것인지, 소스코드에서 사용될 때마다 console.log()를 읽고 처리하는데 지쳐버렸습니다.
  • 지쳐버린 V8은 옆자리에 있던 Profiler를 시켜 console.log()를 미리 실시간으로 "컴파일"해놓도록 부탁합니다.
  • Profiler는 반복되는 console.log()를 실시간으로 컴파일하고 V8에게 넘깁니다. V8은 이제 AST의 각 노드를 읽고 처리(인터프리팅)할 필요가 없습니다.
  • V8은 이제 행복합니다.

그래서 결론은?


  • 자바스크립트의 컴파일러는 "필요한 경우"에만 컴파일을 하는 JIT컴파일러(just-in-time)라고 할 수 있습니다.
  • 필요한 경우라고 한다면 반복적으로 호출되는 함수를 예로 들 수 있겠습니다.
  • decompile하는 경우도 있습니다. Profiler도 사람(?)이니까 실수할 때가 있죠. 필요하다고 판단해서 컴파일을 해놓았는데, 필요하지 않았던 경우나 오류가 있는 경우에는 재빠르게 decompile을 시도합니다.
profile
🧐 사용자와 개발자를 모두 배려하고 싶은 개발자. 백엔드부터 임베디드까지 다양하게 개발하다가 지금은 🎨 프런트엔드에 자리잡았어요.

0개의 댓글