[Javascript] 웹팩

SOL·2023년 12월 26일
0

Javascript

목록 보기
11/13
post-thumbnail

웹팩(Webpack)은 자바스크립트 애플리케이션을 위한 정적 모듈 번들러입니다. 웹팩은 프로젝트의 모든 종류의 파일(자바스크립트, css, 이미지 등)을 모듈로 취급하고, 이 모듈들을 브라우저에서 사용할 수 있는 형태의 하나 또는 여러 개의 파일로 묶어주는 역할을 합니다.

웹팩을 사용하는 주된 이유는 다음과 같습니다.

  • 의존성 관리: 모듈 간의 의존성을 해결하고, 필요한 순서대로 파일을 로드합니다.

  • 로딩 시간 최적화: 여러 파일들을 하나로 합치고, 불필요한 코드를 제거하는 등의 작업을 통해 최종 파일의 크기를 줄이고 로딩 시간을 단축시켜줍니다.

  • 개발 환경 개선: 핫 리로딩 같은 기능을 제공하여 개발 과정에서의 편의성을 높여 줍니다. 코드를 변경할 때마다 브라우저를 새로고침할 필요 없이 바로 변경 사항을 볼 수 있습니다. 그리고 다양한 플러그인과 로더를 지원하여 CSS 최적화, 이미지 압축 등 다양한 작업을 자동화할 수 있습니다.



의존성 관리

웹팩의 의존성 관리는 프로젝트 내에서 사용되는 모듈들 간의 의존 관계를 해결하고, 필요한 순서대로 파일들을 로드하여 최종적으로 브라우저가 이해할 수 있는 형식으로 조합하는 과정을 말합니다.


  • 모듈 인식: 웹팩은 import 또는 require 구문을 사용하여 자바스크립트 파일에서 다른 파일들을 참조하는 방식을 분석합니다. 이러한 방식으로 각 모듈의 의존성을 파악하고, 어떤 모듈이 다른 모듈을 필요로 하는지 지도를 만듭니다.

  • 번들링 순서 결정: 모듈 간의 의존성을 파악한 후, 웹팩은 이 의존성 지도를 기반으로 모든 모듈을 효과적으로 로드할 수 있는 순서를 결정합니다. 이는 프로그램이 예상대로 정확하게 실행될 수 있도록 보장합니다.



로딩 시간 최적화

로딩 시간 최적화는 웹 애플리케이션의 성능을 향상시키기 위해 중요한 요소입니다. 웹팩은 다양한 최적화 방법들을 통해 사용자에게 더 빠른 웹 경험을 제공합니다.


  • 번들링: 웹팩은 여러 개의 소스 파일들을 하나 또는 소수의 파일로 합치는 번들링 기능을 제공합니다. 이 과정에서 서버로부터 브라우저로의 요청 수를 줄일 수 있어, 네트워크 병목 현상을 완화하고 로딩 시간을 줄일 수 있습니다.

  • 미니파이(minify) 및 압축(compress): 웹팩은 코드를 축소하고 압축하여 최종적으로 제공되는 파일의 크기를 줄입니다. 미니파이는 불필요한 공백, 주석, 코드 구문을 최적화하여 제거하는 과정을 포함하며, 압축은 파일을 더 작은 크기로 만들어 전송 효율을 높입니다.

  • 코드 분할(Code Splitting): 큰 프로젝트에서는 코드의 양이 방대해질 수 있습니다. 웹팩은 코드 분할 기능을 통해 큰 덩어리의 코드를 필요에 따라 작은 조각으로 나누고, 이 조각들을 필요할 때만 로드하도록 설정할 수 있습니다. 이는 초기 로딩 시간을 단축하고, 애플리케이션의 반응성을 향상시킵니다.

  • 트리 쉐이킹(Tree Shaking): 웹팩은 사용되지 않는 코드를 제거하는 트리 쉐이킹 기능을 제공합니다. 이 기능은 ES2015 모듈 문법(import 및 export)을 사용하는 프로젝트에서 효과적으로, 실제로 실행되는 코드에 포함되지 않는 불필요한 코드 모듈을 찾아내어 제거합니다.

  • 동적 로딩: 웹팩은 동적으로 모듈을 로드할 수 있는 기능을 제공합니다. 예를 들어, 사용자가 특정 UI 컴포넌트를 클릭할 때 해당 컴포넌트의 코드가 로드되는 방식으로 구현할 수 있습니다. 이를 통해 애플리케이션의 효율성을 높일 수 있습니다.



