[2021.09.02] Webpack & Babel

이다은·2021년 9월 10일
0
post-thumbnail

📌 module

✨ 웹팩은 모듈 번들러다!
모듈에 대해 알아보자!

💡 모듈 정의

자바스크립트에서의 모듈이란 기능 단위의 "자바스크립트 개별 파일"다.

  • 프로그램을 구성하는 단위
  • 자신만의 독립적인 실행 영역
  • 보통 파일 단위로 나뉨

💡 모듈패턴과 필요성

  • 자바스크립트의 소스를 모듈 단위로 관리하거나 라이브러리 등을 만들 때 사용
  • 전역 변수의 사용을 최소화 하기 위함
  • 변수 scope을 지정해서 사용하기 위함
  • Reusablility, Isolation, Organization
  • 모듈 단위로 개발하면, 각 모듈 간의 의존성을 최소화하거나, 의존성 파악이 쉬움.

💡 라이브러리(CRA) 없이 모듈 패턴 구현할 때는 어떻게 했나?

// 이렇게 감싸서 하나의 모듈을 만들 수 있었다.
(function () {
  // scope가 막혀있기 때문에 전역변수가 생성되지 않는다.
  // 즉시 실행함수는 보통 일회용 코드
})();

// 모듈 또 하나
(function () {
	window.myLibrary = /* */;
}());

// 모듈 또 하나
(function () {
	var math = {
		add: function () {}
	}

	window.math = math;
}());

💡 모듈 시스템 라이브러리(모듈 기능 표준화)

✅ CommonJS

  • 실행구문 : module.export, require
  • Node.js에서 사용

✅ ES6 Module

자바스크립트를 이용하는 웹페이지의 코드가 복잡해지기 시작하면서,
효율적인 소스 관리가 필요해져서 이제는 모듈을 정의하는 것 또한 표준으로 정의되었다.

  • 실행구문 : export, import
  • CRA에서 사용

❗ 아직 IE지원이 안되므로, 모듈을 사용하려면 babel, webpack이 필요하다.
babel은 ES6 → 브라우저에서 사용할 수 있도록 모듈을 commonjs로 바꿔주고,
webpack은 모듈간의 의존성을 파악하여 자바스크립트 코드를 bundle(합쳐) 해준다.


📌 webpack

✨ 웹팩은 모듈 번들러다!
➡ 모듈을 알아봤으니 번들러에 대해 알아보자!

💡 번들러(bundler)

  • 번들이란, 여러 파일 여러 구성을 합치는 것을 말한다.
  • 모듈화된 파일들을 하나로 묶어 관리해야하기 때문에, 번들러의 역할이 중요해졌다.
  • 모듈 간의 의존성을 파악하여 하나의 파일로 만들어 준다.
  • npm run build 후에 하나의 자바스크립트 파일로 나온 결과물이 번들러의 결과물!
  • ex) webpack, RequireJS, Rollup, Parcel

bundler

➡ 왼쪽의 서로 종속 관계인 파일들을 웹팩을 통해 하나로 깔끔하게 모아준다!!

💡 만약에 번들러가 없었다면?

  1. 파일 하나하나 HTTP 통신을 통해 서버에 요청이 생긴다.
    ➡ js 파일이 올 때까지 기다리기 때문에 화면 로딩시간이 오래 걸린다.
    ➡ one by one으로 파일을 요청하고 응답받기 때문에 파일 개수가 많아질수록 요청이 많아진다.
  2. 파일이 서로 종속 관계를 가지고 있는 경우, 파일의 로드 순서가 중요해진다.
    ➡ 웹팩이 모듈의 종속(dependecy) 관계를 파악하고 알아서! 잘 하나의 파일로 만들어준다.

💡 결론, 웹팩의 역할!

  • 웹팩은 js 파일 뿐만 아니라, img, css, mp4 등 다양한 리소스를 모두 모듈로 관리하여 서로의 의존성을 관리해준다.
  • 또 웹팩은 개발 단계에서 사용하는 dev server,
    필요할 때 import하는 dynamic import,
    모듈을 하나의 파일로 만들지 않고 의존성을 따져 나눠서 빌드하는 code spliting 등을 지원한다.

webpack


💡 webpack - entry & output

yarn add webpack webpack-cli babel-loader @babel/core @babel/preset-env @babel/preset-react -D
yarn add react react-dom
// webpack.config.js
const path = require('path');

const config = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  }
};

module.exports = config;
  • entry: 이 프로젝트가 어느 파일에서 시작할지 entry 프로퍼티에 경로를 지정

  • output: webpack이 적용된 결과파일을 어느 위치에, 어떤 파일이름으로 생성할지 지정


💡 webpack - loader

  • loader: 파일을 전처리(preprocess) 해주는 것인데, 이 때 파일은 모듈을 뜻하며 js 파일 뿐만 아니라 img, css, csv 등 모든 정적 리소스를 포함한다. loader는 모듈을 입력 받아서, 새로운 모듈로 출력하고 번들링 할 수 있다.

babel-loader

  • 자바스크립트 파일을 처리한다. 예를 들어 jsx 문법으로 작성된 리액트 코드를 처리할 때도 필요하다.
  • js 확장자를 갖는 모듈은 babel-loader가 처리하도록 설정한다.
