Webpack 파헤치기 3 - Loader

조현재·2022년 2월 23일

Webpack

목록 보기
3/4
post-thumbnail

Loader

Loader는 Webpack의 동작에서 가장 중요한 부분이라고 해도 부족하지 않습니다. 이전 글에서 Webpack은 흩어져있는 여러 파일들을 묶어 하나의 파일로 만드는 Bundle 라이브러리라고 말씀드렸습니다. JS, CSS, HTML 등 여러 타입의 파일을 묶기 위해서는 각 파일을 읽는 과정이 필요합니다. Loader는 바로 이 과정에서 필요합니다. 따라서 Loader는 개발하면서 사용한 모든 파일을 Webpack이 제대로 이해하고 Bundle 하기 위한 도구라고 생각하시면 됩니다.

Loader 설정하기

Webpack을 구성할 때 Loader는 module이란 key에 매핑하여 설정합니다.

module: [
	rules: [
    	{
			test: /\.jsx?$/, // 어떤 파일에 적용할 것인지 결정
			use: 'babel-loader', // 어떤 loader를 사용할 것인지 결정
			include: src/, // Loader를 적용할 영역
			exclude: node_modules/ // Loader를 제외할 영역
        },
        ...
    ]
]

Loader는 module key 내 rules 부분에 설정합니다. 크게 어떤 위치, 어떤 파일, 어떤 loader를 적용할 것인지를 명시하여 추가합니다.

Babel Loader

직접 Webpack을 구현해본 적이 없다고 하더라도 Babel이란 단어는 들어보셨을 것입니다. 흔히 브라우저는 ECMA 최신 문법을 이해하지 못하기 때문에 브라우저가 이해할 수 있는 버전으로 변경해주어야 하기 때문에 Babel이 필요하다. 라고 알고 계실 것입니다. 여기서 중요한 개념이 브라우저가 이해할 수 있게입니다. 즉, Babel Loader는 JS 파일들을 Bundling 할 수 있도록 Webpack이 이해할 수 있게 해주는 가장 대표적인 Loader입니다.

CSS Loader

JS 파일을 이해하기 위해 Babel Loader가 필요하다면 CSS 파일을 이해하기 위해서는 CSS 파일이 필요합니다. CSS Loader에는 크게 style-loader, css-loader, sass-loader가 있습니다. 아래 설정을 통해 CSS-Loader를 적용해보겠습니다.

const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;

function getCSSLoaderOption(type, sourceMap) {
	switch (type) {
		// 기본 Regex만 사용할 경우 loader Option
		case 1:
			return { loader: 'css-loader', options: { sourceMap } };

		// Module Regex를 사용할 경우 loader Option
		case 2:
			return { loader: 'css-loader', options: { sourceMap, modules: { getLocalIdent: getCSSModuleLocalIdent } } };

		default:
			console.error('CSS-Loader Error ::: Loader Option is invalid');
			return false;
	}
}

/**
 Creates `style` nodes from JS strings : "style-loader",
 Translates CSS into CommonJS : "css-loader",
 Compiles Sass | Scss to CSS : "sass-loader"
**/

function getCSSLoaders(type, isDevelopment, isSass) {
	// 배포환경에서는 MiniCss 라이브러리로 효율성 확장
	const mainLoader = isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader; 
	const cssOption = getCSSLoaderOption(type, isDevelopment);

	return isSass ? [mainLoader, cssOption, 'sass-loader'] : [mainLoader, cssOption];
}

module: [
	rules: [
    	{
			test: cssRegex,
			exclude: cssModuleRegex,
			use: getCSSLoaders(1, env.isDevelopment, false),

			// https://github.com/webpack/webpack/issues/6571
			// 사용하지 않는 css 파일은 버리기
			sideEffects: true
		},
		{
			test: cssModuleRegex,
			use: getCSSLoaders(2, env.isDevelopment, false),

			include: paths.src
		},
		{
			test: sassRegex,
			exclude: sassModuleRegex,
			use: getCSSLoaders(1, env.isDevelopment, true),

			sideEffects: true
		},
		{
			test: sassModuleRegex,
			use: getCSSLoaders(2, env.isDevelopment, true)
		},
    ]
]

뭔가 Babel Loader의 설정보다 복잡해보이는 것은 기분 탓이 맞습니다... 그래도 차근차근 보면 오히려 이해하기 쉽습니다. Webpack 2, 3 버전에서는 css 파일을 읽기 위해서 style-loader만을 사용했습니다. 그러나 webpack 5 버전으로 넘어오면서 크고 무거운 css 파일을 위해 style-loader와 함께 css-loader를 함께 사용합니다. 쉽게 메인으로 style-loader가 동작하고 서브로 css-loader가 함께 동작한다고 생각하시면 됩니다.

CSS에 Loader를 설정할 때 놓치치 말아야 할 부분은 module.css 입니다. 보통 css의 클래스 이름이 겹칠 경우, 원하는 스타일링이 되지 않는 점을 보완하기 위해 일부 라이브러리 들은 독자적인 module.css를 포함합니다. 그래서 이런 부분에 에러를 놓치지 않기 위해 module.css를 고려하여 Loader를 매핑해주어야 합니다. (처음 에러를 마주했을 때 이게 뭐지 했던 기억이 있네요.. ㅎㅎ)

다양한 Loader들

복잡한 loader를 사용하지 않고 간단하게 몇 가지만 사용할 수 있다면 참 좋겠지만.. 개발을 하다보면 절대 그럴 수 없는 사실에 막막해지게 됩니다. 그래서 제가 구성한 환경에서 사용한 다양한 Loader를 공유하겠습니다. 2021년, Webpack 5를 기준으로 하고 있으니 혹시 더 좋은 Loader가 생긴다면 댓글로 공유 부탁드립니다.

module: [
	rules: [
		{
			test: /\.tsx?$/,
			use: 'ts-loader',
			include: paths.src,
			exclude: paths.NODE_MODULES
		},
		{
			test: /\.(eot|woff|woff2|ttf|svg|png|jpe?g)$/,
			use: 'url-loader?limit=10000&name=[name]-[hash].[ext]'
		},
		{
			test: /\.ico$/,
			use: 'file-loader?name=[name].[ext]',
			exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/, paths.NODE_MODULES]
		}
    ]
]

정리

저의 Webpack 환경은 위 Loader들로 세팅되어 있습니다. 아직까지는 크게 컴파일에 문제가 되는 점은 발생하지 않았지만 만약 postcss 등 저의 환경과 다른 개발을 사용하게 된다면 적당한 Loader를 찾아 매핑해주면 됩니다.

이렇게 Webpack이 Bundle 과정에서 파일을 읽기 위해 사용하는 여러 Loader에 대해서 알아보았습니다. 다음 글에서는 Loader와 함께 동작하는 Plugin에 작성해보도록 하겠습니다.

profile
배우는 것을 좋아하는 FE 주니어 개발자입니다

0개의 댓글