개발 환경 개선

웹팩은 다양한 기능과 도구를 제공하여 개발자가 보다 효율적이고 편리하게 작업할 수 있도록 돕습니다.


  • 핫 모듈 교체: 이 기능은 애플리케이션을 새로고침하지 않고도 변경된 모듈을 실시간으로 교체할 수 있게 해 줍니다. 이는 개발 중에 UI 상태를 유지하면서 코드 변경사항을 바로 볼 수 있도록 도와주어, 효율성을 크게 향상시킵니다.

  • 소스 맵: 웹팩은 빌드된 코드를 원래의 소스 코드와 연결해주는 소스 맵을 생성할 수 있습니다. 이 기능을 통해 개발자는 크롬 개발자 도구와 같은 브라우저의 디버깅 도구를 사용하여 압축하거나 번들링된 코드가 아닌, 원본 소스 코드에서 디버깅을 진행할 수 있습니다.

  • 환경 설정 제공: 웹팩은 개발(Development)과 프로덕션(Production) 환경을 구분하여 설정할 수 있습니다. 예를 들어, 개발 환경에서는 디버깅을 용이하게 하는 도구와 설정을 활성화하고, 프로덕션 환경에서는 성능 최적화를 위해 다른 설정을 적용할 수 있습니다.

  • 플러그인과 로더: 웹팩은 매우 유연한 플러그인 시스템을 제공하여, 개발 과정에서 필요한 다양한 작업을 자동화하거나 맞춤화할 수 있습니다. 예를 들어, CSS를 자동으로 최적화하거나, 이미지를 압축하는 작업을 플러그인을 통해 설정할 수 있습니다.


핫 모듈 교체

핫 모듈 교체(Hot Module Replacement, HMR)는 웹팩에서 제공하는 매우 유용한 기능 중 하나입니다. 이 기능은 개발 중에 웹 애플리케이션을 새로고침하지 않고도 수정된 모듈을 실시간으로 교체할 수 있게 해 줍니다. HMR을 사용하면 개발자가 코드를 변경한 후 바로 결과를 볼 수 있어 개발 과정의 효율성을 크게 향상시킬 수 있습니다.

HMR의 작동 방식은 다음과 같습니다.

  1. 개발자가 코드를 수정하면 웹팩이 이를 감지합니다.
  2. 웹팩은 변경된 모듈만을 대상으로 새로운 코드를 빌드하고, 이를 기존의 러닝 애플리케이션에 적용합니다.

애플리케이션을 새로고침하지 않기 때문에 애플리케이션의 상태(예: 사용자 입력, UI 상태)는 유지됩니다.


빌드된 파일은 어디에 저장될까요?

빌드된 파일들은 실제로 디스크에 저장되지 않고 메모리에 유지됩니다. 기본적으로 webpack-dev-server는 변경 사항을 감지하고, 해당 모듈만을 다시 컴파일하여, 결과를 서버의 메모리에 저장합니다. 이 접근 방식은 디스크 I/O를 줄여주어 빌드와 리로드 시간을 크게 단축시킵니다.

메모리에 저장된 파일은 웹 서버를 통해 브라우저에 제공됩니다. 브라우저는 변경된 모듈을 즉시 받아 로드하며, 전체 페이지를 새로고침하지 않고도 변경 사항을 반영할 수 있습니다.



webpack.config.js

