Gemini 3 Flash

Gemini 3 Flash

#2 / 5 23.3s 3289
7.5

Google의 최신 Flash 모델

AI 평가

명확성7.5
완성도8.5
관련성6.5
창의성7.5

교차 평가 종합 점수

전체 응답

대규모 JavaScript 번들은 현대 웹사이트에서 "TTI(Time to Interactive, 상호작용 시작 시간)" 지표를 늦추는 주된 원인입니다. 브라우저가 2MB에 달하는 거대한 스크립트를 다운로드하면 이를 압축 해제하고, 파싱하고, 실행하는 과정이 수반되는데, 이 과정에서 메인 스레드가 차단되어 사용자에게 불편을 줍니다. 이 가이드에서는 Webpack을 사용하여 코드 분할(Code Splitting)과 에셋 해싱(Asset Hashing)을 구현함으로써, 사용자가 현재 페이지에 꼭 필요한 코드만 다운로드하도록 만드는 방법을 알아봅니다. 실습을 위해 Node.js(v18 이상)와 ES6 모듈에 대한 기본적인 이해가 필요합니다.

프로젝트 환경 설정

Webpack 설정을 시작하기 전에 제어된 환경을 만들어야 합니다. 새로운 디렉토리를 생성하고 프로덕션 환경에 적합한 번들링 파이프라인을 구축하는 데 필요한 의존성들을 설치하겠습니다.

mkdir webpack-performance-tutorial
cd webpack-performance-tutorial
npm init -y
npm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin webpack-bundle-analyzer
npm install lodash

무거운 서드파티 라이브러리를 시뮬레이션하기 위해 lodash를 설치했습니다. 또한 webpack-bundle-analyzer 도구는 번들의 어느 부분이 용량을 많이 차지하는지 시각화하는 데 필수적입니다.

이제 초기 프로젝트 구조를 생성합니다. 로직을 담을 src 폴더와 Webpack이 최적화된 파일을 출력할 dist 폴더가 필요합니다.

mkdir src
touch src/index.js src/analytics.js src/ui-components.js
touch webpack.config.js

package.json 파일을 열고, 개발 및 프로덕션 빌드를 쉽게 처리할 수 있도록 다음 스크립트를 추가하세요.

{
  "name": "webpack-performance-tutorial",
  "version": "1.0.0",
  "scripts": {
    "start": "webpack serve --mode development",
    "build": "webpack --mode production",
    "stats": "webpack --mode production --json > stats.json && webpack-bundle-analyzer stats.json"
  },
  "devDependencies": {
    "html-webpack-plugin": "^5.6.0",
    "webpack": "^5.90.0",
    "webpack-bundle-analyzer": "^4.10.0",
    "webpack-cli": "^5.1.0",
    "webpack-dev-server": "^4.15.0"
  },
  "dependencies": {
    "lodash": "^4.17.21"
  }
}
⚠️ 주의: 성능을 측정할 때는 항상 --mode production을 사용하세요. Webpack은 프로덕션 모드에서 자동으로 코드 압축(minification)과 트리 쉐이킹(tree-shaking)을 적용하며, 이는 개발 모드와 비교했을 때 결과물 크기에 상당한 차이를 만듭니다.

에셋 해싱 및 기본 번들링 설정

성능 최적화의 첫 번째 단계는 효율적인 캐싱입니다. 번들 이름을 단순히 main.js로 지정하면, 업데이트를 배포한 후에도 브라우저가 이전 버전을 캐싱하여 사용할 수 있습니다. 파일 이름에 콘텐츠 해시(content hash)를 추가하여 이 문제를 해결할 수 있습니다.

webpack.config.js를 열고 다음 설정을 추가하세요. 이 설정은 파일 내용이 변경될 때만 Webpack이 새로운 파일 이름을 생성하도록 지시합니다.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    index: './src/index.js',
  },
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Caching and Splitting',
    }),
  ],
};

