All Articles

바벨(babel)

바벨에 관한 이것저것 모음

바벨은 컴파일러이다. 자바스크립트를 입력받아 자바스크립트를 출력한다. 예를 들면, es6코드를 받아서 브라우저에서 돌아갈 수 있는 es5코드로 바꿔주는 것이다.

나의 프로젝트중 package.json에서 웹팩, 바벨 관련 dependency만 추려보았다.

  "devDependencies": {
    "@babel/core": "^7.5.5",
    "@babel/preset-env": "^7.5.5",
    "babel-loader": "^8.0.6",
    "css-loader": "^3.1.0",
    "file-loader": "^4.1.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.8.0",
    "node-sass": "^4.12.0",
    "sass-loader": "^7.1.0",
    "webpack": "^4.38.0",
    "webpack-cli": "^3.3.6",
    "webpack-dev-server": "^3.7.2"
  }

babel-loader

프로젝트에 es6이상의 문법을 사용하고 싶다면, 바벨 설정이 필요하다. 바벨의 컴파일을 거쳐 build 되도록 해야하는데 여러가지 방법이 있다. 그 중 나는 웹팩의 babel-loader로 바벨을 실행시킨다.

webpack.config.js 의 module.roules의 설정에 아래와 같이 추가한다. node_modules 폴더 빼고 모든 js 파일에 babel 컴파일을 거치도록 한다.

{
    test: /\.js$/,
    exclude: /node_modules/,
    use: ['babel-loader']
},

환경 설정

일단 스크립트에 개발 환경을 설정하기 위해 package.json의 scripts 부분 수정. NODE_ENV 키로 값을 줄 수 있다.

"scripts": {
    "start": "webpack-dev-server",
    "build": "rm -rf dist && NODE_ENV=production webpack"
},

웹팩에서 현재 모드는 process.env.NODE_ENV 로 확인할 수 있다.

const mode = process.env.NODE_ENV;
// 예를 들어 위와 같이 값을 가져와서 사용

바벨에서는 env 속성을 이용하면 환경별로 다른 설정을 줄 수 있다.

// babel.config.js
{
    "env": {
        "production": {
            "presets": ["minify"]
        }
    }
}

바벨과 폴리필

자바스크립트의 최신 기능을 모두 사용하면서 오래된 브라우저를 지원하려면 바벨로 코드 문법도 변환해야하고, 폴리필을 직접 사용해야 하는 것도 있다. 폴리필은 런타임에 기능을 주입한다. 바벨을 사용한다고 해서 js 모든 최신기능을 사용할 수 있는 것은 아니므로 폴리필 설정은 별도로 해야한다.

참고록 async await는 폴리필로 추가할 수 없으며, 컴파일 타임에 코드 변환을 해야한다.

@babel/polyfill

해당 모듈을 import하거나 webpack에 설정할 경우, 모든 폴리필이 포함되어 필요하지 않은 것도 가져오므로 번들 파일의 크기가 커진다.

core-js

@babel/polyfill 패키지는 내부적으로 core-js 패키지를 이용한다. 이 중에서 필요한 폴리필만 가져오면 번들 파일의 크기를 줄일 수 있다.

@babel/preset-env

실행 환경에 대한 정보를 설정하면 자동으로 필요한 기능을 주입해준다.

// babel.config.js
const presets = [
    [
        '@babel/preset-env`,
        {
            targets: '> 0.25%, not dead',
            useBuiltIns: 'usage'
        }
    ]
];

위는 시장 점유율이 0.25% 이상이고 업데이트가 종료되지 않은 브라우저를 의미한다. 브라우저 정보는 browserlist라는 패키지의 문법을 사용하므로, 해당 사이트에 가면 어떤 브라우저인지 잘 나와있다. useBuiltIns: 'usage'는 각 js파일에서 실제 사용한것만 polyfill로 가져온다는 의미이다. 이 설정이 없으면 시장 점유율이 0.25% 이상인 브라우저를 위한 모든 polyfill이 추가된다.

바벨 설정 관련

  • extends: 다른 설정 파일을 가져와서 확장할 수 있다.
  • env, overrides: 환경별 또는 파일별로 다른 설정을 적용할 수 있다.

7.2 바벨 플러그인 제작하기

7.2.1 AST 구조

바벨은 문자열로 입력되는 코드를 AST(abstract syntax tree)라는 구조체로 만들어서 처리한다. 플러그인에서는 AST를 기반으로 코드를 변경한다.

바벨 컴파일 단계

  • 파싱(parse): 입력된 코드로부터 AST(abstract syntax tree) 생성
  • 변환(transform): AST를 원하는 형태로 변환
  • 생성(generate): AST를 코드로 출력

AST는 코드의 구문(syntax)이 분석된 결과를 담고 있는 구조체다. 코드가 같다면 AST도 같기 때문에 같은 코드에 대해서 하나의 AST를 만들어 놓고 재사용할 수 있다.

astexplorer 사이트에서 AST 구조를 확인할 수 있다. 이렇게 구조가 만들어진다니.. 처음 봤다!

책에서 나온대로 const v1 = a + b; 한 줄 파싱해봤을 뿐인데 우측에 엄청 긴 AST 가 생성되었다.

이러한 AST 구조를 파악해야만 바벨 플러그인을 만들 수 있다. 해당 구조를 원하는 형태로 변환하여 다시 코드로 배출하기 때문이다. 멘토라면 이런것쯤은 껌으로 알아야할까? 상당히 어색하다. 바벨 플러그인은 내년에나 만들어봐야겠다.

reference

실전리액트프로그래밍