플로그인을 제작하기 위해선 AST 구조를 알아야 한다.
AST Explorer 에서 AST가 뭔지 알아보자.
에디터에 const myNamy= hwang + 'eunji';를 입력했을때 AST Explorer에 출력된 json의 모습이다.

👻
보기는 했으나 이걸 어떻게 활용하는지..하핳
module.exports = function ({ types: t }) {
  const node = t.BinaryExpression('+', t.Identifier('a'), t.Indentifier('b'));
  console.log('isBinaryEspression:', t.inBinaryExpression(node));
  return {};
};
a+b를 하는 코드 작성inBinaryExpression()을 통해 타입검사를 진행했다.module.exports = function ({ types: t }) {
  return {
    visitor: {
      Identifier(path) {
        console.log('Identifier name:', path.node.name);
      },
      BinaryExpression(path) {
        console.log('BinaryExpression operator: ', path.node.operator);
      },
    },
  };
};
Identifier())Identifier()-개발자가 만든 값(변수, 함수 등)- 함수가 호출되며, 변수가 쓰인 만큼 호출path.node.name 변수명을 나타내며, const myName= hwang + 'eunji에서 myName, hwang에 해당BinaryExpression()함수가 실행path.node.operator는 const myName= hwang + 'eunji에서+연산자에 해당const myName= hwang + 'eunji' 가 입력됬을 때Identifier() 는 2번 호출BinaryExpression() 1번 호출콘솔로그를 제거하는 플러그인을 제작 하기 위해서는 먼저 콘솔로그의 AST를 이해해야 한다.
AST Explorer 사이트에 방문하여 console.log()의 AST를 확인하자
// console.log('hi') 의 JSON 데이터
// 필요없는 옵션 제거함 : start, end)
{
  "type": "Program",
  "body": [
    {
      "type": "ExpressionStatement",
      "expression": {
        "type": "CallExpression",
        "callee": {
          "type": "MemberExpression",
          "object": {
            "type": "Identifier",
            "name": "console"
          },
          "property": {
            "type": "Identifier",
            "name": "log"
          },
          "computed": false
        },
        "arguments": [
          {
            "type": "Literal",
            "value": "hi",
            "raw": "'hi'"
          }]}}
  ],
  "sourceType": "module"
}
- [root]:[type]: Program // 최상위
  - [body]
    - [첫 요소 : `console.log('hi)'`]
      - [type] : ExpressionStatement // 1
      - [expression] : CallExpression // 2
        - [callee]
          - [type] : MemberExpression // 3
          - [object] // 객체 타입과 이름
            - [type] : Identifier  // 4
            - [name] : console
          - [property] // 메서드 or 속성이 위치
            - [type] : Identifier
            - [name] : log
         - [args]
           - [1st args : `('hi')`] // 첫번째 인자에 대한 객체
             - [type] : Literal // 5
             - [value] : 'hi'// 입력값이 표시됨
             - [raw] : 'hi'
 
