In computing, a compiler is a computer program that translates computer code written in one programming language (the source language) into another language (the target language). - wiki
compiler는 작성된 코드의 언어를 다른 언어로 변환하는 도구입니다. 언어를 변환하는 과정을 compile이라고 합니다.
compile은 주로 사람이 이해하는 프로그래밍 언어(고수준 언어)를 컴퓨터에서 실행하기 위해선 컴퓨터가 이해할 수 있는 언어(저수준 언어)로 변환하는 과정을 칭할 때 사용됩니다. 하지만, 무조건 저수준의 언어로 바꿔야 compile로 말하는 것은 아닙니다.
The name "compiler" is primarily used for programs that translate source code from a high-level programming language to a low-level programming language (e.g. assembly language, object code, or machine code) to create an executable program.
A source-to-source translator, source-to-source compiler (S2S compiler), transcompiler, or transpiler is a type of translator that takes the source code of a program written in a programming language as its input and produces an equivalent source code in the same or a different programming language. - wiki
transpiler란 특정 프로그래밍 언어로 작성된 소스 코드를 비슷한 수준의 추상화를 가진 다른 프로그래밍 언어의 소스 코드로 변환하는 도구입니다. source-to-source compiler라고도 불리며, compiler의 일종으로 볼 수 있습니다. 다시 말해, compiler은 transpiler보다 더 포괄적인 의미를 가집니다.
예) TypeScript -> JavaScript, ES2015 -> ES2009
babel은 오래된 브라우저와의 호환을 위해 ES2015+ 코드를 이전 버전의 코드로 변환합니다.
예를 들면, ES2015의 기능 중 하나인 화살표 함수를 함수 선언문으로 변경됩니다.
// Babel Input: ES2015 arrow function
[1, 2, 3].map(n => n + 1);
// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
return n + 1;
});
비슷한 수준의 언어로 변경됐는데 transpiler라고 봐도 되지 않을까 하는 생각이 들었습니다.
stackoverflow에 "Is Babel a compiler or transpiler?" 질문이 있었는데, 답변으로 'babel은 source-to-source compiler, 일명 transpiler이다.'라고 달렸습니다.
즉, transpiler은 compiler에 포함되기 때문에, babel를 유연하게 받아들이면 compiler라고 할 수 있습니다.
현재 프로젝트는 React와 TypeScript로 구현되어 있고, webpack으로 프로젝트 환경을 설정했습니다.
이 환경에서 어떤 compiler를 선택하면 좋을지 테스트해보려고 합니다.
TSC(TypeScript compiler)은 TypeScript 코드를 JavaScript 코드로 컴파일합니다.
webpack 환경에서 TSC로 컴파일 하기 위해서 ts-loader가 필요합니다.
npm install --save-dev typescript ts-loader
설치가 완료됐다면, webpack.config.js와 tsconfig.json을 설정해야 하는데요.
webpack 공식문서을 참고하였습니다.
우선, webpack.config.js를 아래와 같이 설정해줍니다.
module.exports = {
entry: './src/index.ts',
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
그런 다음 tsconfig.json에 compileOptions를 설정해줍니다.
{
"compilerOptions": {
"target": "ES5", /* TS 코드를 어떤 ECMAScript 버전의 자바스크립트로 변환할지 결정 */
"module": "ESNext", /* 컴파일된 JS 코드가 어떤 모듈 시스템을 따를 것인지 결정 */
"jsx": "react-jsx", /* JSX 구문을 어떻게 변환할지 */
"esModuleInterop": true, /* CommonJS 모듈을 ES2015 모듈 스타일로 가져오기 위해 true로 설정 */
"allowJs": true, /* JS도 컴파일 대상에 포함하기 위해 true로 설정*/
"outDir": "./dist", /* 컴파일된 결과물이 저장될 디렉토리 */
"strict": true, /* 엄격한 타입 검사 */
"moduleResolution": "node", /* 컴파일러가 코드 내의 import 구문으로 참조된 모듈을 어떻게 찾을지 결정 */
"sourceMap": true, /* 변경된 JS 코드가 TS의 어디에 해당하는지 알려줌 => 디버깅 용이 */
},
"include": ["src/**/*", "./declaration.d.ts"], /* 컴파일할 파일 지정 */
"exclude": ["node_modules"] /* 컴파일 대상에서 제외할 파일 지정 */
}
tsconfig의 컴파일 옵션들은 굉장히 많으므로 공식문서를 보고 커스텀해보시는 걸 추천드립니다.
ts-loader는 트랜스파일과 타입 검사를 동시에 진행하기 때문에 빌드 속도가 느립니다.
이를 개선하기 위해 fork-ts-checker-webpack-plugin를 사용하면 좋습니다. 이 플러그인은 타입 검사를 별도의 프로세스에게 맡겨 빠르게 빌드할 수 있습니다.
// webpack.config.js
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = {
// ...
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
// add transpileOnly option if you use ts-loader < 9.3.0
// options: {
// transpileOnly: true
// }
}
]
},
plugins: [new ForkTsCheckerWebpackPlugin()],
};
fork-ts-checker-webpack-plugin 적용 전
fork-ts-checker-webpack-plugin 적용 후
제 프로젝트에서 적용해보니 빌드 시간이 약 1초 정도 단축되었습니다.
babel은 ECMAScript 2015+ 코드를 이전 버전의 브라우저에서 호환되는 JavaScript 코드로 변환합니다.
babel를 사용하기 위해 관련 라이브러리를 설치해줍니다.
npm i -D @babel/core @babel/preset-env @babel/preset-typescript @babel/preset-react babel-loader
그리고 아래와 같이 webpack과 babel를 설정해주시면 됩니다.
// webpack.config.js
module.exports = {
// ...
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'babel-loader',
}
]
},
};
// .babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-typescript",
"@babel/preset-react"
],
}
TSC와 다르게 babel은 type을 확인하지 않습니다.
Keep in mind that Babel doesn't do type checking; you'll still have to install and use Flow or TypeScript to check types. - babel
아래 코드처럼 타입 에러가 발생해도, build할 때 에러가 발생하지 않습니다.
const a: number = "hello"; // type 에러 발생
console.log(a);
What is TypeScript
babel 공식문서
바벨과 타입스크립트의 아름다운 결혼
타입스크립트 컴파일 설정 - tsconfig 옵션 총정리
TypeScript의 기본개념과 환경설정