devdubby
내가 배운것들 끄적끄적✏️
devdubby
전체 방문자
오늘
어제

티스토리

  • 전체보기 (18)
    • Frontend (11)
    • 커리어 (2)
    • TIL (0)
    • 일상&생각 (3)
    • 서버 (0)
    • 글또 (1)
    • 회고 (0)

태그

  • 개발블로그
  • 모듈시스템
  • monorepo
  • frontend
  • VirtualDom
  • webpack
  • 백엔드
  • 웹 성능 지표
  • react
  • 회고
  • yarn workspace
  • next.js
  • reactQuery
  • 유데미
  • TDD
  • yarn berry
  • state of css
  • 프론트엔드 세미나
  • udemy
  • 글또
  • 모노레포
  • 웹 성능 최적화
  • spring boot
  • Lighthouse
  • til
  • React Query
  • TanstackQuery
  • 2022년 회고
  • 프론트엔드 기술 세미나
  • SSR

최근 글

블로그 메뉴

  • 홈
  • 태그
  • 방명록
hELLO · Designed By 정상우.
devdubby

내가 배운것들 끄적끄적✏️

모듈 시스템의 역사와 모듈 번들러 알아보기
Frontend

모듈 시스템의 역사와 모듈 번들러 알아보기

2023. 3. 12. 22:29

 

Javascript 개발을 하면서 번들러는 빼놓을 수 없는 도구 중 하나이다. 현재 가장 많이 쓰고있는 Webpack부터 Rollup, Parcel, 그리고 최근 급부상중인 Vite, webpack보다 10배(?) 빠르다는 Turbopack까지 현재 다양한 도구들이 사용되고 있다.

나 또한 저 도구들 중 써본것도 있고, 안써본것이 더 많은데 이 글을 통해 먼저 모듈시스템, 모듈 번들러가 등장하게 된 배경, Webpack에 대해 조사한 장단점에 대해 정리해보려고 한다.

 

출처 : https://2022.stateofjs.com/ko-KR/libraries/build-tools/

 

먼저 들어가기에 앞서, 이러한 Bundling tool 들이 왜 필요하게 되었는지 Javascript 모듈 시스템에 대한 배경지식을 쌓고 넘어가면 좋을 것 같다. 과거에는 스크립트를 직접 HTML 파일에 삽입하는 방식으로 개발했다. 이러한 방식은 코드의 모듈화와 의존성 관리가 어려웠다. 모듈간에 변수가 겹쳐 컨플릭트가 발생할 수도 있고, 이 때문에 어떤 모듈을 먼저 로드해야 하는지 로드 순서에도 신경을 써야했다.

그런데 2008년 브라우저 외부에서도 Javascript를 실행시킬 수 있는 Google의 V8 엔진이 공개되면서 모듈화에 대한 필요성이 부각되고 이 덕분에 등장하게 된 대표적인 모듈 시스템이 바로 CommonJS와 AMD 이다.

 

 

CommonJS vs AMD

CommonJS는 이름에서도 Common을 볼 수 있듯이 Javascript를 브라우저 한정이 아닌 서버사이드 애플리케이션이나 데스크톱 애플리케이션에서도 사용하려고 하는 모듈 시스템이다.

CommonJS는 require()를 통해 모듈을 로드하고 exports 객체를 통해 내보내는 방식을 활용한다. 그리고 모듈을 파일로 구분하기 때문에 모듈 관리가 용이하다는 특징이 있다. 그러나 동기적으로 모듈을 로드하기 때문에 브라우저와는 맞지 않는다.

 

AMD(Asyncronouse Module Define)도 마찬가지로 이름에서 알 수 있듯이 비동기를 지원하고 이 덕분에 브라우저에서 모듈을 로드하고 관리할 수 있는 모듈 시스템이다. AMD는 define이라는 구문을 사용하여 모듈을 정의하는데, 이 때문에 define 구문이 장황해지고 전달하는 인자가 많으면 가독성이 떨어질 수 있다. 

 

CommonJS와 AMD에 대한 더 자세한 내용은 https://d2.naver.com/helloworld/12864에서 확인할 수 있다.

 

이후에는 근본적인 문제를 해결하고 Javascript 언어 자체에서 모듈 시스템을 지원하고자 ECMAScript 6 에서 ES Module 이라고 불리는 표준 모듈 시스템이 나오게 되었다. 이 방식은 현재 우리가 개발하면서 흔히 사용하는 import/export 구문을 사용한다. ES Module은 브라우저에서 지원되고 덕분에 <script type="module"> 처럼 작성하여 모듈을 불러올 수 있게 되었다.

 

이 모듈 시스템들이 궁극적으로 지향하는 바는 무엇이였을까? 바로 스코프가 구분되는 모듈을 만들기 위함이라고 생각한다. 그래서 모듈들의 관리가 용이하고 온전히 개발에만 집중할 수 있도록 하기 위함이 아니였을까.

 