ExpressionStatement : 콘솔로그의 최상위 노드CallExpression : 함수 또는 메서드를 호출하는 코드의 typeMemberExpression : 메서드 호출 시 typeIdentifier : 변수명과 같이 선언되기에 Identifier typeLiteral : 문자열이 주어졌음으로 literal typemodule.exports = function ({ types: t }) {
  return {
    visitor: {
      ExpressionStatement(path) {
        // ExpressionStatement type을 갖을때 호출
        if (t.isCallExpression(path.node.expression)) {
          if (t.isMemberExpression(path.node.expression.callee)) {
            // 노드체이닝이 넘 길어서 변수에 넣고 다시 체이닝
            const calleeNode = path.node.expression.callee;
            if (
              calleeNode.object.name === 'console' &&
              calleeNode.property.name === 'log'
            ) {
              path.remove(); // 조건에 맞으면 코드 최상위 제거! === console.log() 제거하게됨
}}}},},};};
ExpressionStatement(path) 콘솔로그 최상위 Types를 함수화 하여 작성, 매개변수를 지정해 노드에 접근하도록 한다.isCallExpression(node) : is타입명(노드)을 통해 인자로 지정한 node가 해당 type을 인지 확인!isMemberEspression(node) : 맞찬가지로 인자로 넣은 노드가 해당 type인지 확인console 객체에 log 메서드가 쓰였다면 해당 요소의 최상위 노드 제거👻
여기까지 실습하면서 AST 구조 들여다 보다보니 조금, 아주 쪼오오오오오오금 이해가 된다.
직접 만들 플러그인을 사용하기 위해서는 바벨 설정이 필요하다. 전역 설정파일(babel.confil.js)을 만들고 다음 코드를 작성하자.
// babel.config.js
// plugins 변수에 [플러그인1, 플러그인2, ... 그리고 내가만든 플러그인]
// 여러게 플러그인을 배열로 담기
const plugins = ['./plugins/consolelog-remover.js']
module.exports = { plugins }
콘솔로그가 있는 코드를 작성하고 바벨을 사용해 컴파일하여 보자~~아!
// sample-consolelog-remove.js
console.log('콘솔로그를 지워볼깨');
const text = 'run console.log() remove-plugin';
console.log(text);
npx babel 경로/파일명.js 명령 실행 후 콘솔출력
const text = 'run console.log() remove-plugin';
책보고 따라한 실습이지만, 감격....멋지당!!!
분명 잘 작성했는데 에러가나거나 한다면. 노드 체이닝에 문제가 없는지 다시한번 확인하자. 나는 if (t.isMemberExpression(path.node.expression.callee)){} 에서 인자로 넣은 노드에서 expression을 빼먹어서 한참을 다시 봤다! 노드를 잘 보기!
콘솔로그 제거를 해봤으니 콘솔로그 추가하는 플러그인을 작성해보자.
규칙 : 'on'으로 시작하는 함수에 콘솔로그를 추가
먼저 AST Explorer 사이트에 방문하여 onFunctionName() 로직을 작성해 노드를 확인해보자.

// AST 구조 확인하기 : JSON
// 너무 길어서 필요없는 옵션은 제거
{
  "type": "Program",
  "body": [
    {
      "type": "FunctionDeclaration",
      "id": {
        "type": "Identifier",
        "name": "onFunc"
      },
      "body": {
        "type": "BlockStatement",
        "body": [
          {
            "type": "VariableDeclaration", // const 변수 노드
            "kind": "const"
          },
          {
            "type": "ExpressionStatement",  // console.log 노드
            "expression": {
              "type": "CallExpression",
              "callee": {
                "type": "MemberExpression",
                "object": {
                  "type": "Identifier",
                  "name": "console"
                },
                "property": {
                  "type": "Identifier",
                  "name": "log"
           // .. 이하 닫기
          {
            "type": "ReturnStatement", // return 노드
          } 
            // .. 이하 닫기
module.exports = function ({ types: t }) {
  return {
    visitor: {
      FunctionDeclaration(path) {
        if (path.node.id.name.substr(0, 2) === 'on') {
          path
            .get('body')
            .unshiftContainer(
              'body',
              t.expressionStatement(
                t.callExpression(
                  t.memberExpression(
                    t.identifier('console'),
                    t.identifier('log')
                  ),
                  [t.stringLiteral(`call ${path.node.id.name}`)]
                )));}},},};};
function onFunc1() {
  return '일반함수 타입: FunctionDeclaration';
}
const onFunc3 = function () {
  return '익명함수 변수지정: VariableDeclaration';
};
const onFunc4 = () => {
  return '화살표함수 타입: VariableDeclaration';
};
function onFunc1() {
  console.log("call onFunc1");
  return '일반함수 타입: FunctionDeclaration';
}
const onFunc3 = function () {
  return '익명함수 변수지정: VariableDeclaration';
};
const onFunc4 = function () {
  return '화살표함수 타입: VariableDeclaration';
};
AST Explorer에서 확인해보면 알겠지만, 함수 선언 방식마다 타입종류가 다르다 변수형으로 function 함수명 방식 이외의 함수 선언방식은 변수선언 타입 VariableDeclaration 로 적용된다.
function 함수명(){} FunctionDevlaration type()=>{}, function(){} VariableDeclaration type참고자료
실전 리액트 프로그래밍/이재승 저
자바스크립트 개발자를 위한 AST(번역)
바벨-핸드북 깃헙 : 한국어버전 있음
바벨-핸드북 깃헙 : 플러그인 만들기 : 한국어버전 있음