levi

리바이's Tech Blog

Tech BlogPortfolioBoard
AllActivitiesJavascriptTypeScriptNetworkNext.jsReactWoowacourseAlgorithm
COPYRIGHT ⓒ eunwoo-levi
eunwoo1341@gmail.com

📚 목차

    [React] Webpack에서 ts-loader 대신 babel를 선택한 이유

    ByEunwoo
    2025년 7월 12일
    react

    최근 프로젝트에서 Webpack을 사용하여 React + TypeScript 환경을 설정하는 과정에서 ts-loader 대신 babel-loader를 선택했다.

    원래 Webpack에서 TypeScript를 사용하려면 ts-loader를 사용하는 것이 일반적이다. 하지만 최근에 ts-loader대신 babel를 사용해서 Typescript를 컴파일하는 것이 더 효율적인 것을 알게됐다.
    이 글에서 ts-loader 대신 babel-loader를 사용한 이유와 그 장점을 살펴보자.

    TypeScript는 JavaScript에 타입 시스템을 추가한 언어이다. 하지만 브라우저는 TypeScript를 직접 실행할 수 없기 때문에, TypeScript 코드는 반드시 JavaScript로 변환(컴파일)해야 한다.

    Webpack은 기본적으로 .js와 .json만 이해할 수 있다.
    그래서 .ts나 .scss, .png 같은 파일을 처리하려면 loader라는 도구가 필요하다. loader가 webpack에게 통역사 역할을 해주는 것이다.
    ts-loader라는 loader가 TypeScript (.ts)파일을 Webpack이 이해할 수 있는 JavaScript로 변환해준다.

    babel 이란?

    바벨은 최신 JavaScript 코드를 이전 버전의 JavaScript로 변환해 주는 도구이다. 예를 들어, ES6+ 문법을 ES5로 변환해서 오래된 브라우저에서도 동작하게 만들어준다.

    // 변환 전 (ES6+)
    const sum = (a, b) => a + b;
     
    // 변환 후 (ES5)
    var sum = function(a, b) {
      return a + b;
    };

    바벨은 코드를 다음과 같이 바꿔준다.

    • 화살표 함수 → function 키워드를 사용하는 일반 함수
    • 클래스 문법 → 프로토타입 기반 생성자 함수
    • 템플릿 리터럴 → 문자열을 + 기호로 이어 붙여 연결
    • 구조 분해 할당 → 하나씩 값을 꺼내는 일반 변수 할당
    • JSX 문법 → React.createElement() 함수 호출 코드

    React에서는 JSX를 일반 JavaScript로 변환하는 데 바벨이 필수적이다.

    ts-loader 대신 babel-loader를 선택한 이유

    React + TypeScript 프로젝트를 Webpack으로 설정할 때 가장 먼저 고민하는 것 중 하나는 TypeScript 파일을 어떻게 변환할 것인가이다.

    1. 빌드 속도 최적화

    ts-loader는 TypeScript의 전체 타입 검사 과정을 거치며 컴파일을 수행한다. 따라서 규모가 커질수록 타입 체크 + 트랜스파일로 인해 빌드 속도가 느려질 수 있다.

    반면 babel-loader는 타입 검사를 하지 않고 코드만 빠르게 JavaScript로 변환한다. 타입 검사는 별도로 tsc나 fork-ts-checker-webpack-plugin을 통해 처리하면 되기 때문에, 트랜스파일과 타입 체크를 병렬화하여 속도를 개선할 수 있다.

    2. React와의 강력한 호환성

    React 17 이상부터는 JSX를 자동으로 변환하는 automatic runtime 기능이 도입됐다. Babel은 이와 같은 최신 기능을 빠르게 반영하며, @babel/preset-react를 통해 JSX 변환을 효율적으로 수행할 수 있다.
    따라서 React의 최신 문법, 실험적 기능을 빠르게 적용하려면 Babel 환경이 더 적합하다.

    3. 다양한 Babel 플러그인 생태계

    Babel은 방대한 플러그인 생태계를 가지고 있다. 예를 들어 아래와 같은 기능들을 플러그인으로 손쉽게 추가할 수 있다:

    • async/await 트랜스파일
    • class properties, decorators 등 실험적 문법
    • styled-components 최적화
    • polyfill 자동 주입

    이런 기능을 Webpack 빌드 단계에서 유연하게 커스터마이징하고 싶다면 Babel 기반 설정이 더 적합하다.

    babel을 사용하여 설정 방법

    먼저, babel-loader와 필요한 패키지를 설치한다:

    npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/preset-typescript
    • @babel/core: JavaScript 코드를 변환해 주는 도구
    • babel-loader: Webpack에서 바벨을 사용할 수 있도록 연결해 주는 역할.
    • @babel/preset-react: 바벨에게 JSX를 어떻게 변환할지 알려주는 설정.
    • @babel/preset-typescript: 바벨에게 타입스크립트를 어떻게 변환할지 알려주는 설정.
    • @babel/preset-env: 최신 JavaScript 문법을 구버전 브라우저에서도 작동하게 변환해준다. React를 해석하는데 필수는 아니지만, 최신 JavaScript 문법을 쓸 계획이 있다면 넣는 걸 추천한다.

    Webpack에 바벨 로더 설정 추가하기

    webpack.config.js 파일의 entry, module.rules, resolve를 다음과 같이 수정하자.

    module.exports = {
      // ... 기존 설정 유지
      entry: './main.tsx', // 웹팩이 읽기 시작할 파일을 .tsx로 변경
      module: {
        rules: [
          {
            test: /\.(ts|tsx)$/, // .ts와 .tsx 파일을 대상으로
            use: [
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    '@babel/preset-env', // 최신 JS 문법을 변환
                    '@babel/preset-react', // JSX를 변환
                    '@babel/preset-typescript' // 타입스크립트를 변환
                  ]
                }
              }
            ],
            exclude: /node_modules/
          }
        ]
      },
      resolve: {
        extensions: ['.tsx', '.ts', '.js'] // .tsx 확장자도 처리할 수 있게 한다
      }
    };

    modules.rules와 resolve은 언제 수정해야 할까?

    • module.rules: "이런 파일도 웹팩이 이해했으면 좋겠는데?" 싶을 때

      • .scss, .tsx 같은 새로운 파일을 추가했는데 웹팩이 못 읽을 때
      • 로더를 새로 추가할 때 (예: 이미지, 폰트, SVG 등 처리용)
    • resolve: import, require문을 썼을 때 어떤 파일을 가리키는지 알려주고 싶을 때

      • import A from './A.tsx' → import A from './A'처럼 확장자를 생략하고 싶을 때
      • src/components/... 이런 긴 경로를 @components/...처럼 짧게 쓰고 싶을 때
      • 모듈을 찾는 기준 경로를 바꾸고 싶을 때 (node_modules 말고 src도 보게 만들기 등)

    fork-ts-checker-webpack-plugin

    타입 검사를 별도로 처리하기 위해 fork-ts-checker-webpack-plugin을 사용할 수 있다.

    fork-ts-checker-webpack-plugin을 사용하는 가장 큰 장점은 타입 검사(Type Checking)와 Linting을 Webpack 번들링과 병렬로 수행할 수 있다는 것이다. 이를 통해 빌드 속도를 크게 향상시킬 수 있다.

    정리해보면

    • Webpack과 타입 체크를 병렬 처리

      • 기본적으로 ts-loader는 **타입 검사 + 트랜스파일(코드 변환)**을 동시에 처리
      • 하지만 이 경우 빌드 속도가 느려질 수 있다.
      • babel-loader는 타입 검사를 생략하고 빠르게 트랜스파일만 수행
      • 이때 fork-ts-checker-webpack-plugin을 사용하면, 타입 체크는 별도의 프로세스에서 병렬로 수행되므로 Webpack 빌드 속도는 빨라지고, 타입 안전성도 유지
    • 빠른 핫 리로딩 (HMR) 유지

      • Webpack 개발 서버에서는 빠른 HMR(Hot Module Replacement)이 중요한데,
      • 타입 체크 때문에 매번 전체 빌드를 기다리면 개발 생산성이 떨어진다.
      • 이 플러그인은 타입 검사를 백그라운드에서 하므로 빠른 HMR을 유지할 수 있다.

    HMR이란 코드 변경 시 전체 페이지를 새로고침하지 않고, 변경된 부분만 업데이트하는 기능이다. 이를 통해 개발 중에 빠르게 결과를 확인할 수 있다.

    fork-ts-checker-webpack-plugin 설정

    먼저, fork-ts-checker-webpack-plugin을 설치한다.

    npm install --save-dev fork-ts-checker-webpack-plugin

    그 다음, webpack.config.js에 플러그인을 추가한다.

    import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
     
    module.exports = {
      // ... 기존 설정 유지
     
      plugins: [new ForkTsCheckerWebpackPlugin()],
    };

    이제 Webpack 빌드 시 타입 검사를 별도의 프로세스에서 병렬로 수행하게 된다.

    결론

    ts-loader는 TypeScript의 변환과 타입 검사를 동시에 수행하는 반면, babel-loader는 빠른 트랜스파일에 집중하여 빌드 속도를 개선할 수 있다.

    이번 프로젝트에서는 생산성, 유연성, React 최신 기능 지원 측면에서 babel-loader를 선택했다. 타입 검사는 별도의 도구로 수행하면서 빌드와 검증을 분리하니, 결과적으로 더 빠르고 유연한 개발 환경을 구축할 수 있었다.

    Posted inreact
    Written byEunwoo