웹 생태계가 발전하고 애플리케이션이 더 복잡해짐에 따라 처리해야 하는 Javascript 모듈의 개수도 극적으로 증가하게 되었다. 대규모 프로젝트에서는 수천 개의 모듈이 존재 한다고도 한다. 이러한 모듈 하나하나를 직접 관리한다면 모듈 로드 순서를 파악해야 한다거나 의존성 파악에 어려움이 있어 모듈간에 충돌이 발생할수도 있고, 개발 생산성이 현저하게 떨어지게 된다. 이에 따라 이를 도와주는 도구들이 필요했고 모듈 번들러들이 등장하기 시작했다. 그 중 Webpack에 대해 알아보자.

 

 

Webpack

출처: https://webpack.kr/

현재 가장 많이 쓰이는 번들러 중 하나인만큼 생태계가 풍부하고 안전성이 뛰어난 모듈 번들러이다. https://webpack.kr/concepts/ 에 따르면 entry, output, loader, plugin 등의 핵심 개념을 설명하고 있는데 이를 통해 구성요소들을 조합하여 원하는 번들링 결과물을 생성할 수 있다.

 

Entry(엔트리)

엔트리는 웹 애플리케이션에서 시작하는 지점이다. 엔트리 파일은 모든 종속성의 시작점이며, 이를 기반으로 모든 종속성을 찾아 하나의 번들 파일로 묶는다. 엔트리는 일반적으로 자바스크립트 파일의 경로를 나타내며, 여러개의 엔트리를 지정할 수도 있다.

 

Output(출력)

output은 번들링 된 파일의 경로 및 이름을 지정한다. 엔트리로부터 시작하여 모든 모듈 및 종속성을 가져와 하나의 파일로 번들링한 다음, output 경로에 번들 파일을 저장한다. output 경로는 일반적으로 프로젝트의 dist 폴더와 같은 빌드 디렉토리로 설정해주면 된다.

 

Loaders(로더)

로더는 다양한 유형의 파일을 웹 애플리케이션에서 사용할 수 있는 모듈로 변환한다. 로더는 일반적으로 test, use 및 include/exclude 속성을 사용하여 구성한다. test 속성은 로더가 처리할 파일의 유형을 정의하며, use 속성은 해당 파일을 처리하는데 사용될 로더를 지정한다. include/exclude 속성은 파일 경로의 패턴을 나타내어 로더가 처리할 파일을 필터링한다. 로더는 위에서 말했던바와 같이 CSS, 이미지, 폰트 등 다양한 파일 형식을 처리할 수 있다.

 

Plugins(플러그인)

플러그인은 번들링된 자원을 처리하고 추가로 최적화하기 위해 사용된다. 로더와 달리, 플러그인은 보다 광범위한 작업을 수행하며, 로더에서 처리할 수 없는 작업을 수행할 수도 있다. 예를 들어, HTMLWebpackPlugin은 HTML 파일을 생성하고, UglifyJSPlugin은 번들링된 자바스크립트 코드를 압축하는데 사용된다.

 

 

장점

다양한 로더와 플러그인 지원

Webpack의 Loader와 플러그인을 이용해 CSS나 이미지 같은 에셋들을 Javascript 코드로 변환할 수 있도록 해주고 번들을 최적화하거나 에셋들을 관리할 수 있다는 것이 편리하게 모듈을 관리할 수 있다는 장점으로 볼 수 있다.

 

코드 스플리팅으로 인한 초기 로딩 속도 개선

Webpack은 코드 스플리팅을 지원한다. 이 덕분에 코드를 여러 개의 chunk로 분할하고 필요한 시점에 필요한 모듈을 적절히 로딩할 수 있다. 덕분에 초기 로딩 속도를 빠르게 해줄 수 있다.

 

dev-server

Webpack은 webpack-dev-server 플러그인을 통해 개발 서버를 지원한다. 이를 통해 개발 중 코드가 변경되면 빌드하여 브라우저를 자동으로 새로고침 해주는 Live reloading이나 새로고침 대신 수정된 모듈만 빌드하여 해당 모듈만 교체하는 HMR(Hot Module Replacement) 기능을 사용할 수 있다.

 

단점

러닝커브가 높다

Webpack은 다양한 로더와 플러그인을 사용하고 복잡한 configuration으로 추가 작업을 필요로 해서 러닝커브를 높일 수 있다. 또한 복잡한 문서가 진입장벽을 높여주는 것도 한 몫 한다. 

 

느린 속도

Webpack은 특히 개발모드에서 처리 속도가 느려 모듈의 의존성이 복잡하거나 큰 프로젝트일수록 느려질 수 있다.

 

번들 파일 크기가 커질 수 있다

Webpack은 모든 의존성을 하나의 파일에 번들링하므로, 번들 파일의 크기가 커질 수 있다. 그래서 이를 해결하기 위해서 코드 스플리팅 등의 기능을 사용해야 한다.

 

 

 

Rollup

출처:&nbsp;https://rollupjs.org/

 

Rollup의 특징은 ES module을 사용하여 번들파일을 생성한다는 것이다. 덕분에 사용되지 않는 코드는 제거되고 번들 크기를 줄여줘 성능을 개선할 수 있다. Webpack은 트리쉐이킹을 적용하기 위해 sideEffects 속성, mode 속성 등 다른 옵션을 바꿔줘야 하지만 Rollup은 기본적으로 트리쉐이킹을 지원한다.

 

 

