
어쩐지 오늘은 AST에 대해 알고 싶어졌습니다. 🏄🏻♀️
프로그램 코드의 구조를 나타내는 특성 때문에 컴파일러에서 널리 사용되는 데이터 구조입니다.
컴파일러 구문 분석 단계의 결과
노드로 구성되어있고, 각 노드는 코드의 다양한 구성 요소를 나타냅니다.
노드들은 서로 계층적인 관계를 가지고, 트리 구조에서 루트 노드부터 시작하여 자식 노드로 내려가는 형태로 표현하게돼죠.
const a = 'test';
요걸 AST로 변환시키면 아래처럼 됩니다.
{
"type": "Program",
"start": 0,
"end": 17,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 17,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 16,
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"name": "a"
},
"init": {
"type": "Literal",
"start": 10,
"end": 16,
"value": "test",
"raw": "'test'"
}
}
],
"kind": "const"
}
],
"sourceType": "module"
}
분석
AST는 코드의 구문을 추상화하기 때문에, Javascript 코드를 분석하고 검사하는데 유용해요.
예를 들면 코드에서 사용되는 변수, 함수, 클래스 등의 선언과 참조를 추적하거나
코드의 일관성을 검사하거나, 잠재적인 오류를 감지하는 등 정적 분석 작업을 수행할 수 있습니다.
eslint, tslint 같은 정적 분석 도구에서 AST를 활용해서 코드 검사 기능을 구현할 수 있어요.
타입 체크
Javascript는 동적 언어이기 때문에 런타임에 오류가 발생할 수 있는데요.
정접 타입 체크 도구를 사용해서 코드를 분석하고 타입 오류를 사전에 검출할 수 있습니다.
주로 AST를 사용해서 코드의 타입을 분석하고, 변수, 함수 매개변수, 반환 값 등에 대한 타입 정보를 확인할 수 있어요.
코드를 실행하기 전에 타입 오류를 발견하고,
개발자에게 경고 또는 오류 메시지를 제공해서 프로그램의 안정성과 신뢰성을 높일 수 있답니다.
어디선가 익숙한 설명이지 않나요?!
자주 사용하는 Typescript가 바로 정적 타입 체크 도구에 속합니다.
코드 변환
AST를 편집하거나 변환하여 코드를 수정하거나 재구성하는 작업을 수행할 수 있습니다.
요걸로 코드의 자동화, 리팩토링, 언어 확장등을 할 수 있어요.
var 키워드를 let이나 const로 변환하여 변수 스코프를 명확하게 정의for 루프를 Array.map() 또는 Array.forEach() 메서드를 사용하는 형태로 변환일반적으로 코드 생성 작업을 하려면 AST를 수정해서 새로운 코드를 생성하는 걸로 이루어집니다.
변환 작업을 수행하기 위해 AST 노드를 순회하고, 각 노드의 유형에 따라 적절한 Javascript 코드를 생성해요.
JSX를 Javascript로 변환하는 경우, JSX 요소와 컴포넌트를 Javascript 함수 호출로 변환하는 작업이 수행됩니다.
const element = <h1>내 이름은 씬디</h1>;
const element = React.createElement("h1", null, "내 이름은 씬디");
TSX의 경우 Typescript 컴파일러가 TSX 코드를 AST로 변환한 다음,
AST를 분석하고 수정해서 Javascript 코드로 변환해요.
이를 통해 타입 검사, 코드 변환, 코드 생성이 수행됩니다.
TSX 코드를 Javascript로 변환하는 과정에서 AST를 수정하여 JSX 요소를 Javascript 함수 호출로 변환하거나,
Type Annotation을 제거하고 타입 검사를 수행해요.
Typescript 컴파일러 외에도 Babel, SWC 같은 도구도 TSX를 Javascript로 변환 가능해요.
@babel/traverse 라이브러리를 제공해요@babel/generator 라이브러리를 제공해요.Esprima
var ast = esprima.parse("var a = 'test';");
Acorn
var ast = acron.parse('var a;', {
ranges: true
});
직접 사용해보진 않았는데 다음엔 사용해보고 후기도 올리도록 할게요!
잘못된 부분은 알려주세요 !~!