ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 프론트엔드 빌드, 번들러
    FE 2025. 9. 22. 22:49

    🔍 빌드

    빌드란 개발자가 작성한 소스코드를 브라우저가 실행가능한 형태로 변환하고 여러 파일을 하나 또는 소수의 파일로 묶어 최적화하는 과정입니다.

     

    🤔 빌드가 왜 필요할까

     

    1️⃣ 브라우저 호환성 문제 해결

    브라우저마다 지원하는 자바스크립트 문법이 다릅니다.

     

    const, async/await, Promise 같은 최신 문법(ES6+)은 구형 브라우저에서 동작하지 않기 때문에 실행 가능한 문법으로 변환을 해주어야 합니다.

    • 트랜스파일링(Transpiling) 을 통해 최신 코드를 구버전 문법으로 변환해줍니다.

     

    2️⃣ 모듈 번들링 (Module Bundling)

    의존성이 있는 여러개의 파일들을 하나의 파일로 합쳐주는 역할

     

    우리가 작성하는 코드는 보통 여러 개의 파일(모듈)로 나뉩니다.

    • 브라우저는 기본적으로 ES Module을 지원하지만 구형 브라우저에서는 지원하지 않음
    • 초기 페이지를 로딩하기 위해서 여러 HTTP 요청이 필요

     

    index.js
    utils.js
    components/
    ├── header.js
    ├── footer.js
    └── sidebar.js

     

    💡 해결책

    • 여러 개의 JS, CSS, 이미지 파일을 하나(혹은 몇 개)로 묶어 브라우저에 전달
    • 네트워크 요청 수 감소 → 성능 향상

     

    3️⃣ 성능 최적화

    빌드 과정에서 다양한 성능 최적화 기법을 적용

     

    코드 압축 공백, 주석, 불필요한 문자를 제거 변수명을 짧게 변경
    난독화 코드 가독성을 낮춰 보안 강화 변수명, 함수명을 의미없는 문자로 변경
    tree shaking 사용하지 않는 코드를 제거하여 번들 크기 최적화  
    code splitting 필요한 코드만 분리하여 초기 로딩 속도 향상  
    캐싱 최적화 파일명에 해시값 추가로 브라우저 캐싱 활용 변경되지 않은 파일은 캐시 사용

     

    4️⃣ 개발 편의성

    빌드 도구는 개발자의 생산성을 높여주는 다양한 기능을 제공

    • Hot Module Replacement (HMR): 코드 수정 시 페이지 전체 리로드 없이 즉시 반영
    • 자동화된 테스트와 코드 린팅
    • 개발 서버 제공
    • 에러 추적(소스맵 제공)
    • 자동 리로드: 파일 변경 감지 시 자동으로 브라우저 새로고침

     

    ☁️ 기능

    ↪️ Transpiling

    https://www.youtube.com/watch?v=D-fqNyTV3b8

     

     

    작성된 소스코드를 브라우저가 해석할 수 있는 형태(언어)로 변환

     

    예시: ES6+ → ES5

    *// Before (ES6+)*
    const greet = (name) => {
      console.log(`Hello, ${name}`);
    };
    
    *// After (ES5 - 구형 브라우저 호환)*
    "use strict";
    var greet = function greet(name) {
      console.log("Hello, " + name);
    };

     

    예시: TypeScript → JavaScript

    *// Before (TypeScript)*
    interface User {
      name: string;
      age: number;
    }
    
    const user: User = { name: "John", age: 25 };
    
    *// After (JavaScript)*
    const user = { name: "John", age: 25 };

     

    🫔 Bundling

    • 모듈들을 하나(혹은 여러 개)로 묶는 과정
    • Tree shaking과 함께 작동하여 사용되지 않는 코드 제거

     

    모듈들을 하나(혹은 여러 개)로 묶는 과정
    📁 src/
    ├── index.js
    ├── utils.js
    ├── api/
    │   ├── auth.js
    │   └── user.js
    └── components/
        ├── Header.js
        └── Footer.js
    
    ↓ 번들링 후
    
    📁 dist/
    ├── bundle.js
    ├── modules.js
    └── styles.css

     

    🚐 코드 압축(minify)

    • 공백, 주석, 불필요한 문자를 제거
    function calculateTotal(number1, number2) {
      const result = number1 + (number1 * number2);
      return result;
    }
    
    // After
    function a(b,c){return b+b*c}

     

    🤯 Obfuscation (난독화)

    • 보안을 위해 코드를 읽기 어렵게 변환
    // Before
    function getUserInfo(userId) {
      const apiUrl = '<https://api.example.com>';
      return fetch(`${apiUrl}/users/${userId}`);
    }
    
    // After (난독화)
    function _0x1a2b(a){const b="<https://api.example.com>";return fetch(b+"/users/"+a)}

     

    🌱 Tree shaking

    사용되지 않는 코드 제거로 빌드 크기 최적화

    • ES Module(ESM)의 import/export 기반에서만 제대로 작동 (정적 분석)
    • CommonJS(require/module.exports)에서는 동적 분석의 한계로 완전한 Tree Shaking이 어려움

     

    // utils.js
    export function used() {
      console.log("I'm used!");
    }
    export function unused() {
      console.log("I'm never used...");
    }
    
    // index.js
    import { used } from './utils.js';
    used();
    
    // 최종 번들에는 used() 함수만 포함

     

    🧩 환경 설정

    개발(Development)과 배포(Production) 모드에서 다른 설정 적용

     

    🧑‍💻 개발 모드 (Development)

    • HMR 활성화
    • 상세한 에러 메시지
    • Source Map 생성 (디버깅 용이)
    • 압축하지 않은 코드 (가독성 우선)
    • 빠른 빌드 시간

     

    🖥️ 배포 모드 (Production)

    • 코드 압축 및 난독화
    • Tree Shaking 적용
    • 최적화된 번들 크기
    • 해시값을 포함한 파일명 (캐싱)
    • 에러 리포팅 도구 연동 (Sentry)

     

    *// webpack.config.js 예시*
    module.exports = (env, argv) => {
      const isProduction = argv.mode === 'production';
    
      return {
        mode: isProduction ? 'production' : 'development',
        devtool: isProduction ? false : 'eval-source-map',
        optimization: {
          minimize: isProduction,
          splitChunks: isProduction ? {...} : false
        }
      };
    };
    
    // vite.config.js 예시
    import { defineConfig } from 'vite';
    
    export default viteConfig(({ command, mode }) => {
      const isProduction = mode === 'production';
      return {
        base: './',
        build: {
          minify: isProduction, // 프로덕션 모드일 때만 압축
          sourcemap: !isProduction, // 개발 모드에서만 소스맵
          rollupOptions: {
            //...
          },
        },
        server: {
          open: true, // 개발 서버 실행 시 브라우저 자동 열기
        },
      };
    });

     

    📖 HMR (Hot Module Replacement)

    개발 중 특정 코드 변경 시 페이지 새로고침 없이 해당 부분만 리로드

     

    👍 장점

    • 애플리케이션 상태 유지
    • 빠른 개발 피드백
    • 개발 생산성 향상

     

    🏄‍♂️ 동작 과정

    1. 파일 변경 감지
    2. 변경된 모듈만 다시 컴파일
    3. 브라우저에 변경사항 전송
    4. 런타임에서 모듈 교체

     

    📌 Code Splitting

    코드를 여러 개의 청크(chunk)로 나눠 필요할 때만 로드

     

    📍 예시 - React.lazy

    import React, { Suspense } from "react";
    
    const LazyComponent = React.lazy(() => import("./MyComponent"));
    
    function App() {
      return (
        <div>
          <Suspense fallback={<div>로딩 중...</div>}>
            <LazyComponent />
          </Suspense>
        </div>
      );
    }
    • React.lazy()로 컴포넌트를 필요할 때 로딩하도록 하고 Suspense를 함께 사용하여 로딩 중일 때 보여줄 UI를 설정

     

    📍 동적 Import

    // 버튼 클릭 시에만 test 모듈 로드
    button.addEventListener("click", async () => {
      const { Test } = await import("./test-module");
      const test = new Test();
      test.render();
    });
    
    // 라우트별 코드 분할
    const routes = {
      '/dashboard': () => import('./pages/Dashboard'),
      '/profile': () => import('./pages/Profile'),
      '/settings': () => import('./pages/Settings')
    };

     

    🔧 빌드 도구

    현재 가장 널리 사용되는 빌드 도구로는 Webpack, Rollup, Vite 등이 있습니다.

     

    1️⃣ Webpack

    https://webpack.kr/

     

    가장 널리 사용되는 자바스크립트 모듈 번들러중 하나입니다.

    (JavaScript, CSS, 이미지 등)을 모듈로 관리할 수 있고 이를 하나의 파일로 번들링하는 기능을 제공합니다.

    • 강력한 로더와 플러그인 시스템을 통해 다양한 파일 형식과의 호환성을 제공하기 때문입니다.

     

    하지만 Webpack의 설정이 복잡하고 초기 구성이 어려울 수 있다는 단점이 있습니다.

    • 또한, 프로젝트의 규모가 커질수록 빌드 시간이 길어질 수 있습니다.
    • Webpack은 모든 모듈을 분석하고 의존성을 파악하는 과정에서 시간이 소요되기 때문입니다.

     

    그럼에도 Webpack은 강력한 기능과 넓은 사용자 기반을 가지고 있어 많은 프로젝트에서 선호되고 있습니다.

     

    2️⃣ Rollup

    Rollup은 ES6 모듈을 중심으로 설계된 모듈 번들러입니다. Webpack과 비교했을 때 Rollup은 더 작은 번들 사이즈를 생성하는 것으로 알려져 있습니다.

    • Rollup은 트리 쉐이킹(tree-shaking) 기능을 통해 사용되지 않는 코드를 제거하기 때문입니다.

     

    Rollup은 라이브러리와 프레임워크 개발에 적합한 도구로 평가받고 있습니다.

    • Rollup이 ES6 모듈의 장점을 최대한 활용하기 때문

     

    하지만 Rollup은 Webpack만큼 다양한 파일 형식과의 호환성을 제공하지 않아 생태계가 상대적으로 작다는 단점이 있습니다.

    • 주로 자바스크립트 모듈에 초점을 맞추고 있기 때문입니다.

     

    3️⃣ Vite

    Vite(프랑스어로 "빠르다(Quick)"를 의미하며 발음은 "veet"와 비슷한 /vit/

    • 바이트라고 읽는 줄 알았는데 아니였다..!

     

    Vite는 최신 프론트엔드 개발 도구로, 빠른 빌드 속도와 즉각적인 모듈 업데이트를 제공합니다.

     

    Vite는 ES 모듈을 기반으로 동작해 개발 중에는 서버 사이드에서 모듈을 직접 제공합니다.

    • Vite는 브라우저가 ES 모듈을 직접 해석할 수 있도록 하여 전통적인 번들링 과정을 생략하기 때문입니다.

     

    이로 인해 개발 환경에서의 빌드 속도가 매우 빨라져 변경 사항이 즉시 반영됩니다.

    또한, Vite는 설정이 간단하고 사용하기 쉽다는 장점이 있습니다.

     

    🧑🏻‍💻 실제로 빌드 도구 사용해보기

    • typescript와 vite를 이용

     

    1️⃣ 빌드 도구 세팅

    npm create vite@latest my-project
    cd my-project
    npm install
    • 템플릿 선택 시 vanilla-ts 선택

     

    2️⃣ 개발 환경 실행

    {
      "scripts": {
        "dev": "vite",       // 개발 서버 실행
        "build": "vite build", // 배포용 빌드
        "preview": "vite preview" // 빌드 결과 프리뷰
      }
    }
    npm run dev
    • Vite의 개발 서버가 실행되고 HMR 자동 지원

     

    3️⃣ 빌드 실행

    npm run build
    • dist/ 폴더 생성
    • 코드 압축 및 최적화 확인 가능

     

    'FE' 카테고리의 다른 글

    History API 와 클라이언트 라우팅  (1) 2025.09.08
    DocumentFragment으로 DOM 조작하기  (0) 2025.09.08
    프론트엔드 아키텍처 구조 - MVC, MVVM  (0) 2025.09.02

    댓글

Designed by Tistory.