본문 바로가기
  • 프론트엔드 개발자 세오세오 | Frontend dev Seo
Learn to Code

[JS] 웹팩(Webpack)과 바벨(Babel): 바닐라 자바스크립트에 처음부터 적용시켜보기

by CEOSEO 2021. 9. 9.
728x90
반응형

 

 

최근 바닐라 자바스크립트로 과제를 만들 기회가 있었다. 요즘 계속 React를 많이 사용했었기 때문에 JSX의 편리함에 익숙해져있던 편이었지만 다행히도 바닐라 자바스크립트를 사용해서 코딩하는 것 자체는 별 어려움이 없었다. 다만, 계속 create-react-app으로 만들어진 프로젝트들을 했었기 때문에 한번도 Webpack이나 Babel을 직접 인스톨해본 적이 없다는 것을 새삼스레 깨달았다. 그래서 이번 기회에, 아주 옛날 HTML, CSS, 그리고 자바스크립트를 혼자 공부했던 시절 진행했던 Front-End Mentor의 챌린지 과제 중 하나에다가 시험삼아 Webpack과 Babel을 인스톨해보고 설정을 직접하는 연습을 해보려고 한다.

 

오늘의 실험 대상은 무려 작년(!?)에 만들었던, 정말 내 GitHub에 생성된 최초의 레포지토리인 과제이다. HTML, CSS, 그리고 자바스크립트를 혼자 열심히 공부해보고 2주도 되지 않아 만들었던 것이니 얼마나 ... 음... 크흑... 🙈🙈🙈 (말잇못) 도대체 무슨 자신감이었는진 모르겠지만 뭔가 처음으로 혼자 만들었다는 사실에 들떠서 아래 포스팅을 남겼던 것 같다:

 

2020.12.24 - [Learn to Code] - 프론트엔드 맨토(Frontend Mentor), 과제 제출하기!

 

프론트엔드 맨토(Frontend Mentor), 과제 제출하기!

HTML, CSS, 자바스크립트까지 얼추 공부한 뒤 어떤 프로젝트를 해야하나 고민을 했었다. 그리고 가뭄난 땅에 내린 비처럼(?) 찾게 된 Frontend Mentor라는 곳! 여기서 쪼렙들을 위한 가장 가장 쉬운 HTML

seo-tory.tistory.com

 

 

 

 

 

현재 상황 🙈🙈🙈

🙈 더 이상의 미니멀리즘은 허하지 않는다  🙈

 

모양은 멀쩡하다

 

디자인은 FrontEnd Mentor 챌린지에서 나왔던 것과 동일하게 되어있다. 얼핏 기억이 나는데, 그 옛날(?) 저 프로필 사진을 동그랗게 처리하면서 혼자 엄청 어려워 했던 것 같다. 도대체 왜 저걸로 끙끙거렸는지 잘 기억이 나지 않지만, 자꾸 동그라미가 내 맘도 몰라주고 perfect circle이 아닌, 뭔가 아파보이는 모양으로 나왔던 것 같다.

 

 

이런 느낌이랄까...

 

웹 개발 공부를 처음 시작하며 만들어보았던 작업물을 이제와 돌아보니 정말... 🙈🙈🙈...이지만 시험삼아 여기에다가 Webpack과 Babel을 적용해보도록 하겠다.

 

 

 

npm init -y

 

현재 이 프로젝트는 더 이상의 심플함은 존재할 수 없다는 걸 몸소 보여주며 극상의 미니멀리즘을 실천하고 있다. 그러고보니 js 파일도 하나 없다. (도대체 여기에 왜 Webpack과 Babel이 필요한가)

 

그래도 일단 이번 실험(?)의 목적은 웹팩과 바벨을 직접 인스톨해보고 설정도 해보고하는 것이니, 가장 먼저 해주어야 할 것이 npm init이었다. 이제 npm과의 새로운 륄레이션쉽에 도입한 나의 디랙토리는 아래와 같이 날 것 그대로의 package.json을 소유하게 된다.

 

// pacakge.json

{
  "name": "mobile-first-profile-card",
  "version": "1.0.0",
  "description": "A mobile-first, responsible profile card",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ksyksy815/Mobile-First-Profile-Card.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/ksyksy815/Mobile-First-Profile-Card/issues"
  },
  "homepage": "https://github.com/ksyksy815/Mobile-First-Profile-Card#readme"
}

 

 

 

Babel

바벨은 자바스크립트 트랜스파일러(transpiler)이다. 자바스크립트 언어는 매해 새로운 기능들이 추가되는데, 간혹 오래된 브라우저에서 이러한 최신 문법을 지원하지 않는 경우들이 있다. 이런 브라우저로 사용자가 접속하였을 땐, 최신 문법으로 작성된 코드는 돌아가지 않는다. 이를 방지하기 위해, 바벨은 최신 자바스크립트 문법을 지원하지 않는 브라우저에서도 최신 문법으로 작성된 코드들이 잘 돌아갈 수 있도록 변환해준다.

 

바벨을 사용하기 위해 우선 아래와 같이 3개의 패키지를 더해준다.

 

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

 

