본문 바로가기
Front-end/Webpack

7. webpack에 대한 이해(사용목적, 기본개념)

by devraphy 2021. 6. 25.

- Vue 프로젝트 클론코딩을 완료한 이후, Vue와 webpack에 대한 기본적인 개념적 이해가 궁금했다. 

- 그러므로 본 포스팅에서 webpack을 왜 사용하는지와 webpack의 기본구조에 대한 이야기를 해보려고 한다. 

 

1. webpack을 사용하는 이유 

프론트 개발의 영역이 넓어지면서 JavaScript를 이용한 다양한 기술적 풀이가 생겨났다. 

하나의 웹 페이지에 연결된 JS파일이 많아지면서 관리에 있어 한계가 발생했고, 

웹사이트의 로딩속도가 길어지고 그만큼 더 많은 요청이 발생하여 네트워크 비용이 증가했다.

더불어, JS파일이 많아지면서 서로의 scope를 침범하여 변수간의 충돌을 일으킬 위험성이 증가했다.

 

이를 해결하기 위해, JS의 즉시호출함수(IIFE) 기능을 이용한 CommonJS, AMD, UMD와 같은 기술이 등장하였고 JS파일을 하나의 module로 관리하는 방안이 마련되었으나, JS파일의 수 만큼의 module을 관리하는 것 또한 쉽지 않았다. 또한 당시 모든 브라우저에서 module 시스템을 지원하지 않았다. 

 

이와 같은 이유로, module을 IIFE 형태로 변경해주고 여러 module을 하나의 파일로 만들어주는 bundler를 통해 네트워크 비용을 최소화 할 수 있는 개발과정이 필요했다.

 

이에 대한 해결책을 제공하는 기술이 webpack bundler다. 

 

a) 즉시호출함수(IIFE)란?

https://jeonghwan-kim.github.io/series/2019/12/10/frontend-dev-env-webpack-basic.html

 

- JS에서 함수 scope를 사용하여 외부에서 함부로 함수에 접근하지 못하도록 하는 것을 말한다. 

- 여기서 함수 scope란, 일종의 접근지정자 / 접근제어자를 의미한다. 

 

b) CommonJS(CJS)란?

// 아래와 같이 require을 통해 package/lib 모듈을 변수에 담을 수 있습니다.
var lib = require('package/lib');

// 가져온 모듈을 아래와 같이 사용할 수 있습니다.
function foo () {
  lib.log('hello world!');
}

// foo 함수를 다른 파일에서 사용할 수 있도록, 다른 모듈로 추출될 수 있습니다.
exports.foobar = foo;

- CJS는 require 키워드를 통해 재사용할 module을 가져온다. 

- exports 키워드를 이용하여 모듈화하여 다른 파일에서도 사용할 수 있도록 새로운 모듈로 추출한다. 

 

var foo = require('foo');
var bar = require('bar');

foo.log('It is foo');
bar.log('It is bar');

- CJS는 동기적으로 작동하는 코드이므로 서버 쪽에서 사용이 용이하다. 

- Node.js가 CJS 방식을 채택하여 사용하고 있다.  

 

c) AMD란(Asynchronous Module Definition)?

- 웹 또는 브라우저 환경에서는 모든 코드가 동기적으로 작동하는 것은 치명적인 단점이 된다. 

- 왜냐면 로딩이 완료될 때까지 사용자가 아무것도 할 수 없기 때문이다.

- 그러므로 AMD는 비동기적 환경에서 모듈을 사용하기위한 방법이다.

- 대표적으로 RequireJS가 있다. 

// 종속성을 갖는 모듈인 'package/lib'를 모듈 선언부의 첫 번째 파라미터에 넣으면,
// 'package/lib'은 콜백 함수의 lib 파라미터 안에 담깁니다.
define(['package/lib'], function (lib) {

  // 로드된 종속 모듈을 아래와 같이 사용할 수 있습니다.
  function foo () {
    lib.log('hello world!');
  }

  // 생성된 foo 함수는 리턴을 통해 foobar라는 이름의 다른 모듈로 추출될 수 있습니다.
  return {
    foobar: foo
  };
});

