본문으로 바로가기

프론트엔드 개발환경의 이해 : Webpack (2)

category Frontend 2021. 3. 14. 16:24

지난 포스팅에서 모든 브라우저에서 모듈을 지원하는게 아니라고 했고 그렇기 때문에 웹팩이 필요하다고 했다

그렇다면 웹팩이 하는 일은 무엇일까?

웹팩

출처 : https://webpack.js.org/

웹팩이란?

모듈로 개발을 하게되면 app.js가 math.js를 불러와서 사용하듯 하나의 자바스크립트가 다른 모듈을 임포트해서 사용한다

이런 관계를 의존 관계에 있다고 얘기를 하는데

웹팩은 이런 모듈로 연결되어 의존 관계에 있는 파일들을 하나로 합쳐준다

이때 하나로 합친 파일을 번들이라고 하고

하나로 합쳐주는 작업을 하는 웹팩을 번들러라고 한다

웹팩 설정

웹팩을 실행할 때에는 알아야할 주요 옵션이 4가지, 필수 옵션 1가지가 존재한다

  1. mode
  2. entry
  3. output
  4. loader
  5. plugin

mode

mode는 프로젝트가 개발 환경인지, 운영 환경인지를 결정하는 옵션이다

entry

모듈의 시작점을 entry라고 한다

모듈이란 의존 관계에 있는 모든 파일들을 하나로 묶어주는 번들러라고 했다

파일들을 하나로 묶을 때 시작점(entry)을 웹팩에게 알려주는 설정 그래야 시작점에서 부터 의존 관계를 읽어갈 수 있기 때문

기본값은 .src/index.js

output

엔트리를 시작점으로 의존 관계에 있는 자바스크립트를 묶은 파일을 번들이라고 했다

번들을 생성했으면 그 번들을 어딘가에 저장해야하는데 그때 필요한 옵션이 바로 output이다

output 옵션은 번들의 이름과 저장 경로를 설정한다

기본값은 .dist/main.js

설정해보기

여기까지만 보고 감을 잡기 위해 웹팩을 설정을 해보자

const path = require('path');

module.exports = {
    mode: "development", // 개발 환경 설정
    entry: { // 엔트리 파일 설정
        main : './src/app.js',
    },
    output: {
        path: path.resolve('./dist'), // output 경로 설정
        filename: "[name].js" // 파일명 설정
    }
}

entry를 설정할 때 key와 value로 설정하는 이유는 엔트리가 여러 가지일 때를 대비해서 객체로 묶었고

output의 filename이 []로 묶여있는 것은 엔트리가 여러 가지일 때 동적으로 파일명을 생성하기 위함이다

const path = require('path');

module.exports = {
    mode: "development", // 개발 환경 설정
    entry: { // 엔트리 파일 설정
        main : './src/app.js',
          main2 : './src/app2.js',
    },
    output: {
        path: path.resolve('./dist'), // output 경로 설정
        filename: "[name].js" // 파일명 설정
    }
}

같이 설정되었다면

main.jsmain2.js 파일들이 각각 생성된다

package.json 파일에 스크립트를 수정해서 npm으로 웹팩으로 번들링을 할 수 있게 수정해보자

{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10"
  }
}

build : 'webpack'만 추가해 주면 npm이 node_module안에 있는 webpack을 찾고 webpack은 webpack.confing.js을 찾아서 설정에 따라 번들링을 실행한다

이제 npm run build를 실행해주면 정상적으로 번들링이 되고 dist 폴더에 main.js라는 파일이 생성된다

html에서 자바스크립트를 로드해오는 부분을 아래처럼 바꿔주면 끝.

<script src="dist/main.js"></script>

로더

웹팩은 모든 파일을 모듈로 바라본다 여태까지 하나로 묶은 파일은 js형태 밖에 없었지만

css, 이미지, 폰트 전부 다 모듈로 생각하고 번들링을 하는데 묶여서 나온 파일은 js인데.. 어떻게 js가 아닌 다른 형태의 파일들을 js하나로 묶을 수 있는 걸까?

바로 웹팩의 로더 덕분이다 이 로더가 모든 파일을 자바스크립트 내부에서 사용가능하게끔 만들어 준다

로더 만들어보기

로더의 동작원리를 이해하기 위해서 간단한 로더를 만들어 보자

// my-webpack-loader
module.exports = function myWebpackLoader(content){
    console.log('myWebpackLoader가 동작');
    return content;
}

로더는 이러한 함수 형태로 작성하고 우리의 로더는 동작했을 때 로그를 찍고 파일내용을 그대로 반환하는 일을 한다

이제 webpack.config.js에 가서 만든 로더를 설정해주자

const path = require('path');

module.exports = {
    mode: "development",
    entry: {
        main : './src/app.js',
    },
    output: {
        path: path.resolve('./dist'),
        filename: "[name].js"
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: [
                    path.resolve('./my-webpack-loader.js')
                ]
            }
        ]
    }
}

로더는 module 객체의 rules라는 배열에 추가해줄 수 있다

rules는 또 test와 use키를 갖는데 여기서

test는 정규표현식을 가지며 표현식을 만족하는 모든 파일을 대상으로

use의 경로에 설정된 로더에 집어 넣는다

플러그인

로더가 번들링과정에서 파일들 하나하나에 간섭하는 역할이었다면 플러그인은 약간 반대라고 할 수 있다

번들링이 끝난 후 번들 파일에 간섭하는 것이 플러그인의 역할이다

플러그인 만들어보기

로더처럼 플러그인을 만들어보면서 동작 원리를 이해해보자

이전과는 다르게 클래스로 만든다

class MyWebpackPlugin {
    apply(compiler) {
        compiler.plugin('emit', (compilation, callback)=>{
            const source = compilation.assets['main.js'].source();

            compilation.assets['main.js'].source = () => {
                const footer = `
            /**
            * MyWebpackPlugin의 결과물
            * Build Date: 2021-04-01
            **/
            `

            return  source +'\n\n' + footer;
            }
            callback();

        })
    }
}

module.exports = MyWebpackPlugin

플러그인을 만들면 웹팩에서 compiler를 주입해주고 컴파일러를 통해 compilation.assets['파일명'].source()로 번들된 파일의 코드를 얻을 수 있다

source함수가 실행되는 것을 이용해서 source 함수를 바꿔치기해서 번들 파일 하단에 글을 남기는 플러그인을 만들었다

'Frontend' 카테고리의 다른 글

주요 플러그인  (0) 2021.03.18
주요 로더와 순서  (0) 2021.03.16
프론트엔드 개발환경의 이해 : Webpack  (0) 2021.03.10
프론트엔드 개발환경의 이해 : NPM  (0) 2021.03.09
MVC 패턴  (0) 2021.03.06