그동안 프로젝트를 진행할 때 제가 환경 설정을 주도한 적이 없었습니다.

프로젝트 환경 설정은 기본적으로 갖춰야 할 능력이기에 바닐라 자바스크립트로 진행하는 프로젝트를 위한 환경 설정을 직접 해보고자 합니다.

Babel, Webpack, ESLint, Prettier, EditorConfig를 통해 프로젝트 환경 설정을 할 예정입니다.

이번 포스트에서는 Babel, Webpack을 적용시키는 것까지 다루고 다음 포스트에서 ESLint, Prettier, EditorConfig를 적용시키는 내용을 다루겠습니다.

학습을 하며 작성된 글이기 때문에 틀린 부분이 존재할 수 있습니다. 그럴 경우 정정해주시면 감사드립니다 😄

다음 포스트 : ESLint, Prettier, EditorConfig 적용하기

프로젝트 초기화

프로젝트 환경 설정을 위해 package.json을 생성해줍니다.

npm init -y

그 후 간단하게 폴더 구조를 잡아줍니다. 저는 다음과 같은 폴더 구조를 가져가기로 했습니다.

project init

Babel

Babel이란?

Babel 공식 홈페이지에서는 Babel is a JavaScript compiler 라고 소개하고 있습니다.

맞습니다. Babel은 ECMAScript 2015 이상 버전을 지원하지 않는 브라우저를 위해 상위 버전 코드를 각 브라우저에 호환이 되게 바꾸어주는 JavaScript compiler입니다.

새롭게 도입된 기술을 사용하고 싶지만 브라우저에서 지원하지 않아서 사용할 수 없는 경우 Babel을 통해 해결할 수 있습니다.

설치 및 적용

Babel 공식 홈페이지를 참고하여 진행하였습니다.

필요한 패키지들을 설치해줍니다.

npm install --save-dev @babel/core @babel/cli @babel/preset-env

  • core : 변환에 필요한 API들이 모여있는 패키지입니다.

  • cli : Babel은 command line에서 파일을 컴파일 할 수 있게 해주는 내장 CLI를 제공하는데 이를 사용할 수 있게 해줍니다.

  • preset-env : Target을 설정하여 해당하는 브라우저 환경에 대한 syntax transform과 polyfill을 제공해줍니다. Target에 대해서만 동작을 수행하기 때문에 bundle의 크기를 줄여줍니다.

설치가 완료 됐으면 config 파일을 생성해줘야 합니다.

babel.config.json 파일을 생성해주고 다음과 같이 설정을 해줍니다.

{
  "presets": [
    [
      "@babel/env",
      {
        "targets": {
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        },
        "useBuiltIns": "usage",
        "corejs": "3.6.5"
      }
    ]
  ]
}

project state

만약 Babel 7.8.0 이전 버전을 사용한다면 babel.config.js 파일을 통해 설정을 해주어야 합니다. => 참고

babel.config.json vs babelrc.json

babel.config.json은 전체 설정 파일이라고 생각하면 된다.
프로젝트 전체에 babel 설정이 적용된다.

babelrc.json은 프로젝트의 특정 부분에 적용시키고자 할 때 사용된다.

Babel에서는 babel.config.json을 추천하고 있다.

Webpack

모듈 번들러인 Webpack을 사용할 것입니다.

webpack.config.js를 통해 여러 설정을 할 수 있는데 핵심이라고 생각되는 속성 몇 가지만 짚고 넘어가겠습니다.

  • entry : 번들링을 시작할 파일을 지정합니다.
  • output : 번들링 된 결과물과 관련된 내용을 설정합니다. 일반적으로 결과물은 dist 폴더에 생성합니다.
  • loader : Webpack이 불러 올 수 없는 정적 파일들을 불러 올 수 있게 도와줍니다. 기본적으로 번들링이 되기 전 각각의 파일 단계에서 적용됩니다.
  • plugin : loader보다 더 많은 기능을 제공합니다. 번들 단계와 Chunk 단계에서 동작하며 주로 번들링이 끝난 후에 동작하는 경우가 많습니다. 쉽게 말하면 번들링 된 결과물에 대해 특정 작업을 처리하기 위해 사용됩니다.

Webpack이란?

공식 문서에 따르면 Webpack은 modern JavaScript 애플리케이션을 위한 정적 모듈 번들러입니다. Webpack은 entry point를 기준으로 의존성을 찾아 여러 개의 파일을 하나의 번들로 만들어줍니다. 여러 파일을 불러오기 위해서는 네트워크 통신에 필요한 비용이 늘어나는데 Webpack을 사용하면 이러한 문제를 해소시킬 수 있습니다.

설치 및 적용

웹팩 설정을 위해 설치할 패키지들은 다음과 같습니다. 기본 요소

  • webpack
  • webpack-cli loader
  • babel-loader
  • css-loader
  • style-loader
  • html-loader plugin
  • html-webpack-plugin 개발 편의
  • webpack-dev-server

기본 요소, loader는 패키지 명으로 추론이 가능하실 거라 생각하여 html-webpack-plugin과 webpack-dev-server에 대해서만 설명을 조금 덧붙이겠습니다.

  • html-webpack-plugin : 다른 경로에 있는 html 파일을 복제하여 dist 폴더에 추가해줍니다.
  • webpack-dev-server : 실시간으로 reloading이 가능한 웹 서버를 제공해줍니다.