웹팩을 사용하기 위해서는 webpack.config.js 파일을 통해 여러 설정을 구성해야 합니다. 이 파일에서는 엔트리 포인트(entry point), 아웃풋(output), 로더(loaders), 플러그인(plugins) 등을 정의하여 웹팩이 어떻게 작동할지를 지정합니다.


전체적인 기본 코드 구조는 다음과 같습니다.

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

module.exports ={
	mode: 'development',
	entry: './app.js', // 애플리케이션의 진입점
	output: { // 출력에 관한 설정
		path: path.resolve(__dirname, 'dist'), // 번들이 생성될 경로
		filename: 'bundle.js' // 생성되는 번들의 이름
	},
	devServer:{ // 개발 서버 설정
		compress: true, //압축해라 
		port: 9999,
	},
	module: { // 모듈 처리 규칙(로더 등)
		rules: [
			{
				test: /\.js$/, // 로드할 파일 형식
				exclude: /node_modules/, // 제외할 폴더
				use: {
					loader: 'babel-loader', // 사용할 로더 (필수적인 로더로 바벨이 있습니다.)
					options: {
						presets: ["@babel/preset-env","@babel/preset-react"]
					}
				}
			}
		]
	},
	plugins: [ // 플러그인 설정
		new HtmlWebpackPlugin({
			title: '임의로 만들어서 넣을 수 있습니다.',
			template: 'index.html'
		})
	]
}


설정별로 좀 더 자세히 살펴보겠습니다.

mode

mode: 'development',

웹팩이 최종적으로 서비스할 용도의 파일을 만드는 것인지, 아니면 현재 개발중인 상태의 파일을 만드는 것인지를 구분시켜주기 위해 스위칭하는 옵션입니다.


entry

entry: './app.js',

애플리케이션의 시작점을 지정합니다. 웹팩이 애플리케이션을 빌드할 때 이 파일을 기준으로 모듈의 의존성 트리를 생성합니다.

이미지, css, 텍스트 파일, json 파일 등 굉장히 여러 포맷들의 파일들이 웹팩의 입력으로 들어옵니다.


output

output: {
  	path: path.resolve(__dirname, 'dist'), 
    filename: 'bundle.js' 
},

웹팩이 프로젝트를 빌드한 후 번들된 결과물을 저장할 경로와 파일 이름을 정의합니다.

path에는 디렉토리 경로로 dist를 많이 사용하는데, OS별로 디렉토리 시스템 구조가 다르기 때문에 path 패키지를 이용해서 디렉토리명을 안전하게 지정해줄 수 있습니다. path의 resolve에 현재 디렉토리를 의미하는 상수와 출력할 디렉토리 이름을 넘겨줍니다.


module

module: { 
  rules: [
    {
      test: /\.js$/, 
      exclude: /node_modules/, 
      use: {
        loader: 'babel-loader', 
        options: {
          presets: ["@babel/preset-env","@babel/preset-react"]
        }
      }
    }
  ]
},

웹팩은 오직 JavaScript와 JSON 파일만 이해할 수 있기 때문에, 다른 타입의 파일(예: CSS, 이미지, TypeScript 등)을 처리하기 위해 로더를 사용합니다. 로더를 설정하면 웹팩은 이러한 파일들을 모듈로 변환하여 애플리케이션에서 사용할 수 있게 해줍니다.

module에는 rules 배열이 들어있고, 이 룰안에 지정하는것들을 loader라고합니다. 사용할 로더의 이름과 각 로더마다 어떻게 동작하면 좋을지에 대한 옵션들을 작성해줍니다.

위의 코드를 예시로 들어 바벨 로더를 사용할 때, entry를 기준으로 들어오는 모든 파일들을 바벨 로더가 처리해야하는 것은 아니므로, 자바스크립트 파일만 처리하도록 test 속성에 정규식으로 파일 형식을 지정해줍니다.

node_modules 폴더는 너무 커서 번들링에 포함시키면 쓸데없이 출력파일이 커질 수 있으니, exclude옵션을 사용해서 제외시킵니다.


