어서와, 개발은 처음이지?

자바스크립트 컴파일레이션(코드의 실행과정) 본문

[기획] 누구도 알려주지 않은 이야기

자바스크립트 컴파일레이션(코드의 실행과정)

오지고지리고알파고포켓몬고 2019. 6. 30. 05:34
반응형



지금부터 다룰 내용들은 개인적으로 고급 개념이라고 생각합니다. 

다만 저의 클라스가 아직 그 영역에 미치지 못하기에 초/중급자의 눈으로 뇌피셜을 섞어서 풀어내보겠습니다.



1. 개요


자바스크립트는 일반적으로 스크립트 언어로써, 인터프리터 언어로 분류되곤 하는데 실은 컴파일러 언어라고 합니다.

자바스크립트의 컴파일레이션은 코드가 실행되기 직전에 순식간에 일어나고, just in time 이라고 표현합니다.


컴파일레이션 과정을 이해하면 호이스팅, this 바인딩, let const 선언 등에서 일어나는 현상을 이해하는데 도움이 됩니다.



2. 컴파일레이션 3단계


자바스크립트 코드는 크게 3단계를 통해 해석(컴파일)됩니다.


1. 토크나이징 / 렉싱 : 코드를 의미있는 조각(token)으로 만드는 과정. (예) var a = 2; -> var, a, =, 2, ;

2 .파싱 : 문법 구조를 반영하여 중첩 원소를 갖는 트리형태로 바꾸는 과정. 파싱의 결과로 만들어진 트리를 AST(추상 구문 트리)라 부름

3. 코드 생성 : AST를 실행코드(기계어)로 바꾸는 과정



3. 엔진, 컴파일러, 스코프의 이해


코드의 해석(컴파일) 관점에서, 코드의 실행으로 관점을 옮겨 보면 엔진, 컴파일러, 스코프가 상호작용하게 됩니다.


- 엔진 : 컴파일레이션 시작부터 끝까지 모든 과정과 프로그램 실행을 책임짐 (런타임 환경을 실질적으로 엔진이 담당하고 있다고 볼 수 있겠습니다.)

- 컴파일러 : 파싱, 코드 생성 등(컴파일레이션)

- 스코프 : 선언된 변수 목록을 작성하고 유지


4. 구문의 실행


var a = 2;라는 코드는 엔진, 컴파일러, 스코프에 의해 아래와 같은 과정으로 실행되게 됩니다.


1. 컴파일러가 var a를 만나면 스코프 안에 변수 a가 있는지 체크 

2. 있으면 선언을 무시하고, 없으면 스코프 안에 a를 선언하라고 요청 

3. 그 후 컴파일러는 a = 2 대입문을 처리하기 위해 엔진이 실행할 수 있는 코드를 생성 

4. 엔진이 실행하는 코드는 먼저 스코프에 a라는 변수가 현재 스코프 내에서 접근할 수 있는지 확인 

5. 가능하다면 엔진은 변수 a를 사용, 아니라면 상위 스코프에서 접근여부 탐색 

6. 글로벌 스코프에서 까지 못찾으면 에러 발생


이를 잘 생각해보면, 컴파일레이션 단계에서 스코프에 기록된 변수가 해당 스코프 내에서 호이스팅이 일어나리라 유추할 수 있습니다.

또한 let, const 같은 선언문은 var와는 다른 해석과정을 거치기 때문에 런타임에서 다르게 동작하겠구나 유추할 수 있습니다.




5. LHS와 RHS


컴파일러가 생성한 코드를 실행할 때, 엔진은 변수 a가 생성된 적 있는지 스코프에서 검색합니다.


이 과정에서 LHS 검색, RHS 검색을 통해 스코프를 탐색하는데, LHS는 사실상 할당의 느낌이고, RHS는 변수 혹은 어떤 참조가 사용될 때, 어딘가 있는 값을 탐색하는 행위로 볼 수 있습니다.


아래 코드를 예로 들어보겠습니다.

function foo(a){
	console.log(a);
}
foo(2);


1. foo(2)가 실행되면서 참조할 수 있는 foo 함수가 있는지 RHS 검색 

2. 스코프에 참조가능한 foo가 있으므로 오류 없이 foo(2) 실행 

3. foo의 파라미터인 a는 LHS 검색으로 foo(a = 2)와 같이 할당 

4. 참조할 수 있는 console 객체가 있는지 RHS 검색 

5. console은 글로벌 스코프에 선언되어 있으므로 오류 없이 실행 

6. console.log의 파라미터 a는 console.log(a = 2) LHS로 할당 (추측컨데 이 과정 전에 log(a)는 foo스코프 내에서 a를(값 2) RHS로 가져오게 될 것임)


사실 어떤게 LHS고 어떤게 RHS인지를 구분해 내는것은 크게 중요하지 않습니다.

이러한 과정을 통해 코드가 실행되는지를 인지하고 있는 것이 핵심입니다.


이 과정을 인지했다면 아래 명제를 어느정도 깊이있게 음미하실 수 있겠습니다.


어느 스코프까지 검색할 것인가, var는 함수 스코프 let const는 블록 스코프. (스코프는 코드에서 {}을 의미합니다.)



6. 마치며


이번 글에서는 자바스크립트 코드가 어떻게 해석되고, 실행되는지에 대한 이론적인 부분을 다뤄봤습니다.


저는 이 부분을 읽으면서 아리송하게 생각했던 호이스팅, 클로저 등의 현상이 적어도 '그냥'일어나는 건 아니구나 하고 받아들일 수 있게 되었습니다.(왜 그렇게 구현했는지는 브랜든 아이크 형님께..)


보통 호이스팅이 뭔가요? 라는 질문은 많이 받아봤어도 그게 왜 일어나나요? 라는 질문은 흔치 않으니까요.


우리는 이 질문에 '컴파일레이션 과정에서 스코프에 기록된 변수들이 엔진에서 실행될 때 최상단에서 선언한 것으로 해석되어지기 때문'이라는 식으로 그럴듯하게 대답할 수 있게 되었습니다.


계속해서 js의 깊은 곳에 대해 알아보도록 하겠습니다.



7. 참고


You don't know js(타입과 문법, 스코프와 클로저) / 갓 심슨 형님께 영광을 바칩니다.





Comments