그래서 webpack이 뭔데?

­가은·2023년 10월 25일
21
post-thumbnail

"webpack이 뭐야?"

누군가 이렇게 묻는다면 자신있게 답을 이야기할 수 있을까?

난.. 없다...
저 질문에 대답할 자신이 없다면 나와 함께 webpack을 공부해보도록 하자.

먼저 난 꽤나 많은 프로젝트를 시작해봤음에도 불구하고 (끝내지 못한 것도 많지만...) webpack에 대해 아는게 거의 없다.
대충 Create React App을 사용하면 모든게 해결되었고, 그래서 크게 신경쓰지 않았다.
vite를 사용할 때도 어떤 점 때문에 사용하는건지 제대로 이해하지 못했던 것 같다.

그래서 이제라도 webpack이 무엇인지에 대해 학습해보려 한다.

가보자고..




🍞 목표

webpack이 어떤 역할을 하는지 학습하고, 설정 방법을 알아보자.


🍞 webpack이란?

먼저 공식문서를 살펴보자.
webpack 설명의 가장 첫 문단은 다음과 같다.

webpack은 모던 JavaScript 애플리케이션을 위한 정적 모듈 번들러입니다. webpack이 애플리케이션을 처리할 때, 내부적으로는 프로젝트에 필요한 모든 모듈을 매핑하고 하나 이상의 번들을 생성하는 디펜던시 그래프를 만듭니다.

일단은 정적 모듈 번들러라고 한다.
먼저 모듈이 무엇인지 알아보자.

🍞 모듈

모듈러 프로그래밍 (moduler programming)은 기능에 따라 애플리케이션 코드를 여러 단위 (unit)로 분해하는 소프트웨어 설계 기술이다.
여기서 각 단위를 모듈이라고 한다.

이렇게 말하면 감이 잘 오지 않을 수 있는데, 간단히 말하면 파일 하나가 모듈이라고 생각하면 된다.
각 파일은 다른 모듈에서 참조하거나 종속성을 가질 수 있는 모듈이다.
하나의 애플리케이션은 수많은 파일, 혹은 수많은 모듈로 구성되는 것이다.

굳이 코드를 모듈화하는 이유는 무엇일까?
코드의 관리, 테스트, 재사용이 용이하기 때문이다.
한 파일에 코드를 모두 집어넣는다면 가독성이 떨어지고, 관리도 힘들어질 것이다.
또 모듈로 분리한다면 각 모듈의 역할이 명확해지고, 해당 역할이 필요할 때 import해서 사용할 수 있다.

🍞 모듈 번들러

모듈 번들러 (module bundler)는 JS 모듈을 브라우저에서 실행할 수 있는 단일 파일로 묶는 역할을 한다.

출처: freeCodeCamp - Let’s learn how module bundlers work and then write one ourselves

모듈 번들러를 사용하지 않는다면, 우리는 직접 모듈 간의 의존성이나 파일 로딩같은 것들을 수동으로 처리해야 한다.

모듈 번들러는 두 가지 단계를 거쳐 작동하게 된다.

1. 의존성 해결

의존성 그래프 매핑 (Mapping a Dependency Graph) 단계를 거친다.
모든 파일의 관계 맵을 생성하는 것이다.

이렇게 말하면 무슨 소리인지 이해가 잘 안될 것이다.

간단히 말하면 파일 간 의존성을 파악하는 것이다.
먼저 애플리케이션의 시작점, 즉 entry file을 분석하여 해당 파일이 의존하는 모듈들을 파악한다.
그리고 이 파일이 의존하는 모듈들의 의존성을 확인하기 위해 이 모듈들을 탐색한다.
번들러는 이 과정에서 각 파일에 고유한 식별자 (id)를 할당한다.
모든 작업이 끝나면 번들러는 모든 파일 간 관계를 나타내는 의존성 그래프를 생성한다.

한마디로 설명하자면, 번들러는 entry file을 시작으로 해당 파일이 의존하는 모듈들을 파악하고, 이를 통해 모든 파일들의 의존성 관계를 추적하여 의존성 그래프를 생성한다.

출처: https://github.com/pahen/madge

브라우저가 함수를 요청할 때, 모듈에서 함수를 검색하는데 의존성 순서가 필수적이기 때문에 위와 같은 의존성 그래프가 필요하다.

2. 포장

한국어로 번역하니 뭔가 어색한데, packing 단계이다.
이 단계에서는 의존성 해결 단계에서 받아온 결과를 기반으로 브라우저가 처리할 수 있는 정적 자산 (static assets)을 제공한다.

출처: https://webpack.kr/

자세히 설명하자면 아래와 같다.

  • 코드 파일 통합

    • 의존성 그래프를 기반으로 코드 파일들을 하나로 통합한다.
  • 각 모듈에 함수와 module.exports 객체 주입

    • 각 모듈이 독립적으로 작동할 수 있도록 한다.
    • 다른 모듈에서 사용할 수 있도록 한다.
  • 단일 실행 가능한 번들 생성

    • 위의 과정들이 끝나면, 모든 코드 파일과 의존성을 하나의 파일로 만들어낸다.
    • 이 파일, 즉 이 번들은 브라우저에서 직접 로드하고 실행할 수 있다.

한마디로 설명하자면, packing 단계는 여러 개의 코드 파일과 의존성을 브라우저에서 실행할 수 있는 단일 파일로 만드는 과정이다.


여기서 잠깐 다시 공식문서의 설명을 읽어보자.

