Webpack 기초 간단 정리✨ - 실전편

기록일기📫·2021년 11월 6일
14

webpack

목록 보기
2/3
post-thumbnail

이번 포스팅에서는 기본적인 웹팩 설정을 진행하고 간단한 자바스크립트 어플리케이션을 빌드하는 과정을 진행해 본다.

💡 웹팩에 익숙하지 않으신 분은 webpack 기초 간단 정리✨ - 개념편을 먼저 보고 오시는 것을 추천합니다 :)

시작🥳

이번 포스팅의 목적은 웹팩 컨피그를 직접 작성해보며 이해도를 높이는 것이다. 따라서 html, javascript, css, image 파일을 웹팩으로 번들링 하기 위해 필요한 최소한의 기본 설정만 진행해 볼 예정이다.

폴더 구조

본격적으로 시작하기 앞서 우리가 만들 프로젝트의 폴더 구조를 살펴보자.
우리가 만들 초기 프로젝트 구조(as-is)와 빌드 후(to-be)의 프로젝트 구조는 아래와 같다.

빌드 후에는 오른쪽 사진과 같이 dist 폴더 하위에 js파일과 css파일을 번들링 한 결과물(main.js)이 저장되도록 설정을 진행해보자.


프로젝트 생성

그럼 프로젝트 생성부터 바로 시작해보자!

package manager로는 yarn을 이용할 것이다. yarn init -y를 통해 프로젝트를 초기화 해주고, 필요한 패키지들을 모두 설치하자.

/* 폴더 생성 */
mkdir webpack-bolierplate
cd webpack-boilerplate

/* 기본 package 설치 */
yarn init -y
yarn add -D webpack webpack-cli webpack-dev-server webpack-merge
yarn add -D css-loader file-loader html-loader
yarn add -D html-webpack-plugin mini-css-extract-plugin clean-webpack-plugin

설치한 패키지들은 모두 빌드 타임에 필요한 패키지들이기 때문에 -D 옵션을 이용해 devDependency로 설치해 주었다. 필요한 패키지들을 모두 설치한 후 package.json 파일은 아래와 같다.

설치한 패키지들이 어떠한 역할을 하는지를 대략적으로만 살펴보자.

지금 다 이해할 필요는 없고, '이런것들을 사용하는구나!' 정도의 느낌만 가지고 가도 충분하다.

clean-webpack-plugin : 빌드시 이전에 빌드 했던 파일 삭제
css-loader : css 모듈화. css import 가능하게 함
file-loader : 파일 모듈화시켜서 import 가능하게 함
url-loader : file-loader와 동일하나, 파일을 base64 URL로 변환(경량화)
html-webpack-plugin : 빌드시 html 파일에 빌드한 javascript 파일 삽입
mini-css-extract-plugin : css 파일로 따로 빼서 빌드
webpack : 웹팩 코어 기능
webpack-cli : 웹팩 command를 cli로 사용
webpack-dev-server : 웹팩 개발 서버 띄우기
webpack-merge : 웹팩 config 파일 병합


웹팩 설정

패키지 설정까지 끝마쳤으니 이제 웹팩 설정을 진행할 준비가 다 되었다!
그럼 이제 root 디렉토리에 웹팩 컨피그 설정을 위해 webpack.common.js 파일을 생성하고 컨피그를 시작해보자.

사용 모듈 불러오기

우선 사용할 모듈들을 모두 불러오자.

나머지 모듈의 사용 용도는 위에서 설명했으니, path 모듈만 살펴보자. path 모듈은 node.js이 기본으로 제공하는 모듈로 파일/폴더등의 경로를 편리하게 설정할 수 있는 인터페이스를 제공한다.

우리는 path에서 제공하는 resolve 메서드를 활용하는데, 이 함수는 인자로 받은 경로들을 하나로 합쳐서 문자열 형태의 path를 리턴한다.

entry, output 설정

이제 entry와 output을 지정해주자.

우리는 src폴더 안에 main.js파일을 entry로 사용하고, dist 폴더를 빌드 경로로 둘 것이기 때문에 위와 같이 설정해주었다.

loader 설정

다음으로는 loader 설정을 진행하자.

css loader

