ts 책 스터디(타입스크립트 컴파일)

MountionRiver·2025년 8월 9일

자바스크립트의 런타임과 타입스크립트의 컴파일

런타임과 컴파일타임

  • 프로그래밍 언어는 고수준 언어와 저수준 언어로 나눠짐.
    고수준 언어: 사람이 이해하기 쉬운 언어
    저수준 언어: 컴퓨터가 이해하기 쉬운 언어

자바스크립트는 대표적인 고수준 언어에 속하며, 컴파일러나 인터프리터에 의해 저수준 언어로 번역되어 실행된다.

자바스크립트 런타임

자바스크립트 런타임은 자바스크립트가 실행되는 환경을 의미한다. 대표적인 자바스크립트 런타임으로 크롬이나 사파리 같은 인터넷 브라우저와 Node.js 등이 있다.
자바스크립트 런타임의 구성 요소: 자바스크립트 엔진, 웹 API, 콜 백 큐, 이벤트 루프, 렌더 큐 등

타입스크립트 컴파일

일반적으로 컴파일은 추상화 단계가 다른 고수준 언어에서 저수준 언어로 변환되는 과정을 가리킨다.

타입스크립트는 고수준 언어가 또 다른 고수준 언어로 변환되는 것이기 때문에 컴파일이 아닌 트랜스파일이라고 부르기도 한다.
넓은 범위의 컴파일 좁은 의미의 트랜스파일

타입스크립트는 · ts 확장자가 붙은 파일을 찾아내서 컴파일한 다음에 ·js 확장자가 붙은 자바스크립트 파일을 만들어낸다. 타입스크립트 컴파일러는 소스코드를 해석하여 AST(최소 구문 트리)를 만들고 이후 타입 확인을 거친 다음에 결과 코드를 생성한다.

  1. 타입스크립트 소스코드를 타입스크립트 AST로 만든다. (tsc)
  2. 타입 검사기가 AST를 확인하여 타입을 확인한다. (tsc)
  3. 타입스크립트 AST를 자바스크립트 소스로 변환한다. (tsc)
  4. 자바스크립트 소스코드를 자바스크립트 AST로 만든다. (런타임)
  5. AST가 바이트 코드로 변환된다. (런타임)
  6. 런타임에서 바이트 코드가 평가evaluate되어 프로그램이 실행된다. (런타임)

1,2 단계는 상시 -> 에디터에서 실시간 작업 흔히 이야기하는 정적 타입검사

빌드시 1,2,3 단계 전부 수행 -> JS 파일 생성

런타임 → JS 엔진(일반적으로 브라우저)이 4,5,6단계 수행

AST(Abstract Syntax Tree)

컴파일러가 소스코드를 해석하는 과정에서 생성된 데이터 구조다. 컴파일러는 어휘적 분석exical
analysis과 구문 분석syntax analysis을 통해 소스코드를 노드 단위의 트리 구조로 구성한다.

타입스크립트 소스코드의 타입은 1~2단계에서만 사용된다. 3단게 이후부터는 타입을 확인 X

타입스크립트 컴파일러의 동작

코드 검사기로서의 타입스크립트 컴파일러

타입스크립트에서는 컴파일타임에 코드 타입을 확인하기 때문에 코드를 실행하지 않고도 오류가 있다는 것을 바로 알 수 있다. 타입스크립트는 코드를 실행하기 전에 자바스크립트 런타임에서 발생할 수 있는 에러를 사전에 알려준다.
즉, 컴파일타임에 문법에러와 타입 관련 에러를 모두 검출한다.

// 원래 js도 안됨 에러를 런타임에서 뱉는게 아니라 컴파일시점에 밷음
const developer = {
  work() {
    console.log("working...");
  }
};

developer.work(); 
developer.sleep();

코드 변환기로서의 타입스크립트 컴파일러

타입스크립트 컴파일러는 타입을 검사후 자바스크립트(사용자가 설정한)로 트랜스파일한다.
타입스크립트 소스코드는 런타임에서 실행될 수 없다.
다음 예시는 타입스크립트 컴파일러가 타입스크립트 파일을 자바스크립트로 변환한 결과를보여준다. 타입스크립트 컴파일러의 target 옵션(사용자가 설정한 버전)을 사용해서 컴파일 된다

타입스크립트 컴파일러는 타입 검사를 수행한 후 코드 변환을 시작하는데, 이때 타입 오류가 있더라도 일단 컴파일을 진행한다. 타입스크립트 코드가 자바스크립트 코드로 변환되는 과정
은 타입 검사와 독립적으로 동작하기 때문.

const name: string = "zig";
// Type 'string' is not assignable to type 'number'
const age: number = "zig";

age 변수를 number 타입으로 선언했지만 문자열 "zig"를 할당하여 타입 에러가 발생한다. 하
지만 자바스크립트로 컴파일할 수는 있다. 다음은 이 코드를 tsc로 컴파일한 것이다.

