1. Preview
- 사실 처음부터 타입스크립트가 어떻게 자바스크립트 코드로 변환되는 지 관심 있었던 것은 아니다. 시작은 React에서 제공하는 컴포넌트의 다양한 타입에 대한 정확한 사용법을 알고 싶었다. 타입을 확인하는데 다음과 같은 코드를 발견하고 경악했다.
다음은 리액트 소스 코드의 일부분이다.
type ReactFragment = Iterable<ReactNode>;
type ReactNode = ReactElement | string | number | ReactFragment | ReactPortal | boolean | null | undefined;
??? ReactFragment Type은 Generic으로 ReactNode 타입을 사용하고, 그 ReactNode 타입 안에는 ReactFragment타입이 있는게 아닌가????
위의 코드 상황을 가정하여 타입 선언이 순환 참조되는 예시 코드를 작성했는데, 정상적으로(?) 에러 문구가 표시된다.
다음과 같다.
// Wrong case
type a = b | number;
type b = a | string;
// Correct case
type a = b[] | number;
type b = a | string;
위의 리액트 코드가 왜 작동하는 지 알기 위해 Typescript Compiler를 뜯어보았다.(결국 이유는 아직 알지 못했다... 아시는 분 댓글 남겨주시면 감사하겠습니다.)
답은 알지 못했지만, 답을 찾아가는 과정에서 타입스크립트의 컴파일 과정에 대해 공부할 수 있었다. 그 내용을 정리하고자 한다.
2. Typescript Compiler
타입스크립트는 한마디로 표현하면 Type Safe Javascript라고 볼 수 있다. 기존 Javascript의 경우 type을 선언하지 않고 사용하기 때문에, Runtime에 실제 변수에 값이 할당, 런타임에 타입을 추론한다. 예시는 다음과 같다.
// js
var a = 0;
var b = "0";
console.log(a + 1); // result: 1
console.log(b + 1); // result: "01"
Typescript의 경우, tsc (타입스크립트 컴파일 명령어)를 통해 .ts 소스파일을 .js로 변환한다. 간략한 과정은 다음과 같다.
1. Scanner
Scanner는 소스코드의 모든 Identifier를 분류하는 작업을 한다(어떻게 표현할 지 모르겠어 Tokenize한다고 표현했다.). Preserved word keyword(whitespace, let 등 선언자, number등의 타입 생성자)등과 개발자가 선언한 변수 이름 등이 해당된다. Typescript Playground에 접속하여 코드를 작성하고 Scanner Plugin을 실행시키면, 스캐너가 작성된 코드를 어떻게 분류하는 지 알 수 있다.
Typescript Playground: https://www.typescriptlang.org/play
TS Playground - An online editor for exploring TypeScript and JavaScript
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
www.typescriptlang.org
2. Parser
Parser는 Scanner가 분류한 Token(?)으로 AST를 만드는 과정을 수행한다. AST(Abstract Syntax Tree)는 소스코드의 구조를 프로그래밍 언어의 컴파일 구조에 따라 추상적으로 정리한 트리로, Parser가 위 작업을 수행한다. 매우 감사하게도 Typescript AST Viewer라는 프로그램이 있어, 내가 짠 코드가 어떻게 AST로 변환되는 지 확인할 수 있다. 링크를 걸어두겠다.
Typescript AST Viewer: https://ts-ast-viewer.com/#
TypeScript AST Viewer
ts-ast-viewer.com
3. Checker
Parser에서 만든 AST의 Validation을 Check를 담당한다. Preview에 내가 작성해놓은 코드가 실제 Syntax에 적합한 지 확인하는 로직이 담겨있다. Preview에 있는 Wrong case의 경우, Checker의 타입선언 관련 함수가 실행되고, 에러 발생 시에 diagnostics에 pre-define한 error code를 넘겨준다(위의 예시는 checker -> function getDeclaredTypeofTypeAlias를 참고하면 된다). checker를 무사 통과하면, js 파일이 생성되는 것이다!
3. 마치며
다른 호기심으로 시작해서 타입스크립트 컴파일 과정을 궁금해하는 프로세스가 신기하면서도, 내가 사용하고 있는 프로그래밍 언어에 대한 이해도가 늘어간다는 것이 뿌듯했다(아직 원래 고민하던 질문의 답은 해결되지 않았지만....). 원래 문제도 빨리 해결해야겠다.
* 사실과 다른 내용이 있거나, 미처 공부하지 못해 빠진 내용이 있을 수 있습니다. 첨언, 조언 등 해주시면 감사히 받겠습니다. *
'개발 > Typescript' 카테고리의 다른 글
undefined vs null 차이 (2) | 2025.01.22 |
---|---|
[TIL - Typescript] Truly, Falsy (1) | 2024.05.09 |
[Typescript] JEST란? (단위 테스트 라이브러리) (0) | 2023.03.15 |