- define 키워드를 통해 재사용할 module을 가져온다.

- 이후 return 키워드를 통해 가져온 module을 새로운 module로 추출한다. 

 

require(['package/myModule'], function (myModule) {
  myModule.foobar();
});

- 새롭게 생성된 module을 require 키워드로 가져와 매개변수(myModule)에 할당하여 사용할 수 있다. 

 

d) UMD(Universal Module Definition)란?

- AMD와 CJS 방식이 서로 호환되지 않아 발생하는 문제를 해결하기 위해 나온 해결책이다.

- 특정한 키워드나 규칙이 있다기 보다는 AMD와 CJS를 함께 사용하는 방식으로 디자인 패턴에 더 가까운 개념이다. 

https://beomy.github.io/tech/javascript/cjs-amd-umd-esm/#umd-universal-module-definition

 


2. webpack의 4요소 (webpack.config 를 작성하는 이유)

a) Entry

- webpack은 모든 것을 module로 인지한다. JS, stylesheet, 이미지파일 등 모든 것을 JS 모듈로 로딩하여 사용한다. 

- JS가 로딩하는 모듈이 많을수록 모듈간의 의존성은 증가한다. 그래서 여러 모듈을 bundle이라는 하나의 파일 형태로 묶는다. 

- 여러 module의 관계(의존성)를 파악하여 하나로 묶기 위해서는 기준점/시작점이 필요하다. 

- 그 시작/기준점이 되는 것이 Entry다. 

 

module.exports = {
  entry: {
    main: "./src/main.js",
  },
}

또는 

module.exports = {
  entry: "./src/main.js"
}

- 위의 코드는 webpack.config.js에 작성되는 부분이다. 

- Entry가 되는 파일을 webpack에게 알려주기 위해서는 위의 코드와 같이 webpack.config.js 파일을 작성한다.

- Entry 경로가 src/main.js가 되는 이유는 index.html에서 사용하는 모든 자바스크립트의 시작점이 src/main.js 이기 때문이다.

 

b) Output

- Output은 Webpack을 통해 만들어진 결과물이 반환될 경로를 지정하는 부분이다. 

module.exports = {
  output: {
    filename: "bundle.js",
    path: "./dist",
  },
}

- Webpack이 Entry에 지정된 파일을 기준으로 관계가 형성된(의존성) 파일(module)들을 찾는다.

- 선택된 여러 module을 하나로 묶어 bundle을 만든다.

- Webpack의 bundling 과정을 통해 만들어진 결과물(bundle)을 output에 지정된 경로와 이름으로 반환한다.

- 프로젝트의 터미널에서 npm run build 명령을 실행하면 결과물이 해당 경로에 해당 이름으로 반환된다. 

 

module.exports = {
  output: {
    // path: path.resolve(__dirname, 'dist'), 
    // ==> 결과물의 반환지점을 설정 
    
    // filename: 'main.js',
    // ==> 결과물의 이름을 지정
    
    // 기본적으로 webpack의 output 경로는 dist로 기본설정되어 있다.
    // 그러므로 default로 지정된 경로로 결과물을 반환한다면, 따로 작성할 필요는 없다. 
    // npm run build를 프로젝트의 터미널에 입력하면 dist 폴더와 내부파일(결과물)이 생성된다.
    
    clean: true 
    // 덮어쓰기 기능 속성
    // 빌드를 여러번 하게되면 dist폴더가 여러번 생성된다. 이때마다 덮어쓰기를 하기 위한 속성이다.
  },
}

- 위의 코드 주석에 작성한 것 처럼, webpack의 output 경로는 dist로, 이름은 main.js로 기본 설정되어 있다.

- 그렇기에 따로 작성하지 않아도 default 값으로 dist 폴더에 결과값이 생성될 것이다. 

- 추가적으로 clean 속성은 덮어쓰기 기능이다.

- 여러번 빌드 명령을 실행했을 때, dist 폴더가 계속해서 생성되는 것을 방지하기 위해 사용한다.  

 

c) Loader

- Webpack은 모든 파일을 모듈로 관리한다. 