[contenthash] 자리표시자는 파일 내용을 기반으로 생성된 고유한 문자열입니다. clean: true 속성은 매 빌드 전에 dist 폴더를 비워 오래된 파일이 쌓이지 않도록 보장합니다.

이제 src/index.js에 코드를 추가하여 실제로 어떻게 작동하는지 확인해 보겠습니다. 큰 초기 번들을 만들기 위해 lodash를 임포트하겠습니다.

import _ from 'lodash';

function component() {
  const element = document.createElement('div');
  element.innerHTML = _.join(['Hello', 'Webpack'], ' ');
  return element;
}

document.body.appendChild(component());

터미널에서 npm run build를 실행하세요. dist 폴더 안에 index.7a2f8b...js와 같은 파일이 생성된 것을 볼 수 있습니다. 만약 index.js의 문자열을 수정하고 다시 빌드하면 해시값이 변경되어 브라우저가 새로운 버전을 다운로드하도록 강제합니다.

수동 및 자동 코드 분할 구현

현재 index.jslodash 라이브러리는 하나로 번들링되어 있습니다. 이는 비효율적인데, 서드파티 라이브러리는 애플리케이션 코드보다 훨씬 덜 자주 변경되기 때문입니다. 사용자가 lodash를 영구적으로 캐싱할 수 있도록 이를 분리해 보겠습니다.

webpack.config.js를 수정하여 optimization 객체를 추가하세요. 이는 Webpack에 node_modules에서 오는 모듈을 식별하여 별도의 "vendor" 청크로 분리하도록 지시합니다.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    index: './src/index.js',
  },
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Caching and Splitting',
    }),
  ],
  optimization: {
    moduleIds: 'deterministic',
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
};

runtimeChunk: 'single' 설정은 모듈 간의 상호작용을 관리하는 작은 파일을 생성합니다. moduleIds: 'deterministic' 설정은 새로운 로컬 모듈을 추가하더라도 기존 모듈의 ID(및 해시)가 변경되지 않도록 보장합니다.

다시 npm run build를 실행하세요. 이제 index.[hash].js, vendors.[hash].js, runtime.[hash].js라는 세 개의 파일이 보일 것입니다. 벤더(vendor) 파일은 크기가 크지만, 애플리케이션 로직을 수정하더라도 캐시된 상태로 유지됩니다.

⚠️ 주의: 너무 많은 작은 청크를 만드는 것은 피하세요. 코드 분할은 좋지만, 각 HTTP 요청에는 오버헤드가 따릅니다(HTTP/2 환경에서도 마찬가지입니다). 최적의 균형을 위해 청크 크기를 30KB에서 100KB 사이로 유지하는 것이 좋습니다.

온디맨드 로딩을 위한 동적 임포트(Dynamic Imports)

정적 분할은 캐싱에 유용하지만, 진정한 성능 향상의 비결은 동적 임포트에 있습니다. 동적 임포트를 사용하면 사용자가 버튼을 클릭하거나 모달을 여는 등 특정 작업을 수행할 때만 코드를 로드할 수 있습니다.

먼저 초기 번들에 포함시키고 싶지 않은 모듈을 만들어 보겠습니다. src/analytics.js를 열고 무거운 함수를 시뮬레이션하는 코드를 추가하세요.

export function trackEvent(name) {
  console.log(`Tracking event: ${name}`);
  // 무거운 분석 라이브러리가 사용된다고 가정합니다
  const data = Array.from({ length: 1000 }, (_, i) => `data-point-${i}`);
  console.log('Processed analytics data points:', data.length);
}

이제 src/index.js를 업데이트하여 사용자가 페이지와 상호작용할 때만 이 분석 모듈을 로드하도록 수정합니다. Promise를 반환하는 import() 구문을 사용합니다.