plugins

plugins: [ 
    new HtmlWebpackPlugin({
      title: '임의로 만들어서 넣을 수 있습니다.',
      template: 'index.html'
    })
]

웹팩으로 하나의 출력 파일을 만드는 과정에서 중간에 무언가 처리할 필요가 있을 때, 그것만을 위한 소프트웨어를 plugin이라고 부릅니다.

로더가 파일별 변환을 담당한다면, 플러그인은 번들 최적화, asset 관리, 환경 변수 주입 등 번들 프로세스의 전반적인 과정을 커스터마이즈할 수 있게 해줍니다.

예를들면 ES6 이상 문법으로 만들어진 자바스크립트를 입력(entry)으로 받아놓고 module에 이것을 es5 문법으로 변환해주는 트랜스파일러를 하나 세팅해주고, 변환된 파일을 플러그인에다가 넘겨줍니다. console log와 같은 주석들을 제거하는 플러그인을 세팅해줬다면 번들링 프로세스에서 순서대로 실행됩니다.

위의 예시 코드에서 html-webpack-plugin 은 html 파일을 받아서 최종적인 번들링 파일을 output으로 보낼때 사용될 html을 생성해 줄 수도 있고, 템플릿화해서 다른 부가적인 처리를 할 수도 있는 그런 기능들을 제공해줍니다. 번들링된 js를 html의 header에 <script defer src="bundle.js"></script> 해당 스크립트를 자동으로 넣어줍니다.

외부 패키지므로 require 해야하며 함수라서 객체로 만들어서 넣어주어야합니다.


devServer

devServer:{ 
  	compress: true, 
    port: 9999,
},

개발 중에 사용할 웹 서버의 설정을 제공합니다. 예를 들어, HMR(핫 모듈 교체)을 활성화하거나, 개발 서버의 포트를 설정할 수 있습니다.

설정한 웹 서버를 띄우기 위해서 packege.json에 스크립트를 만들어줍니다. 웹팩을 설치했으니 그냥 webpack이라고 실행하면 default로 webpack.config.js를 찾아서 실행합니다. 그러나 webpack만 실행하면 번들링만 해줍니다. 계속 결과를 확인하면서 개발하기 위해 dev server를 띄우는 dev 스크립트도 추가해줍니다.

"script" : {
	"build": "webpack",
	"dev" : "webpack serve",
}

이제 npm run dev를 실행시키면 dev server가 실행되며 9999포트로 화면을 띄울 수 있습니다. dev server를 통해 번들링 된 빌드 파일은 메모리에 올라갑니다. 빌드 결과물을 확인하기 위해서는 npm run build를 실행시켜주어야 합니다.



웹팩과 Node.js의 관계

왜 webpack.config.js는 Node.js 문법을 사용할까요?

웹팩이 브라우저가 아닌 Node.js 환경에서 실행되기 때문입니다. 웹팩이 Node.js 환경에서 실행된다는 것은, 웹팩이 Node.js의 기능과 API에 의존하여 자신의 기능을 수행한다는 것을 의미합니다.

Node.js는 JavaScript를 브라우저 밖에서 실행할 수 있게 하는 런타임 환경입니다. 따라서 webpack.config.js은 Node.js 스크립트 파일이며, 이를 처리하기 위해 코드도 Node.js 환경의 규칙을 따라야 합니다.

Node.js는 CommonJS 모듈 시스템을 사용하여 파일과 모듈을 관리하며, 이 시스템을 통해 파일과 모듈의 의존성을 관리하고, requiremodule.exports를 사용하여 모듈을 불러오거나 내보낼 수 있습니다. 웹팩은 이 모듈 시스템을 활용하여 프로젝트의 모든 자바스크립트 파일과 기타 자산을 하나의 파일로 번들링하는 작업을 수행합니다.



profile
개발 개념 정리

0개의 댓글

관련 채용 정보