const name = "zig";
const age = "zig";

타입스크립트 컴파일 이후에는 타입이 제거되어 순수한 자바스크립트 코드만 남는다. 컴파일된 코드가 실행되고 있는 런타임에서는 타입 검사를 할 수 없기 때문에 주의해야 하는 경우도 있다.

// 마찬가지로 에디터에서 에러 띄움
type Shape = Square | Rectangle;
function calculateArea(shape: Shape) {
  if (shape instanceof Rectangle) {
// 'Rectangle' only refers to a type, but is being used as a value here
// Property 'height' does not exist on type 'Shape' Property 
// 'height' does not exist on type 'Square'
  return shape.width * shape.height;
  }else {
    return shape width * shape.width;
  }
}

바벨과의 차이 에러 알려줌

타입스크립트 컴파일러의 구조

타입스크립트는 5단계를 걸쳐 컴파일한다.

스캐너 파서 바인더 체커 이미터
스캐너: ts 토큰화
파서: 토큰 기반 AST 생성
바인더: AST 노드기반 심볼 생성
체커 : AST + 심볼 기반 타입검사ㅁ
이미터: AST+ 코드검사 기반 js 생성

프로그램

  • 타입스크립트 컴파일러는 tsc 명령어로 실행된다. 컴파일러는 tsconfig.json에 명시된 컴파 일 옵션을 기반으로 컴파일을 수행한다. 먼저 전체적인 컴파일 과정을 관리하는 프로그램 객체(인스턴스)가 생성된다. 이 프로그램 객체는 컴파일할 타입스크립트 소스 파일과 소스 파일 내에서 임포트된 파일을 불러오는데, 가장 최초로 불러온 파일을 기준으로 컴파일 과정이 시작된다.

스캐너

타입스크립트 소스 파일을 어휘적으로 분석하여 토큰을 생성하는 역할을 한다. 다시 말해 소스코드를 작은 단위로 나누어 의미 있는 토큰으로 변환하는 작업을 수행한다.

파서

토큰 기반 AST를 생성
업로드중..

바인더

생선한 AST에 등장하는 모든 선언을 심벌로 만들고,
스코프 체인과 심벌 테이블을 구성해 이름 → 선언 연결
이 결과물을 타입체커가 사용해서 타입 분석을 하기 때문에 타입검사의 기반을 마련하는 단계

type SomeType = string | number;

interface SomeInterface {
    name: string;
    age?: number;
}

let foo: string = "LET";

const obj = {
name: "이름",
age: 10,
};
class MyClass {
name;
age;
constructor(name: string, age?: number) {
this.name = name;
this.age = age ?? 0;
}
}

const arrowFunction = () => {};

function normalFunction() { }

arrowFunction();

normalFunction();

const colin = new MyClass("colin");

타입 심벌:
SomeType → TypeAlias Symbol
SomeInterface → Interface Symbol
변수 심벌:
foo → Variable Symbol
obj → Variable Symbol
arrowFunction → Variable Symbol
함수 심벌:
normalFunction → Function Symbol
클래스 심벌:
MyClass → Class Symbol

아래와 같이 스코프 체인 만듬

전역 스코프
 ├─ MyClass (Class)
 │   ├─ 클래스 스코프
 │   │   ├─ name (필드)
 │   │   ├─ age  (필드)
 │   │   └─ constructor
 │   │       └─ 생성자 매개변수 스코프
 │   │           ├─ name (매개변수)
 │   │           └─ age  (매개변수)
 └─ normalFunction (Function)
     └─ 함수 스코프

체커와 이미터

체커는 AST의 노드를 탐색하면서 심볼 정보를 불러와 주어진 소스 파일에 대해 타입 검사를 진행하는 것이다.

checker.ts의 getDiagnostics () 함수를 사용해서 타입을 검증하고 타입 에러에 대한 정보를 보여줄 에러 메시지를 저장한다.

이미터는 타입스크립트 소스 파일을 변환하는 과정에서 개발자가 설정한 타입스크립트 설정 파일을 읽어오고, 체커를 통해 코드에 대한 타입 검증 정보를 가져온다.

그리고 emitter.ts 소스 파일 내부의 emitFiles () 함수를 사용하여 타입스크립트 소스 변환을 진행한다.

  1. tsc 명령어를 실행하여 프로그램 객체가 컴파일 과정을 시작한다.
  2. 스캐너는 소스 파일을 토큰 단위로 분리한다.
  3. 파서는 토큰을 이용하여 AST를 생성한다.
  4. 바인더는 AST의 각 노드에 대응하는 심볼을 생성한다. 심볼은 선언된 타입의 노드 정보를 담고 있다.
  5. 체커는 AST를 탐색하면서 심볼 정보를 활용하여 타입 검사를 수행한다.
  6. 타입 검사 결과 에러가 없다면 이미터를 사용해서 자바스크립트 소스 파일로 변환한다.

0개의 댓글