-
묵혔다 꺼낸 JS - 컴파일러와 스코프JS 2021. 10. 4. 23:08
컴파일러의 기본 동작 (컴파일레이션)
자바스크립트 코드의 동작을 이해하기 위해서는 먼저 컴파일러의 동작 부터 알아야 할 것이다.
컴파일러의 동작은 3가지로 나뉜다.
- 토크나이징
- 파싱
- 코드 생성
1. 토크나이징
우리가 밑에 있는 것 처럼 코드를 작성한다고 예를 들자
var a = 0; 이라고 한줄의 코드를 작성하면 컴파일러는 먼저 이 줄의 코드를 이렇게 분할한다. (토큰화 시킨다.)
'var', 'a', '=', '0', ';'
이러한 키워드 분할이 가능한 이유는 컴파일러의 Lexical Analyzer(어휘 분석기) 덕분에 가능하다.
Lexical Analyzer는 우리가 작성한 코드 중 공백, 연산자, 세미콜론, 주석 구문과같은 특수기호들을 만나면 끊어 읽어 하나의 토큰을 만든다.
그리하여 위와같은 결과가 나타나는 것이다.
요약. 토크나이징은 컴파일러가 Lexical Analyzer로 코드를 분할 한 뒤 여러개의 토큰을 만든다.
2. 파싱
토크나이징이 완료가 되면 컴파일러는 파싱을 하게 되는데, 파싱은 Syntax Analyzer(구문 분석기)라는 친구가 작성한 언어가 자바스크립트면 자바스크립트 문법에 맞게, C언어라면 C언어 문법에 맞게 해석을 적용한다.
우리가 평소 오류를 범할 때 컴파일러는 Syntax Analyzer로 오류를 잡아내게 되고 우리에게 이러이러한 오류가 있다고 알려주는 것이다.
만약 오류가 없다면 정상적으로 작성한 구문들을 언어의 알맞은 문법을 해석 한 후 AST(Abstract Syntax Tree) - 추상 구문 트리를 생성하게 된다.
맨 처음 작성했던 코드를 자바스크립트의 AST로 변환 된 코드를 한번 보자.
(AST Explorer로 작성한 결과입니다. https://astexplorer.net )
자바스크립트의 AST트리의 결과(JSON으로 후처리 된 결과)로 컴파일러가 파싱과정에서는 언어의 문법에 맞게 처리한 AST라는 트리가 나온 것을 확인 할 수 있었다.
+ 결과의 노드를 손수 그려서 좀 더 간단히 핵심적인것만 따보자. (그림 💩✋주의...)
3. 코드 생성
마지막으로 AST트리를 엔진이 실행 할 수 있는 코드 생성를 생성하고 컴파일러의 작업은 여기서 끝나게 된다. 이제 나머지 코드 실행은 자바스크립트 엔진이 도맡게 된다.
스코프와 자바스크립트 엔진
스코프
스코프는 컴파일러가 코드를 해석할 때 각 변수와 변수의 값들을 미리 저장하고 자바스크립트 엔진에게 필요한 변수의 값을 제공한다. 그리고 스코프는 자바스크립트 엔진에 참조할 변수의 접근영역 담당도한다.
자바스크립트 엔진
자바스크립트 엔진은 자바스크립트의 코드를 컴파일레이션부터 코드 실행, 종료까지 처음부터 끝까지 책임지고 코드 실행하는 핵심적인 역할을 한다.
여기서 잠깐 중간 정리.
그럼 자바스크립트의 동작을 한번 정리해보자.
자바스크립트의 컴파일러가 토크나이징, 파싱으로 AST를 생성, 코드 생성을 함.
스코프는 자신이 가진 변수영역에 자바스크립트 엔진이 원하는 변수값을 참조해주고, 스코프의 변수가 없으면, 상위 스코프를 탐색한다.
자바스크립트 엔진은 스코프에게 변수 참조값을 받고, 받은 값으로 코드의 동작을 담당.
중첩 스코프
중첩 스코프란 스코프 내부에 스코프가 존재할 경우 내부에 있는 스코프를 중첩 스코프라고 일컫는다.
중첩 스코프는 상위 스코프와는 다른 자신의 스코프를 따로 가지고있다. 상위 스코프는 하위 스코프에 접근 할 수 없지만, 하위 스코프는 상위 스코프에 접근이 가능한 특징도 가지고 있다.
엔진이 원하는 변수가 하위 스코프에게 참조되어있지 않을 경우, 상위 스코프로 이동해서 상위 스코프의 참조값을 찾고, 없으면 또 상위 스코프를 찾아, 마지막으로는 전역 스코프에 접근하여 원하는 변수를 찾게된다. 만약 변수를 찾았다면 참조하고, 못찾게된다면 오류를 발생하게 된다.
2번째의 예시는 fn의 스코프에서 a라는 변수의 참조값을 엔진이 찾으려고 했으나, 찾지 못해 상위 스코프인 전역 스코프에 접근하였으나, 전역 스코프에도 참조하고있지 않으므로 에러(ReferenceError)를 발생하게된다.
3번째의 예시는 상위 스코프는 하위 스코프에 접근하지 못한다는 예시를 보여주고있다.
설명하자면 현재 b라는 변수가 fn함수 스코프 내부에 있다. 하지만 b라는 변수를 현재 상위 스코프에서 사용하려고 하나, 상위 스코프는 하위 스코프의 변수에 참조 접근이 불가능한 특성 때문에 이를 해결하려면 상위 스코프에도 b라는 변수를 하나 더 생성해야한다.
스코프 특성 정리.
스코프는 내부에 스코프들이 존재 할 수 있다.
내부에 존재하는 스코프(하위 스코프)들은 해당 스코프의 상위 스코프부터 전역 스코프들의 변수까지 참조 가능하다.
상위 스코프는 하위 스코프들의 변수를 참조하지 못한다. 이 경우 ReferenceError (변수 선언 에러)가 일어난다.
엔진이 하위 스코프에게 변수 참조값을 못 받으면, 전역 스코프까지 접근하여 값을 받고, 못받으면 ReferenceError (변수 선언 에러)가 일어난다.
도움받은 자료들
https://gyujincho.github.io/2018-06-19/AST-for-JS-devlopers
자바스크립트 개발자를 위한 AST(번역)
AST for JavaScript developers(by Bohdan Liashenko)의 번역글입니다.
gyujincho.github.io
https://dev.to/rajesh04159786/javascript-compiler-scope-tdz-in-depth-pf
JavaScript compiler , Scope & TDZ in depth
JavaScript is a compiled & interpreted language Most of the beginners can confuse about this s...
dev.to
https://ko.wikipedia.org/wiki/V8_(자바스크립트_엔진)
V8 (자바스크립트 엔진) - 위키백과, 우리 모두의 백과사전
V8 (자바스크립트 엔진) 위키백과, 우리 모두의 백과사전.
ko.wikipedia.org
'JS' 카테고리의 다른 글
묵혔다가 꺼낸 JS - 스코프의 효용성, 블록 스코프, 호이스팅 (0) 2021.10.12 묵혔다가 꺼낸 JS - 렉시컬 스코프 (0) 2021.10.08 묵혔다 꺼낸 JS - 암시적 변환 (==연산자의 비교연산) (0) 2021.09.29 묵혔다 꺼낸 JS - 암시적 변환 (+, -, &&, ||) (0) 2021.09.28 묵혔다 꺼낸 JS - Falsey, 명시적 강제 변환 (0) 2021.09.21