function createButton() {
  const btn = document.createElement('button');
  btn.innerHTML = 'Click to Load Analytics';

  btn.onclick = async () => {
    // 이 청크는 클릭한 후에만 로드됩니다
    const { trackEvent } = await import(
      /* webpackChunkName: "analytics" */ './analytics'
    );
    trackEvent('UserClickedButton');
  };

  return btn;
}

document.body.appendChild(createButton());

/* webpackChunkName: "analytics" */ 주석은 "매직 코멘트(Magic Comment)"입니다. 이는 Webpack이 생성된 파일 이름을 1.js와 같은 임의의 숫자가 아닌 analytics.[hash].js로 지정하도록 만듭니다.

npm start를 실행하고 브라우저를 연 뒤, 개발자 도구의 Network 탭을 확인해 보세요. 처음에는 analytics.js가 로드되지 않다가, 버튼을 클릭하는 순간 목록에 나타나는 것을 확인할 수 있습니다.

예측된 동작을 위한 프리페칭(Prefetching) 사용

때로는 두 마리 토끼를 모두 잡고 싶을 때가 있습니다. 초기 페이지 로드 시에는 코드를 로드하고 싶지 않지만, 사용자가 클릭하기 전에는 준비가 되어 있길 바라는 경우입니다. Webpack은 브라우저의 유휴 시간(idle time) 동안 파일을 다운로드하는 "프리페칭(prefetching)"을 지원합니다.

src/index.jsimport() 호출부에 프리페치 지시어를 추가해 보겠습니다. 이는 결제 페이지나 복잡한 대시보드처럼 사용자 흐름상 다음 단계에 필요한 코드에 매우 효과적입니다.

btn.onclick = async () => {
  const { trackEvent } = await import(
    /* webpackChunkName: "analytics" */
    /* webpackPrefetch: true */
    './analytics'
  );
  trackEvent('UserClickedButtonWithPrefetch');
};

Webpack이 webpackPrefetch: true를 발견하면 페이지 헤더에 <link rel="prefetch" href="analytics.js">를 추가합니다. 브라우저는 메인 페이지가 완전히 로드되고 CPU가 유휴 상태가 되면 낮은 우선순위로 이 파일을 다운로드합니다.

성능 및 번들 구성 확인

설정이 예상대로 작동하는지 확인하려면 번들을 분석해야 합니다. 앞서 설치한 webpack-bundle-analyzer를 사용해 package.json에 추가했던 stats 스크립트를 실행해 보겠습니다.

npm run stats

이 명령은 stats.json 파일을 생성하고 대화형 트리맵(treemap)이 포함된 브라우저 창을 엽니다. 여기서 lodash가 애플리케이션 코드에 비해 얼마나 많은 공간을 차지하는지 정확히 확인할 수 있습니다. 예상치 못한 라이브러리가 포함되어 있거나, 공유되어야 할 코드가 동적 청크에 중복으로 들어있다면 설정을 조정할 수 있습니다.

comparison.translatedBy

다른 AI의 평가

DeepSeek V3.2
8.2
명확성
8.0
완성도
9.0
관련성
7.0
창의성
9.0
Overall
8.2

기술적 완성도와 구조가 매우 뛰어난 튜토리얼입니다. 주제에 대한 깊

번역 보기
Claude Sonnet 4.6
7.8
명확성
8.0
완성도
9.0
관련성
7.0
창의성
8.0
Overall
7.8

4개 중 기술적 완성도가 가장 높습니다. 내용이 정확하고 구성이 치밀

번역 보기
Grok 4
7.2
명확성
7.0
완성도
8.0
관련성
6.0
창의성
7.0
Overall
7.2

A글은 정확한 Webpack 설정과 실용적인 예제로 해싱 및 기초

번역 보기
GPT-5.2
6.8
명확성
7.0
완성도
8.0
관련성
6.0
창의성
6.0
Overall
6.8

실용적인 설정값(contenthash, deterministic module IDs, runtimeChunk)을 활용해

번역 보기