명령어를 통해 설치를 해줍니다.

npm i -D webpack webpack-cli babel-loader css-loader style-loader html-loader html-webpack-plugin webpack-dev-server

그 후 webpack.config.js 파일을 생성한 후 다음과 같이 작성해줍니다.

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

간단한 테스트를 위해 src 폴더에 2개의 JavaScript 파일을 만들겠습니다.

// src/add.js

const add = (a, b) => {
    return a+b;
}

export default add;
// src/index.js

import add from './add';

function component() {
    const element = document.createElement('div');
 

    element.innerHTML = add(1,1);
 
    return element;
}
 
document.body.appendChild(component());

webpack을 실행해보기 위해 package.json에 명령어를 추가하겠습니다.

script add

그 후 npm run start명령어를 실행해보면 dist 폴더가 생성되고 내부에 bundle.js 파일이 만들어진 것을 확인할 수 있습니다.

bundle result

번들링 된 파일이 잘 동작하는지 확인하고 싶으시다면 Html 파일을 만들어 테스트해보셔도 됩니다. 저는 다음 단계에서 HtmlWebpackPlugin을 활용하여 생성해 줄 예정이기 때문에 이 단계는 건너 뛰겠습니다.

Webpack 추가 옵션 설정

개발 서버

우선 개발시 편의를 위해 Webpack Dev Server 옵션을 추가하려고 합니다.

webpack.config.js를 다음과 같이 수정해주세요.

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer: {
    contentBase: './dist'
  },
};

그 후 package.json의 script를 조금 수정하겠습니다.

script add

npm run start 명령어를 실행하면 번들링이 되면서 개발 서버가 실행되는 것을 확인할 수 있습니다.

아직 Html 파일이 없기 때문에 아무 것도 보이지 않는 모습입니다.

dev server

Html 생성 하기

dist 폴더 내부에 Html 파일을 생성해도 괜찮지만 개인적으로 Html 파일을 public 폴더에 위치 시키고 싶어서 Plugin을 사용할 예정입니다.

HtmlWebpackPlugin을 활용하여 번들링 할 때 마다 dist 폴더에 Html 파일을 복제할 것입니다.

우선 public 폴더에 index.html을 생성하겠습니다.

// public/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Jinhyukoo JJang</title>
  </head>
  <body>
  </body>
</html>

webpack.config.js를 다음과 같이 수정합니다.

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

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer: {
    contentBase: './dist'
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, './public/index.html')
    })
  ],
};

filename은 생성 될 파일 이름이며 template은 root 기준 어느 경로에 위치한 html 파일을 복제할 지를 설정해주는 옵션입니다.

자세한 옵션은 여기를 참조해주세요.

그 후 npm run start를 실행해보면 화면에 2가 출력되는 것을 확인할 수 있습니다.

loader 설정하기

3가지 loader를 적용할 예정입니다.

  • html-loader : Html을 string으로 export해주며 최적화 시킬 수 있다.
  • css-loader : CSS를 읽어오기 위한 loader이다.
  • style-loader : CSS를 DOM에 주입시킨다.
  • babel-loader : webpack과 babel을 통해 JavaScript 파일을 transpiling 시킨다.

webpack.config.js 파일에 module 옵션을 추가하여 다음과 같이 수정합니다.

...

module.exports = {
  
  ...

  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      },
      {
        test: /\.html$/i,
        use: {
          loader: 'html-loader',
          options: {
            minimize: true
          }
        }
      },
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
};

alias 설정

alias 설정을 해보겠습니다. 프로젝트 규모가 커지면 상대 경로를 사용하여 파일을 import 해오기가 까다롭습니다. alias는 말 그대로 별칭을 설정하여 절대 경로로 파일을 import 해올 수 있게 해줍니다.

webpack.config.js 파일에 resolve 옵션을 추가하여 다음과 같이 수정해줍니다.

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

module.exports = {
  entry: './src/index.js',
  resolve: {
    extensions: ['.js'],
    alias: {
      '@': path.resolve(__dirname, 'src/'),
      '@public': path.resolve(__dirname, 'public/')
    }
  },
  
  ...

};

index.js 파일로 가서 add를 Import 하는 부분을 수정한 후 다시 실행해봅시다.

import add from './add' => import add from '@/add';

잘 동작하는 것을 확인할 수 있습니다.

mode 설정

마지막으로 mode를 설정하는 것으로 웹팩 설정을 마무리 짓겠습니다.

mode는 크게 2가지로 나눌 수 있는데 development와 production으로 나눌 수 있습니다. Webpack은 개발할 때와 배포할 때 각각의 상황에 맞게 번들링을 진행합니다.

webpack.config.js와 package.json의 script를 수정해줘야 합니다.

webpack.config.js에 인자와 mode 옵션을 추가해줍시다.

...

module.exports = (env) => ({
  mode: env.production ? 'production' : 'development',
  
  ...

})

package.json의 명령어는 다음과 같이 수정해줍니다.

script add

CLI에서 실행되는 명령어에 –env를 통해 값을 전달해주면 해당 모드에 따라 다른 방식으로 번들링을 진행합니다.

이렇게 해서 Webpack, Babel 설정을 끝냈습니다. 다음 포스트에서는 ESLint, Prettier, EditorConfig 설정을 해보도록 하겠습니다.

다음 포스트 : ESLint, Prettier, EditorConfig 적용하기

참고 자료