많이 사용하는 css용 로더로는 MiniCssExtractPlugin과 style-loader가 있다. 이번 설정에서는 MiniCssExtractPlugin.loader를 사용했다.

style-loader를 사용하지 않은 이유는 style-loader의 동작 방식 때문인데, style-loader는 번들링하게 될 경우 스타일 파일마다 style 태그를 만들어서 html 파일 내에 삽입한다.

따라서 css파일이 많아지면 그만큼 index.html 파일에 삽입되는 style 태그의 개수가 늘어나게 된다.

별도의 파일로 추출하는 형태로 번들링을 진행 하고 싶을 시에는 MiniCssExtractPlugin을 사용해야 한다.

file loader

파일을 처리하기 위해 url-loader를 사용하였다. 파일을 처리하기 위한 로더로는 url-loader와 file-loader가 있다.

url-loader는 파일을 base64 문자열 형태로 변환하여 번들 파일에 문자열 형태로 직접 넣어주는 방식이고, file-loader는 파일을 별도 추출하여 output 폴더로 넣어주는 방식이다.

url-loader를 이용하여 모든 파일을 base64 형태로 변환할 수도 있지만, 주로 limit 옵션을 줘서 특정 용량보다 작은 파일에 대해서만 진행한다. 이 경우 그 이상의 큰 파일은 file-loader를 통해 처리한다.

따라서 모든 파일을 base64 형태로 처리하려는 것이 아니라면 file-loader와 함께 사용해야 한다.

모든 파일을 url-loader로 처리하게 되면 파일 요청을 하는 네트워크 통신 횟수는 적어지겠지만, 번들의 크기는 커진게 된다. 따라서 용량이 작거나 반복해서 사용하지 않는 이미지에만 url-loader를 사용하는 것이 권장된다.

실제로 꽤 큰 이미지를 url-loader를 이용해 빌드하고 결과물을 확인해 보면 '아.. limit 걸어야겠다...^0^' 하고 바로 이해하게 된다.

위 사진은 72KB 정도 되는 파일을 url-loader를 이용해 base64로 변환해 본 것이다.

다시 설정 코드로 돌아가서, url-loader에 name 옵션을 추가한 것을 볼 수 있는데 이는 파일명을 변경하기 위해서이다. [ext]는 확장자, [hash]는 기본적으로 번들링시 붙여주는 해쉬스트링 값이다.

해당 옵션 적용 후 빌드를 진행하면 아래의 사진처럼 [name].[ext]?[hashString]의 형태로 파일이 만들어지게 된다.

plugin 설정

마지막으로 플러그인 설정을 살펴보자!

다른 플러그인들은 주석으로 설명이 될 것 같으니, HtmlWebpackPlugin에 대해서만 살펴보자. htmlwebpack plugin은 빌드시 번들링 된 style 파일과 javascript 파일을 자동으로 넣어주는 기능을 제공한다.

템플릿 파일 경로를 주고 빌드를 진행하면, 아래 사진과 같이 main.js 파일과 style.css 파일을 자동으로 주입해 준다.

dev, prod config 파일 분리

이제 기본적인 웹팩 설정은 다 마쳤다. 조금의 커스텀만 더 진행해보자. 지금은 하나의 파일에 모든 컨피그를 진행한 상태지만, 추후 확장성을 고려했을때 dev파일과 prod 파일을 나눠서 관리하는게 더 효율적이다.

이를 위해 공통의 설정은 webpack.common.js파일에 담아두고, 개발 환경과 프로덕션환경에 필요한 설정들은 webpack.dev.js, webpack.prod.js에 나눠 관리해보자.

webpack.common.js

common 파일에는 공통적인 설정만 담아놓았다.

이제 여기에 dev환경과 prod환경에 필요한 환경들을 각각 추가하여 빌드 시 merge할 것이다.

webpack.dev.js

개발 환경에서 실행될 dev 파일이다.

historyApiFallBack의 경우 SPA 개발시 주로 하는 설정으로 404가 발생하면 index.html로 리다이렉트를 진행하는 설정이다.

webpack.prod.js

prod 파일은 실제 배포를 위한 build에 사용되게 된다.

프로덕션의 경우 아직 추가할 설정이 많지 않기 때문에 mode 설정만 진행해 주었다.

package.json 명령어 추가하기

