본문 바로가기
TYPESCRIPT

웹팩(Webpack) 사용하기

by 일태찡 2023. 4. 7.

웹팩(Webpack)이란 무엇이며 왜 필요한가

 

 

다음과 같이 지금까지 진행했던 프로젝트 네트워크 탭을 확인하면 폭포 형태의 차트를 볼 수 있습니다.

이는 HTTP 요청을 설정하는 데 걸리는 셋업 시간을 나타낸 것입니다.

 

보시다시피 파일이 매우 작더라도 모든 HTTP 요청을 위한 여분의 셋업으로 인해 시간이 다소 소요되는 것입니다.

모든 HTTP 요청에는 베이스 오버헤드(base overhead), 지속(duration)이 발생합니다.

 

지금은 모든 것들이 로컬 개발 서버 환경에서 이루어지고 있기 때문에 설정이 매우 빠르게 진행됩니다.

하지만 웹에서 실행하는 경우 이렇게 다수의 요청이 있다면 HTTP 요청의 양만으로 인해 다량의 대기시간이 발생하고 프로젝트가 느려질 수 있습니다.

 

그렇기 때문에 브라우저 지원에 관계없이 요청 수가 작아지는 것이 좋습니다.

그걸 위해서는 웹팩이 필요하고 이는 파일을 묶는(bundle)것을 도와주는 도구입니다.

정확히는 묶고(bundling) 빌드하고(building), 종합하는(orchestration) 도구입니다.

또한 웹팩은 코드를 최적화하고 빌드 절차를 추가하고, 추가 빌드 툴을 제공합니다. (ex. css 파일 지원)

 

 

웹팩 설치하기 & 중요 종속성

 

npm install --save-dev webpack webpack-cli webpack-dev-server typescript ts-loader

 

터미널에서 위와 같이 설치하면 다음과 같이 추가된 사항을 확인할 수 있습니다.

 

package.json

{

  ... 
  
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "lite-server",
    "build": "webpack" // 5
  },
  
  ...

  "devDependencies": {
    "lite-server": "^2.5.4",
    "ts-loader": "^9.4.2", // 4
    "typescript": "^5.0.3",
    "webpack": "^5.78.0", // 1
    "webpack-cli": "^5.0.1", // 2
    "webpack-dev-server": "^4.13.2" // 3
  }
}

 

  1. 우리 코드를 묶고 변환하기 위한 특정 기능을 플러그인 하도록 해줍니다.
  2. 프로젝트에서 웹팩 명령어를 실행하기 위해 필요합니다.
  3. 개발 서버 내에서 빌트 하기 위해서 필요합니다. 파일의 변경사항을 점검하고, 변경이 생겼을 때 웹페이지의 컴파일을 다시 시작합니다.
  4. 웹팩에게 어떻게 코드를 자바스크립트로 변환할 것인지를 전달합니다.
  5. 스크립트 섹션에 원하는 이름을 입력해 간단하게 웹팩을 실행할 수 있습니다.

 

입력 & 출력 구성 추가하기

 

tsconfig.json

{
  "compilerOptions": {
    /* Basic Options */
    "target": "es6", // 1                      /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "es2015", // 2                 /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": [
      "dom",
      "es6",
      "dom.iterable",
      "scripthost"
    ],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    "sourceMap": true, // 5                 /* Generates corresponding '.map' file. */
    //"outFile": "./dist/bundle.js",                       /* Concatenate and emit output to single file. */
    "outDir": "./dist", // 3                    /* Redirect output structure to the directory. */
    // "rootDir": "./src", // 4                /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
    "noEmitOnError": true,

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": false,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    "noUnusedLocals": true,                /* Report errors on unused locals. */
    "noUnusedParameters": true,            /* Report errors on unused parameters. */
    "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    ,"experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
  },
  "exclude": [
    "node_modules" // would be the default
  ]
}

 

  1. 타입스크립트 로더의 웹팩이 이 타겟을 사용합니다. es5나 es6로 설정되어야 합니다.
  2. 모듈은 es2015나 es6로 설정되어야 합니다.
  3. 출력(output)을 검증해야 합니다. 코드를 컴파일할 경로를 결정하는 것입니다.
  4. 루트 경로가 필요하지 않습니다. 웹팩이 이어받을 것이고 웹팩이 루트 파일 위치를 결정할 것이기 때문입니다.
  5. 코드의 디버그를 지원하며 , 웹팩도 이를 지원합니다.

 

