런타임과 컴파일타임
프로그래밍 언어는 고수준과 저수준 언어로 구분
고수준 언어는 사람이 이해하기 쉬운 형식으로 작성
저서준 언어는 컴퓨터가 이해하기 쉬운 형식으로 작성
자바스크립트는 대표적인 고수준 언어에 속하며 컴파일러나 인터프리터에 의해 저수준 프로그래밍 즉, 기계가 이해할 수 있는 언어로 번역
개발자는 소스코드를 작성
소스코드느는 컴파일러에 의해 기계어코드로 변환되어 실행이 가능한 프로그램이 되는데 이 단계를 컴파일타임이라고 부름
다시 말해 컴파일타임은 스스코드가 컴파일 과정을 거쳐 컴퓨터가 인식할 수 있는 기계어 코드로 변환되어 실행할 수 있는 프로그램이 되는 과정을 의미한다.
소스코드의 컴파일이 완료되면 프로그램이 메모리에 적재되어 실행되는데 이 시간을 런타임이라고 한다. 즉, 런타임은 컴파일 과정을 마친 응용 프로그램이 사용자에 의해 실행되는 과정
자바스크립트 런타임
자바스크립트 런타임은 자바스크립트가 실행되는 환경
대표적인 자바스크립트 런타임: 크롬, 사파리, Node.js
자바스크립트 런타임 구성 요소: 자바스크립트 엔진, 웹 API,콜백 큐,이벤트 루프, 렌더 큐
런타임 에러
💡 자바스크립트는 대표적인 인터프리터 언어로 별도의 컴파일 과정이 존재하지 않는다고 알려져 있다. 하지만 엄밀히 말해 자바스크립트에도 컴파일 단계가 존재. 자바스크립트를 해석하고 실행하는 역할을 하는 v8 엔진은 때때로 자바스크립트 코드를 최적화하기 위해 컴파일 단계를 거침.let foo;
foo.bar;//TypeError:Cannot read properties of undefined
const testArr= null;
if(tetArr.length === 0){
console.log("zero length")
}
//TypeError:Cannot read properties of null
function testFn(){
const foo ="bar";
}
console.log(foo);
//ReferenceError: foo is not defined
타입스크립트의 컴파일
일반적으로 캄파일은 추상화 단계가 다른 고수준 언어에서 저수준 언어로 변환되는 과정을 가리킴.
타입스크립트는 tsc라고 불리는 컴파일을 통해 자바스크립트 코드로 변환.
하지만 타입스크립트는 고 수준언어가 저 수준 언어로 변환되는 것이 아니라 고수준 언어가 또 다른 고수준 언어로 변환되는 것이기 때문에 컴파일이아닌 트랜스파일이라고 부름.
이러한 변환 과정은 소스코드를 다른 소스코드로 변환하는 것이기에 타입스크립트 컴파일러를 소스대 소스 컴파일러라고 지칭하기도 함.
타입스크립트는 .ts → .js 파일로 생성
타입스크립트 컴파일러는 소스코드를 해석하여 AST(최소구문트리)를 만들고 이후 타입 확인을 거친 다음에 결과 코드를 생성
타입스크립트 컴파일러가 소스코드를 컴파일하여 프로그램일 실행되기까지의 과정
타입스크립트는 컴파일타임에 타입을 검사하기 때문에 에러가 발생하면 프로그램이 실행되지 않는다. 이러한 특징 때문에 타입스크립트를 컴파일타임에 에러를 발견할 수 있는 정적 타입검사기라고 부른다.
코드 검사기로서의 타입스크립트 컴파일러
타입스크립트 컴파일러는 코드에 타입 오류가 없는지를 확인. 타입스크립트에서는 컴파일타임에 코드 타입을 확인하기 때문에 코드를 실행하지 않고도 오류가 있다는 것을 바로 알 수 있다.
타입스크립트는 정적으로 코드를 분석하여 에러를 검출하며, 코드를 실행하기 전에 자바스크립트 런타임에서 발생할 수 있는 에러를 사전에 알려준다.
자바스크립트에서는 런타임에서 발견할 수 있는 에러를, 타입스크립트에서는 컴파일타임에 발견하여 실행 과정에서 발생할 수 있는 문제를 방지.
타입스크립트 컴파일러는 tsc binder를 사용하여 타입 검사를 하고, 컴파일타임에 타입 오류를 발견.
코드 변환기로서의 타입스크립트 컴파일러
타입스크립트 컴파일러는 타입을 검사한 다음에 타입스크립트 코드를 각자의 런타임 환경에서 동작할 수 있도록 구버전의 자바스크립트로 트랜스파일한다.
타입스크립트 소스코드는 브라우저와 같은 런타임에서 실행 x
타입스크립트 소스코드를 파싱하고 자바스크립트 코드로 변환해야 비로소 실행
타입스크립트 컴파일러의 역할 크게 2가지로 나뉜다.
tsc와 바벨은 소스코드를 ES5 이하의 자바스크립트 코드로 컴파일해준다는 점에서 동일
하지만 tsc와 달리 바벨은 타입 검사를 하지 않는다. 최신 버전의 자바스크립트 코드를 낮은 버전으로 컴파일 하는 것이 바벨의 주된 역할.
타입스크립트 컴파일러는 다섯 단계를 거쳐 타입 검사와 자바스크립트 소스 변환을 진행
타입스크립트 컴파일러는 tsc 명령어로 실행된다. 컴파일러는 tsconfig.json에 명시된 컴파일 옵션을 기반으로 컴파일을 수행. 먼저 전체적인 컴파일 과정을 관리하는 프로그램 객체가 생성된다. 이 프로그램 객체는 컴파일할 타입스크립트 소스 파일과 소스 파일 내에서 임포트된 파일을 불러오는데, 가장 최초로 불러온 파일을 기준으로 컴파일 과정이 시작.
타입스크립트 소스를 자바스크립트로 변환하기 위한 첫 번째 단계는 스캐너.
스캐너는 타입스크립트 소스 파일을 어휘적으로 분석하여 토큰을 생성하는 역할
스캐너가 소스 파일을 토큰으로 나눠주면 파서는 그 토큰 정보를 이용하여 AST를 생성
AST는 컴파일러가 동작하는 데 핵심 기반이 되는 자료 구조로, 소스코드의 구조를 트리형태로 표현.
AST의 최상위 노드는 타입스크립트 소스 파일이며, 최하위 노드는 파일의 끝 지점으로 구성
스캐너는 어휘적 분석을 통해 토큰 단위로 소스코드를 나누지만 파서는 이렇게 생성된 토큰목록을 활용하여 구문적 분석을 수행. 이를 통해 코드의 실질적인 구조를 노드 단위의 트리 형태로 표현
각각의 노드는 코드상의 위치, 구문 종류, 코드 내용과 같은 정보를 담고 있다.
바인더의 주요 역할은 체커단계에서 타입 검사를 할 수 있도록 기반을 마련하는 것이다.
바인더는 타입 검사를 위해 심볼이라는 데이터 구조를 생성.
심볼은 이전 단계의 AST에서 선언된 타입의 노드 정보를 저장한다.
체커는 파서가 생성한 AST와 바인더가 생성한 심볼을 활용하여 타입 검사를 수행. 이 단계에서 체커의 소스 크기는 현재 기준 약 2.7 MB 정도로 이전 단계 파서의 소스 크기보다 매우 크다.
체커의 주요 역할은 AST의 노드를 탐색하면서 심볼 정보를 주어진 소스 파일에 대해 타입 검사를 진행하는 것.
체커의 주요 역할은 AST의 노드를 탐색하면서 심볼 정보를 불러와 주어진 소스 파일에 대해 타입 검사를 진행하는 것. 체커의 타입 검사는 다음 컴파일 단계인 이미터에서 실행
이미터는 타입스크립트 소스 파일을 변환하는 역할을 한다. 즉, 타입스크립트 소스를 자바스크립트(js)파일과 타입 선언 파일(d.ts.)로 생성
이미터는 타입스크립트 소스 파일을 변환하는 과정에서 개발자가 설정한 타입스크립트 설정파일을 읽어보고, 체커를 통해 코드에 대한 타입 검증 정보를 가져온다. 그리고 emitter.ts 소스 파일 내부의 emitFiles()함수를 사용하여 타입스크립트 소스 변환을 진행.
자바스크립트의 컴파일 과정을 정리하면 다음과 같다.