- 모듈에는 여러 종류의 파일이 존재하지만, Webpack은 자바스크립트 하나만 이해한다. 

- 그러므로 자바스크립트가 아닌 언어로 구성된 파일을 Webpack이 이해할 수 있도록 하는 기능이 Loader다.

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: "node_modules",
        use: {
          loader: "babel-loader",
          options: {
            presets: ["env"],
          },
        },
      },
    ],
  },
}

- 위의 예시코드는 Babel-loader 라는 패키지를 Webpack과 연동시키는 설정이다. 

- test 속성 값에는 정규표현식을 이용하여 파일 확장자 명을 지정한다.

- exclude 속성은 test에 작성된 확장자를 갖고 있어도 제외될 폴더명을 지정한다. 더불어, 정규표현식으로 작성할 수 있다.

- use 속성에는 test 속성에 지정된 확장자를 Webpack이 이해할 수 있도록 변환할 패키지/라이브러리를 지정한다. 

- 이 외에도 다양한 속성과 option이 있으니 찾아보기를 권장한다. 

 

d) Plugin

- Loader가 파일 단위로 해석하고 자바 스크립트로 변환하는 과정이라면, 

- Plugin은 묶여진 결과물(bundle)을 처리한다.

  // 번들링 후 결과물의 처리방식 등 다양한 플러그인 사용을 위한 구성요소 추가 
  plugins: [ 
    new HtmlPlugin({ // 생성자를 이용한 플러그인 생성 
      template: './index.html' // 템플릿 연결 
    }),
    new CopyPlugin ({
      patterns: [
        { from: 'static' } // static 폴더 안의 내용이 dist로 복사되어 들어가도록 한다. 
      ]
    }),
    new VueLoaderPlugin(), // vue로더를 연결시키기 위한 플러그인 
    new Dotenv() // .env를 연결시키기 위한 플러그인 
  ]

 

 

e) 참고자료

https://velog.io/@mnz/Webpack-%EC%9B%B9%ED%8C%A9-%EA%B0%9C%EB%85%90-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

 

[Webpack] 웹팩 개념 알아보기

웹팩이란 무엇인지, 어떠한 장점이 있는지 전반적인 개념에 대해 알아보고 웹팩 구성 요소 중 로더에 대해 상세하게 정리해봤습니다 🤔

velog.io

 

https://jeonghwan-kim.github.io/js/2017/05/15/webpack.html

 

웹팩의 기본 개념

자바스크립트 코드가 많아지면 하나의 파일로 관리하는데 한계가 있다. 그렇다고 여러개 파일을 브라우져에서 로딩하는 것은 그만큼 네트웍 비용을 치뤄야하는 단점이 있다. 뿐만 아니라 각 파

jeonghwan-kim.github.io

 

https://beomy.github.io/tech/javascript/cjs-amd-umd-esm/#cjs-commonjs

 

[JavaScript] CJS, AMD, UMD, ESM

처음 자바스크립트는 모듈을 가져오거나 내보내는 방법이 없어, 하나의 파일에 모든 기능들이 들어가야 했습니다. CJS, AMD, UMD, ESM이 등장 후에는 모듈로 개발하고 배포할 수 있게 되었습니다. 이

beomy.github.io

  

https://jeonghwan-kim.github.io/series/2019/12/10/frontend-dev-env-webpack-basic.html

 

프론트엔드 개발환경의 이해: 웹팩(기본)

1. 배경 먼저 모듈에 대해 이야기 해보자. 문법 수준에서 모듈을 지원하기 시작한 것은 ES2015부터다. import/export 구문이 없었던 모듈 이전 상황을 살펴보는 것이 웹팩 등장 배경을 설명하는데 수월

jeonghwan-kim.github.io

 

https://medium.com/javascript-training/beginner-s-guide-to-webpack-b1f1a3638460

 

Beginner’s guide to Webpack

As a beginner to Webpack, this is what I have learned.

medium.com

 

https://www.valentinog.com/blog/webpack/

 

A mostly complete guide to webpack 5 (2020)

A mostly complete guide to webpack's capabilities, always to keep close at hand.

www.valentinog.com

 

댓글