// 1. 바벨코어

@babel/core

바벨코어는 '코어'라는 이름이 나타내듯이, 바벨의 핵심 트랜스파일링 기능이 들어있는 패키지이다.

 

Q. babel-core vs. @babel/core

바벨코어를 검색해보면 간혹 패키지명이 babel-core 또는 @babel/core의 두가지로 나뉘는 것을 볼 수 있다. 이 둘은 그냥 버전 차이로, @babel/core가 최신 버전이라고 생각하면 된다. 그렇기 때문에 새로 dependency를 추가하는 것이라면 @babel/core를 쓰면 된다. 이는 바벨 관련 나머지 패키지들에도 모두 통용된다. (예: babel-present-env => @babel/preset-env)

 

Babel 공식문서 참고:

Scoped Packages
The most important change is finally switching all packages to scoped packages (the folder names in the monorepo are not changed but the name in its package.json is).
This means there will be no more issues with accidental/intentional name squatting, a clear separation from community plugins, and a simpler naming convention.
Your dependencies will need to be modified like so:
babel-cli -> @babel/cli. For us, we basically started by replacing babel- with @babel/.

출처: https://babeljs.io/docs/en/v7-migration#scoped-packages

 

 

// 2. 바벨프리셋

@babel/preset-env

바벨 프리셋은 함께 사용되어야 하는 바벨 플러그인을 모아둔 것이다. 바벨의 플러그인은 어떤 코드를 어떻게 변환시킬지에 대한 규칙들을 뜻한다. 옛것이 아니면 이해하질 못하는 브라우저를 위해, 최신 자바스크립트 문법으로 작성된 코드를 옛날 사람으로 탈바꿈 시키기 위해선 일련의 규칙들이 필요하다. 그런 규칙들이 정해져 있어야 코드 변환이 가능하기 때문이다. 예를 들어, 손에 들고 있는 손풍기는 사군자가 그려진 부채로, 에쉬 계통으로 탈색과 염색을 반복한 웨이브진 머리쪽진 머리로, 형광 노랑 크롭탑개나리빛 저고리로 바꾼다는 규칙들이 명시되어 있는 것이 바벨의 플러그인들이다.

 

????

 

바벨은 이러한 플러그인들(= 규칙들)을 프로젝트의 congifuration 파일에 적용을 한다. 그러면 요즘 것옛 것으로 변환이 가능해진다. 바벨 공식 홈페이지에 가면, 어떤 플러그인들이 있는지 볼 수 있는 리스트가 있다 (링크). 정확히 어떤 최신 문법이 어떤 식으로 변환되어지는지에 대한 예제가 모두 나와있으니 궁금한 경우 참고하면 된다.

 

프리셋(preset)은 이러한 플러그인들을 세트로 모아놓은 것이다. 그렇기 때문에, 바벨을 통해서 코드 변환을 하려면 핵심 변환 능력을 담고 있는 @babel/core 뿐만 아니라, 어떤 코드를 어떻게 변환할지에 대한 규칙들을 담고 있는 @babel/preset-env도 함께 인스톨해야한다. 바벨은 총 4개의 프리셋을 제공하며, @babe/preset-env는 그 중 하나이다 (공식문서). 

 

인스톨한 프리셋을 사용하려면 configuration file을 만들어주어야 한다. 바벨에선 두 종류의 configuration file이 있는데, 그 두 종류는 함께 사용해도 되고, 필요에 따라 각자 사용해도 된다. 

 

1. Project-wide configuration
- babel.config.json files, with the different extensions (.js, .cjs, .mjs)

2. File-relative configuration
- .babelrc.json files, with the different extensions (.babelrc, .js, .cjs, .mjs)package.json files with a "babel" key

출처: 공식문서

 

이번 연습에선, 아래와 같은 내용으로 루트 폴더에 babel.config.json 파일을 만들어주었다( = 1번 타입). 인스톨한 @babel/preset-env를 사용하겠다는걸 알려주는 내용이다.

 

{
  "presets": ["@babel/preset-env"]
}

 

 

// 3. 바벨클리

@babel/cli

바벨의 빌트인(built-in) CLI (Command Line Interface)이다. 파일을 컴파일 할 때 코맨드 라인을 사용해서 할 수 있도록 해준다.

 

공식 문서에 따르면, 이 CLI를 컴퓨터 전체에서 사용할 수 있게 다운로드 해도 되지만, (1) 다른 프로젝트들이 각기 다른 버전의 바벨을 사용할 수도 있고 (2) dependency list에 작성되지 않은 무언가를 사용하여 개발하는 것보단 명확한 의존성 패키지들이 갖춰진 환경에서 개발하는 것이 더 좋기 때문에 이 바벨클리를 개별 프로젝트마다 인스톨하여 사용하는 방식을 추천한다고 한다. (출처)

 

 

 

 

Webpack

웹팩은 의존성있는 모듈을 하나의 파일로 통합시켜주는 번들러이다. 웹팩말고도 여러가지 번들러가 있는데, 그중 가장 많이 사용되는 번들러가 웹팩이다. 모듈 번들러를 사용하면 웹페이지에서 자바스크립트 파일을 여러번 다운로드 받지 않아도 된다는 이점이 있다. 

 

 