프로젝트 시작 지점(entry point)에서 가장 먼저 파일이 실행되고 웹팩이 이 파일 내의 임포트를 파악하고 그다음에는 그 파일들로 가서 임포트를 파악합니다. 임포트 된 파일의 임포트들을 살펴보는 방식입니다. 프로젝트의 모든 파일을 파악할 때까지 진행됩니다. 그다음으로는 파일 내용(contents)을 파악합니다. 그리고 ts-loader 패키지의 도움을 받아서 그것들을 컴파일합니다.

 

// import { ProjectInput } from "./components/project-input.js";
import { ProjectInput } from "./components/project-input";

 

웹팩이 자동적으로 .js 및 기타 확장자 파일을 찾기 때문에 .js 확장자를 모든 파일에서 빼줍니다. 이렇게 하지 않으면 웹팩이 이중 확장자를 검색하게 됩니다.

 

웹팩이 자동적으로 인식해서 우리 프로젝트를 어떻게 동작할지 전달해 주는 역할을 하기 때문에 다음과 같이 이름을 맞춰야 합니다.

 

webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/app.ts', // 1
    output: {
        filename: 'bundle.js', // 2
        path: path.resolve(__dirname, 'dist') // 3
    },
    devtool: 'inline-source-map', // 9
    module: { // 4
        rules: [
            {
                test: /\.ts$/, // 5
                use: 'ts-loader', // 6
                exclude: /node_modules/ // 7
            }
        ]
    },
    resolve: {
        extensions: ['.ts', '.js'] // 8
    }
};

 

웹팩이 채택할 구성 오브젝트(configuration object)가 될 자바스크립트 오브젝트를 엑스포트 하기 위한 노드 js 구문을 사용합니다.

 

  1. 엑스포트 된 오브젝트에 루트 entry 파일을 설정합니다.
  2. 마지막에 생성되는 단일 자바스크립트 파일이 될 것입니다.
  3. 출력이 쓰여지는 경로를 명시해야 합니다. 에러를 방지하기 위해 tsconfig.json에 있는 outDir 경로와 맞추어야 합니다. 절대 경로를 빌드하기 위해 resolve 방법을 이용하고 특수 상수(__dirname)를 사용합니다. dist 폴더로의 절대 경로를 구축을 의미합니다.
  4. 웹팩이 파일들을 어떻게 다룰지에 대한 설정입니다.
  5. 웹팩에게 .ts로 끝나는 모든 파일이 이 규칙에 따라 사용되고 처리되어야 한다고 정규 표현식으로 전달합니다.
  6. 웹팩이 사용하는 로더를 명시합니다.
  7. 웹팩이 노드 모듈을 찾지 않을 것입니다.
  8. 임포트에 추가할 파일 확장자를 웹팩에 전달합니다.
  9. 생성한 묶음(bundle)을 추출하고 정확하게 접속해야 하는 생성된 소스 맵이 이미 존재한다는 것을 웹팩에게 전달합니다.

 

터미널에 npm run build를 입력합니다.

 

 

dist 폴더 내에 다음과 같이 번들링 된 자바스크립트 파일을 볼 수 있습니다.

 

 

이렇게 셋업 하는 자바스크립트 파일을 줄여 개선이 이루어집니다.

 

 

코드를 최적화했지만 소스맵(source map) 덕분에 여기서 모든 코드를 확인하고 디버그 할 수 있습니다.

 

 

웹팩 공식 문서 ▼

https://webpack.kr/

 

webpack

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

 

 

 

 

'TYPESCRIPT' 카테고리의 다른 글

리액트와 타입스크립트  (6) 2023.04.11
장소 선택 및 공유 구글 API 연습  (5) 2023.04.10
모듈과 네임스페이스  (6) 2023.04.06
연습 프로젝트 4  (6) 2023.04.04
연습 프로젝트 3  (6) 2023.04.03