// webpack.config.js
module: {
  rules: [
     {
       test: /\.js$/,
       exclude: /node_modules/,
       use: ['babel-loader']
     }
  ]
}

//babel.config.js
//babel 세팅도 해야한다. @babel/preset-react 프리셋을 사용하도록 설정
const presets = {
  presets: ["@babel/preset-react"]
};

module.exports = presets;

css-loader

  • css 파일을 모듈로 사용할 수 있도록 해준다.
yarn add sass-loader css-loader mini-css-extract-plugin sass -D
{
  test: /\.(sa|sc)ss$/,
  use: [
    MiniCssExtractPlugin.loader,
    'css-loader',
    'sass-loader'
  ]
}

file-loader

  • file-loader를 사용하지 않으면 root 경로에 모든 파일이 번들된다.
  • 개발모드에서 사용한 경로대로 그대로 파일이 번들되길 바라면 file-loader를 사용하자.
  • name설정을 하지 않으면 파일 이름에 해시값이 포함되며 브라우저 캐싱효과를 활용할 수 있다.
{
    test: /\.(png|jpe?g|gif|svg)$/i,
    use: [
      {
        loader: 'file-loader',
        options: {
          name: '[path][name].[ext]'
        }
      }
    ]
}

💡 webpack - plugin

  • plugin은 로더보다 강력한 기능을 갖는다.
  • loader는 특정 모듈에 대한 처리만 담당하지만, plugin은 웹팩이 실행되는 전체 과정에 개입할 수 있다.
 plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css'
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
			output: 'index.html'
    }),
]
  • HtmlWebpackPlugin는 html 파일에 script 태그를 추가하여 번들된 js 파일을 주입한다.

💡 webpack - mode

✅ development

  • 개발 단계
  • 소스맵 제공

✅ production

  • 배포용
  • 코드 minify, uglify
  • 최적화(tree shaking)로 번들된 파일 크기를 작게
//package.json
"scripts": {
    "start": "react-scripts start",
    "start:dev": "REACT_APP_ENV=dev react-scripts start",
    "start:staging": "REACT_APP_ENV=staging react-scripts start",
    "test-start": "yarn test --watchAll=false && react-scripts start",
    "build": "react-scripts build",
    "build:dev": "REACT_APP_ENV=dev react-scripts build",
    "build:staging": "REACT_APP_ENV=staging react-scripts build",
    "build:production": "REACT_APP_ENV=production react-scripts build",
    "test": "react-scripts test",
    "test-all": "react-scripts test --watchAll=false",
    "eject": "react-scripts eject",
    "storybook": "start-storybook -p 6006 -s public",
    "build-storybook": "build-storybook -s public"
  },
    
    
// 사용 예제
const PRODUCTION_URL = 'https://api.co.kr';
const STAGING_URL = 'https://staging.api.co.kr';
const DEV_URL = 'https://dev.api.co.kr';
const LOCAL_URL = 'http://100.28.2.17:3000';

let uri;

switch (process.env.REACT_APP_ENV) { // REACT_APP_ENV
  case 'production':
    uri = PRODUCTION_URL;
    break;
  case 'staging':
    uri = STAGING_URL;
    break;
  case 'dev':
    uri = DEV_URL;
    break;
  default:
    uri = LOCAL_URL;
}

const httpLink = createHttpLink({
  uri,
});

export default httpLink;    

📌 Babel

Babel은 JavaScript 컴파일러입니다.

💡 컴파일러

➡ 사람이 읽기 편한 프로그래밍 언어에서 컴퓨터가 읽기 편한 코드로 바꿔주는 것

💡 바벨이 필요한 이유

  • 바벨을 새로운 자바스크립트 버전을 어느 브라우저에서나 사용할 수 있도록 ES5 버전으로 변환해 준다.
  • 브라우저는 아직 새로운 자바스크립트 버전을 맞이할 준비가 안되어 있는데, 개발자가 새로운 버전으로 효율적으로 문법을 미리 사용할 때, 바벨이 변환해 줘서 동작하는 것!
  • create react app으로 개발할 때 아직 브라우저가 받아드리지 못하는 최신 메서드들이 있는데 이미 CRA에서 바벨 설정이 되어있었기 때문에 마음껏 최신 문법을 사용할 수 있었다.
  • (+JavaScript나 Python은 컴파일 언어가 아니며, 사람이 쓴 대로 컴퓨터가 해석하는 "인터프리터 언어"라고 부른다. 그럼 왜 컴파일 언어가 아닌데 왜 컴파일러라고 부르는지? )
    ➡ 자바스크립트에서 자바스크립트로 변환하는거고, 높은 버전에서 낮은 버전으로만 바벨이 변환을 시켜주는 것이기 때문에 정확한 표현은 아니지만 의미상 컴파일러라고 사용한다. 트랜스 파일러라고 말하는 사람도 있다.

💡 바벨과 관련된 필수 module

  • babel-loader: 바벨과 웹펙이 어떻게 동작하는지
  • @babel/core: babel로 컴파일해서 결과물 파일이 나오도록 babel 관련한 핵심 모듈
  • @babel/preset-env: ES2015?6?7 등 어떤 버전을 쓸지에 관한 모듈
  • @babel/preset-react: jsx를 js로!
profile
단단_프로트엔드개발자!

0개의 댓글