장점

번들링 속도

Rollup은 사용되지 않는 코드를 제거하기 때문에, 번들링할 코드가 줄어들어 더 빠르게 번들링할 수 있다.

 

ES6 모듈 시스템 지원으로 인한 가독성, 유지보수성 향상

Rollup은 ES6 모듈 시스템을 지원하여, 의존성 관리가 용이하며, 정적 바인딩으로 인해 가독성과 유지보수성이 높아진다.

 

CLI 도구 제공

Rollup은 CLI 도구를 제공하여, 터미널에서 간단하게 Rollup을 실행할 수 있다.

참고 : https://rollupjs.org/command-line-interface/

 

 

단점

HMR(Hot Module Replacement) ❌

Rollup은 HMR을 지원하지 않는다. Rollup은 라이브러리나 컴포넌트를 번들링 하는데에 주로 사용하는데, 이는 곧 런타임 환경에서 동작하는 코드를 생성한다. HMR이 런타임 환경에서 코드를 동적으로 변경하고 적용하는 개입을 할 수는 없다.

 

다양한 로더 지원 부족

Rollup은 Webpack과 달리 로더의 지원이 부족하다. 따라서, 이미지나 폰트 등의 파일을 번들링하는 경우에는 별도의 로더를 설치해야 한다.

 

웹 애플리케이션 전체 번들링에 적합하지 않음

Rollup은 주로 라이브러리와 컴포넌트를 번들링하는데 사용되며, Webpack과 같은 다른 모듈 번들러보다는 웹 애플리케이션 전체를 번들링하는데는 적합하지 않다. 단점(?)이라고 하기에는 뭐하고 개발 용도에 따라 적절히 선택하면 될 것 같다.

 

 

 

Parcel

출처: https://ko.parceljs.org/

Webpack과 다르게 Parcel은 zero-configuration을 지향하여 간단한 사용법으로 인기를 얻었다. Parcel은 ES6, CommonJS 모듈 모두에서 Tree Shaking을 지원하고, 파일 시스템 캐시를 지원하기 때문에 빠른 리빌드를 할 수 있도록 해준다. Parcel의 장단점은 다음과 같다.

 

 

장점

Zero-config로 인한 쉬운 사용성

Parcel은 zero-config을 지향하여, 별도의 설정 파일 작성 없이도 쉽게 사용할 수 있다. 

 

쉬운 코드 스플리팅

zero-config덕분에 어떠한 설정 없이도 코드 스플리팅을 할 수 있다. Parcel은 동적 import() 문을 사용하기 때문에 필요한 코드만 로드하고 초기 로딩속도를 쉽게 개선할 수 있다.

 

HMR 지원

Rollup과는 다르게 HMR을 지원하여 코드가 변경되면 브라우저가 이를 감지하고 수정 내용을 즉시 반영할 수 있다. 이를 통해 더 빠르게 확인하고 디버깅할 수 있다.

 

자동 변환

Parcel은 많은 트랜스파일러를 내장 지원하고 있기 때문에, 모듈 안의 설정파일(.babelrc, postcssrc, 심지어 node_modules 까지도) 을 사용하는 코드를 자동으로 변환한다.

 

 

단점

비교적 덜된 문서 문서화

Parcel은 다른 두 모듈 번들러들에 비해 가장 최신에 출시되었다. 때문에 비교적 좁은 생태계와 커뮤니티가 작아 참고할만한 자료가 부족할 수 있다. 사소한 버그를 해결하기 위해 이곳저곳 찾아봐야 할 수도...

 

낮은 안정성

아직까지는 떨어지는 안정성으로 Github 레포지토리 Issue에서 각종 이슈를 발견할 수 있고 이를 해결하기 위해 조금 골치 아픈 상황이 생길수도 있을것 같다.

 

 

 

참고

  1. https://d2.naver.com/helloworld/12864
  2. https://wormwlrm.github.io/2020/08/12/History-of-JavaScript-Modules-and-Bundlers.html#webpack
  3. https://webpack.js.org/
  4. https://rollupjs.org/
  5. https://ko.parceljs.org/

 

저작자표시 (새창열림)

'Frontend' 카테고리의 다른 글

나는 웹 성능 지표를 잘 알고 있었나?  (0) 2023.06.04
그래서 모노레포가 뭐지? (feat. yarn workspace)  (0) 2023.04.09
CSS 스펙 탐구하기  (0) 2023.03.08
React에서 babel의 동작원리 & React와 Virtual DOM 이해하기  (0) 2022.12.13
React Query는 어떤 기술일까?  (0) 2022.12.11
    'Frontend' 카테고리의 다른 글
    • 나는 웹 성능 지표를 잘 알고 있었나?
    • 그래서 모노레포가 뭐지? (feat. yarn workspace)
    • CSS 스펙 탐구하기
    • React에서 babel의 동작원리 & React와 Virtual DOM 이해하기
    devdubby
    devdubby

    티스토리툴바