바벨은 최신 자바스크립트 문법으로 쓰여진 코드가 업데이트가 되지 않은 브라우저에서도 작동할 수 있도록 구형 문법으로 변경해주는 역할을 한다면, 웹팩은 그렇게 변경된 파일들을 이제 최종적으로 모으고 모아서 (=번들링해서) 배포하기 좋게끔 정리해주는 역할을 한다고 할 수 있다.

 

이러한 웹팩과 바벨을 함께 사용해서 자동으로 컴파일 -> 번들까지 되도록 구축을 해놓으면 편리성이 올라가기 때문에 그 둘이 자주 함께 거론되고 사용되는 것이다.

 

npm install --save-dev webpack webpack-cli  babel-loader

 

 

babel-loader

바벨로더는 웹팩이 모듈을 번들링할 때 바벨을 사용하도록 해준다

 

 

 

webpack.config.js

webpack.config.js 파일은 웹팩이 실행될 때, 어떤 설정들에 맞추어 실행되어야할지 알기 위해 참조하는 파일이다. babel.config.js과 마찬가지로, 프로젝트의 루트 폴더에 생성해야한다. 이 설정 파일은 어떤 자바스크립트 파일에서 시작할 것인지, 번들링이 끝난 결과물은 어디에 저장할 것인지, 어떤 추가 규칙들이 있는지 등등에 대한 설정 사항들을 담게 된다.

 

웹팩을 실행시키는데 필요한 설정들엔 정말 많은 것들이 있어서, 링크로 설명을 대신하려고 한다. 공식문서인데, 작성된 webpack.config.js에서 각 옵션을 클릭하면 그 옵션을 설명하는 페이지로 이동시켜준다!

 

디테일한 설정들은 프로젝트의 특성에 맞춰서 적용을 하면 되는데, 내용이 꽤 방대해서 들여다보고 공부하려면 시간이 좀 걸릴 것 같다 😅. 커스텀 웹팩 설정 파일을 만들어주는 온라인 툴도 있다고 하니 들여다보는 것도 재미있을 것 같다.

 

우선 이번 내 실험(?)을 위해선 아래와 같이 짧은 버전으로 작성하였고, "webpack -w"로 트랜스파일링 & 번들링을 모두 실행할 수 있었다!

 

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: 'myBundle.js',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [path.resolve(__dirname, 'src/js')],
        exclude: /(node_modules)|(dist)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },
  devtool: 'source-map',
};

 

 

 

DevServer

사실, 아무 npm 패키지도 사용하지 않는 순수한 html 파일 하나와 css 하나와 js 하나(?)만 가지고 작업을 할 때, 가장 궁금했던 것은 어떻게하면 VSCODE의 Live Server extension 없이 서버를 띄우고 할 수 있냐는 것이었다. 그리고 이번에 웹팩 설정 파일을 들여다보면서 이것에 대한 궁금증을 드디어 해소할 수 있었다!!

 

우선 아래와 같이 웹팩 설정 파일에 devServer 부분을 추가해주었다.

 

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: 'myBundle.js',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [path.resolve(__dirname, 'src/js')],
        exclude: /(node_modules)|(dist)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },
  devtool: 'source-map',
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
    },
    compress: true,
    port: 3000,
  },
};

 

그리고, package.json의 scripts에 추가해주었다.

 

"scripts": {
    "build": "webpack -w",
    "start": "webpack serve --open --progress"
  },

"start"에 해당하는 webpack serve를 사용하려면 webpack-dev-server도 설치해주어야 한다.

 

npm install --save-dev webpack-dev-server

 

webpack serve 뒤에 --open과 --progresss는 사용할 수 있는 옵션들인데, 리액트 보일러플레이트에서 매번 사용하던 두 가지 기능을 골라서 추가해주었다. 어떤 옵션들이 있는지는 여기에서 볼 수 있다. --open은 서버가 시작되면 브라우저가 자동으로 오픈되도록 해주는 옵션이고, --progress는 빌드 중 컴파일 상황을 알려주는 옵션이다. 

 

 

 

마무리

원래 본 작업 파일엔 자바스크립트가 하나도 없었기 때문에 (도대체 왜 얘를 사용했니) 번들링 테스트용으로 main.js 하나를 만들어서 해보았더니, 설정 파일에서 지정한 myBundle.js라는 이름의 파일이 성공적으로 만들어지는 것을 볼 수 있었다. 아직 웹팩 설정을 디테일하게 커스터마이징하는 것과, 바벨 프리셋에 포함되지 않은 플러그인들을 별도로 설치해서 사용해보지 않았기에 더 많은 공부가 필요하다. 그래도 그동안 taken-for-granted로 사용하던 기능들의 뒷편에 어떤 일들이 일어나는지 조금이나마 들춰본 듯한 기분이 들어서  뿌듯한 기분이 얼핏 드는 것 같기도 하다! 😄

 

 

 

728x90
반응형

댓글