마지막으로, package.json에 webpack 이용을 위한 시작 명령어를 추가해주자.

start일때는 dev파일을 참조해 통해 devserver를 실행하고, build일때는 prod파일을 참조해 빌드를 진행하도록 설정해주었다.


static 파일 생성

생각보다 포스팅이 길어지고 있지만, 이제 웹팩 설정을 끝냈으니 이제 빌드에 필요한 기초 프로젝트 파일들을 만들어 보자.

앞서 말했듯 이번 포스팅에서는 기초적인 웹 어플리케이션 개발에 필요한 html, css, javascript, image 파일을 만들고 웹팩을 통해 직접 빌드해볼 것이다.

root 디렉토리에 index.html이 위치하고, src 폴더 안에 javascript 파일 및 정적 파일(이미지,css파일)들이 담긴 구조로 프로젝트를 생성했다. 자세한 구조는 포스팅 상단의 이미지를 참조하자.

util.js

util 파일은 두개의 간단한 함수로 이루어져 있다.

makeSenetence 함수는 전달된 name으로 string을 return 하는 간단한 함수이다.

makeAvatar는 Avatar 컴포넌트를 생성 함수로, thumbnail 이미지와 message를 조합해 target의 child로 새로 만든 avatar를 반환한다.

이 두개의 함수를 main.js에서 호출할 것이다!

main.js

main.js는 entry 역할을 할 파일이다. main에서 앞서 util.js에서 정의한 makeSentence, makeAvatar 함수를 호출한다. 즉, main.js는 util.js에 의존한다.

따라서 빌드 시 웹팩이 의존성을 검사하여 main.js와 util.js를 합쳐 하나의 파일로 만들어 줄 것이다.

style.css

기초적인 스타일링을 진행해 주었다.


build 해보기

이제 드디어!!! 모든 설정이 끝났다. start나 build 명령어를 이용해서 실행해보자!

정상적으로 실행 되는것을 확인했다!
실제로 빌드된 dist/main.js 파일의 내용은 아래와 같다.

main.js에서 import해서 사용한 util.js의 함수들과 image가 들어가 있는것을 확인할 수 있다.

완성! 끗!

후기

간단한 웹팩 설정을 진행해보았다. 사실 처음에는 react-typescript 개발 환경을 설정하는 과정을 바로 진행할까 했었는데, 최소한의 설정을 먼저 진행 해보고 추가적으로 진행하는게 나을 것 같아 일단 기본적인 설정만 진행하였다.

개념 공부를 하고 어느정도 안다고 생각 했는데 역시 실제로 코드를 작성하며 진행해 보는 것은 느낌이 많이 다른 것 같다.

아웃풋 파일을 보며 번들링에 대해 조금 더 이해 할 수 있었고, 다양한 설정 옵션에 대해 살펴 볼 수 있었던 좋은 기회가 되었다😃

아, 추가로 라인 개발팀에서 웹팩 공식문서를 번역해주셨다! 이곳에서 볼 수 있으니 관심 있는 분들은 살펴보시길!

실습을 진행하며 작성한 코드는 git repository에도 올려 놓았으니 필요하신 분은 자유롭게 쓰셔도 됩니다! :)

++ 21/11/20 기존 코드에 react개발 환경 설정을 추가 적용하였습니다. 기존의 코드는 base-branch에서 확인 가능합니다.

Reference

해당 포스팅은 아래의 글을 참조하여 작성하였다.

https://github.com/taniarascia/webpack-boilerplate
https://github.com/doonguk/webpack-boilerplate#step9
https://www.youtube.com/watch?v=zal9HVgrMaQ&t=601s
https://jeonghwan-kim.github.io/series/2019/12/10/frontend-dev-env-webpack-basic.html

2개의 댓글

comment-user-thumbnail
2021년 11월 12일

훌륭합니다. 필요한 정보를 찾은 것 같습니다. 귀하의 게시물에서 일부 데이터를 보고 언급하겠습니다. 당신에게 많은 의무 https://subwaysurf.co

답글 달기
comment-user-thumbnail
2023년 11월 13일

나는 이 블로그를 매우 좋아합니다. 유익한 주제입니다. 그것은 몇 가지 문제를 해결하는 데 매우 도움이 됩니다. @eggy car

답글 달기