AST(Abstract Syntax Tree)는 소스 코드를 트리 구조로 표현한 것입니다. Babel, ESLint, Prettier 같은 도구들이 모두 AST를 기반으로 동작합니다. AST를 이해하면 코드 변환 도구를 직접 만들 수도 있습니다.

AST란?

JS
// 이 코드가
const x = 1 + 2;

// AST로 변환되면
{
  type: "Program",
  body: [{
    type: "VariableDeclaration",
    kind: "const",
    declarations: [{
      type: "VariableDeclarator",
      id: { type: "Identifier", name: "x" },
      init: {
        type: "BinaryExpression",
        operator: "+",
        left: { type: "NumericLiteral", value: 1 },
        right: { type: "NumericLiteral", value: 2 }
      }
    }]
  }]
}

코드 변환 파이프라인

PLAINTEXT
소스 코드 → 파싱(Parse) → AST → 변환(Transform) → 수정된 AST → 생성(Generate) → 변환된 코드
JS
const { parse } = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const generate = require("@babel/generator").default;

// 1. 파싱
const ast = parse("const x = 1 + 2;");

// 2. 변환 — 모든 숫자를 2배로
traverse(ast, {
  NumericLiteral(path) {
    path.node.value *= 2;
  },
});

// 3. 생성
const output = generate(ast);
console.log(output.code); // "const x = 2 + 4;"

Babel 플러그인 만들기

console.log 자동 제거

JS
// babel-plugin-remove-console.js
module.exports = function () {
  return {
    visitor: {
      CallExpression(path) {
        if (
          path.get("callee").matchesPattern("console.log") ||
          path.get("callee").matchesPattern("console.debug")
        ) {
          path.remove();
        }
      },
    },
  };
};

화살표 함수 변환

JS
// 화살표 함수 → 일반 함수
module.exports = function ({ types: t }) {
  return {
    visitor: {
      ArrowFunctionExpression(path) {
        const { params, body } = path.node;

        // 본문이 표현식이면 return 문으로 감싸기
        const funcBody = t.isBlockStatement(body)
          ? body
          : t.blockStatement([t.returnStatement(body)]);

        path.replaceWith(
          t.functionExpression(null, params, funcBody)
        );
      },
    },
  };
};

// 입력:  const add = (a, b) => a + b;
// 출력:  const add = function(a, b) { return a + b; };

자동 에러 로깅

JS
// 모든 catch 블록에 자동으로 에러 로깅 추가
module.exports = function ({ types: t }) {
  return {
    visitor: {
      CatchClause(path) {
        const param = path.node.param;
        if (!param) return;

        // 이미 로깅이 있는지 확인
        const hasLogging = path.node.body.body.some(
          (stmt) =>
            t.isExpressionStatement(stmt) &&
            t.isCallExpression(stmt.expression) &&
            stmt.expression.callee?.property?.name === "error"
        );

        if (!hasLogging) {
          const logStatement = t.expressionStatement(
            t.callExpression(
              t.memberExpression(t.identifier("console"), t.identifier("error")),
              [t.stringLiteral("[Error]"), param]
            )
          );
          path.node.body.body.unshift(logStatement);
        }
      },
    },
  };
};

AST Explorer 활용

PLAINTEXT
https://astexplorer.net/
1. 왼쪽에 소스 코드 입력
2. 오른쪽에 AST 트리 확인
3. 파서를 "babel" 선택
4. Transform 탭에서 플러그인 코드 테스트

path API 주요 메서드

JS
// path — AST 노드의 래퍼
path.node;           // 현재 노드
path.parent;         // 부모 노드
path.parentPath;     // 부모 path

// 탐색
path.get("body");    // 자식 path
path.getSibling(0);  // 형제 path
path.findParent((p) => p.isFunction()); // 조건에 맞는 부모 찾기

// 수정
path.replaceWith(newNode);   // 노드 교체
path.remove();               // 노드 제거
path.insertBefore(node);     // 앞에 삽입
path.insertAfter(node);      // 뒤에 삽입

// 검사
path.isIdentifier();         // 타입 확인
path.isIdentifier({ name: "x" }); // 세부 조건
path.matchesPattern("console.log");

ESLint 규칙도 AST 기반

JS
// no-console 규칙의 간소화 버전
module.exports = {
  create(context) {
    return {
      MemberExpression(node) {
        if (
          node.object.name === "console" &&
          node.property.name === "log"
        ) {
          context.report({
            node,
            message: "console.log 사용 금지",
          });
        }
      },
    };
  },
};

AST 기반 도구들

도구용도AST 활용
Babel트랜스파일링코드 변환
ESLint린팅패턴 검출
Prettier포매팅코드 재생성
TypeScript타입 체크타입 분석
webpack번들링의존성 분석
jscodeshift코드모드대규모 리팩터링

**기억하기 **: AST는 코드를 트리로 표현한 것이며, Parse → Transform → Generate가 코드 변환의 3단계입니다. astexplorer.net에서 AST 구조를 탐색하면 Babel 플러그인이나 ESLint 규칙을 쉽게 작성할 수 있습니다.

댓글 로딩 중...