webpack은 모던 JavaScript 애플리케이션을 위한 정적 모듈 번들러입니다. webpack이 애플리케이션을 처리할 때, 내부적으로는 프로젝트에 필요한 모든 모듈을 매핑하고 하나 이상의 번들을 생성하는 디펜던시 그래프를 만듭니다.

이제 이 부분이 무슨 의미인지 이해가 될 것이다.

하지만 webpack으로 넘어가기 전에, webpack이 정적 모듈 번들러라고 했으므로 정적 모듈 번들러와 동적 모듈 번들러의 차이에 대해서도 간단히만 알아보고 넘어가자.


🍞 정적 모듈 번들러 vs 동적 모듈 번들러

1. 정적 모듈 번들러

  • 빌드 타임에 모든 모듈의 의존성을 해석하여 하나의 파일로 번들링한다.
  • 런타임에 추가적인 파일을 불러올 수 없다.
  • webpack, parcel, rollup 등이 있다.

2. 동적 모듈 번들러

  • 런타임에 필요한 모듈을 동적으로 로딩하고 해석한다.
  • 런타임에 추가적인 모듈을 필요로 할 때 유용하다.
  • systemJS 등이 있다.

이제 정적 모듈 번들러가 어떤 역할을 하고, webpack이 어떤 것인지에 대해 감을 잡았을 것이다.
본격적으로 webpack 설정 방법에 대해 알아보자!


🍞 Entry

entry point는 webpack이 내부의 의존성 그래프를 생성하기 위해 사용하는 모듈이다.
의존성 해결 부분에서 아래와 같이 설명했었다.

간단히 말하자면 파일들 간 의존성을 파악하는 것이다.
먼저 애플리케이션의 시작점, 즉 entry file을 분석하여 해당 파일이 의존하는 모듈들을 파악한다.
그리고 이 파일이 의존하는 모듈들의 의존성을 확인하기 위해 이 모듈들을 탐색한다.

여기 언급된 entry file을 설정해주는 것이다.
기본값은 ./src/index.js이다.
entry 속성을 설정해 다른 entry point를 지정할 수 있다.

// webpack.config.js

module.exports = {
  entry: './path/to/my/entry/file.js',
};

🍞 Output

output 속성은 생성된 번들을 내보낼 위치이 파일의 이름을 지정하는 방법을 webpack에 알려주는 역할을 한다.
기본 출력 파일은 ./dist/main.js로 , 생성된 기타 파일의 경우에는 ./dist 폴더로 설정된다.

// webpack.config.js

const path = require('path'); // 파일 경로를 지정하기 위해 사용되는 cord Node.js 모듈

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'), // 번들을 내보낼 위치
    filename: 'my-first-webpack.bundle.js', // 번들의 이름
  },
};

🍞 Loaders

webpack은 기본적으로 JS와 JSON 파일만 이해한다.
하지만 loader를 사용하면 다른 유형의 파일을 처리하고, 유효한 모듈로 변환하여 사용할 수 있다.

// webpack.config.js

const path = require('path'); 

module.exports = {
  module: {
    rules: [{ 
      test: /\.txt$/, // 변환이 필요한 파일을 식별
      use: 'raw-loader', // 변환을 수행하는데 사용되는 loader를 가리킴
      
      // webpack 컴파일러가 .txt 파일로 확인되는 경로를 발견하면, 
      // 번들에 추가하기 전에 raw-loader를 사용하여 변환
    }],
  },
};

🍞 Plugins

plugin을 활용하여 번들을 최적화하고, 에셋을 관리하고, 환경 변수 주입과 같은 광범위한 작업을 수행할 수 있다.

// webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // plugin 요청
const webpack = require('webpack'); // 내장 plugin에 접근하는 데 사용

module.exports = {
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
  
  // plugin을 여러 번 사용할 수 있으므로, new 연산자로 HtmlWebpackPlugin을 호출하여 plugin의 인스턴스 만들기
};

🍞 Mode

mode를 설정하면 webpack에 내장된 환경별 최적화를 활성화할 수 있다.
development, production, none 중 하나로 설정할 수 있다.

  • development: 개발 모드
  • production: 배포 모드 (기본값)
  • none: 기본 최적화 옵션 설정 해제

모드에 따라 번들링된 파일 크기가 달라진다.
development > none > production 순이다.
production의 경우 webpack 모듈 번들링 과정에서 자체적으로 코드를 최적화하여 용량을 줄인다.

// webpack.config.js

module.exports = {
  mode: 'production',
};

이렇게 webpack이 무엇인지 학습하고, 기본적인 설정방법까지 알아보았다.
이 글의 목적은 webpack이 무엇인지 학습하는 것이었기 때문에, 더 깊은 부분들은 여기서 다루지 않으려 한다.

하지만 이제는 누군가 "webpack이 뭔데?" 라고 물었을 때 조금이라도 대답할 수 있는 사람이 되었길 바란다.




🍞 요약

  • webpack은 정적 모듈 번들러 중 하나
  • 모듈은 기능에 따라 코드를 여러 단위로 분해한 것
  • 모듈 번들러는 JS 모듈을 브라우저에서 실행할 수 있는 단일 파일로 묶음
  • webpack은 Entry, Output, Loaders, Plugins, Mode 등으로 유연하게 설정할 수 있음


참고 자료

4개의 댓글

comment-user-thumbnail
2023년 11월 9일

좋은 글 감사합니다!! 많은 도움이 됐어요 🐧

1개의 답글
comment-user-thumbnail
2023년 11월 9일

많은 도움이 되었어요 👍🏻
글이 정말 잘 읽히네요 글솜씨 부러워요 🥺

1개의 답글