이번 포스팅에서는 Javacript의 모듈과 모듈 번들러의 탄생 및 핵심 기능, 마지막으로 Rollup.js 번들러에 대해 살펴보려고 한다.
모듈
Rollup에 대해 이야기해보기 전에 모듈과 번들러에 대해 간략히 살펴보고 넘어가자. 프론트엔드 진영에서 개발을 하게 되면 항상 등장하는 개념인데, 용어 그대로 모듈(분리된 코드 및 조각)들을 묶어주는 역할을 한다.
건축,부동산 및 선박에 관심이 있는 사람이라면 '모듈 공법'에 대해 들어본 적도 있을것이다. 빌딩 혹은 선박을 한군데서 시공하는것이 아닌, 여러 부분을 모듈 형식으로 쪼갠 후 조립해 효율성을 극대화 하는 공법이다. 개발관점에서 보면 여러 PR을 통해 머지 후 어플리케이션을 완성하는 형태라고 보면 비슷할것 같다 ?
규모가 큰 프로그램을 개발할 때 모듈의 개념은 빠질 수가 없었고, 웹 어플리케이션 역시 예외는 아니었다. 관심사의 분리는 늘 필요하고, 이를 실현하기 제일 쉬운 방법은 파일을 쪼개는 것이었다.
하지만 단순히 파일을 쪼개서 여러 script 태그로 로드시킬때에도 문제점은 존재했는데, 가장 대표적으로 스코프가 오염되거나 네임스페이스 충돌문제가 생길수있다 . 코드를 통해 예시를 살펴보자.
// app.js
var num = 10;
function getNum() {
console.log(num);
}
// main.js
var num = 20;
function getNum() {
console.log(num);
}
<!-- index.html -->
<html>
<head></head>
<body>
<script src="./app.js"></script>
<script src="./main.js"></script>
<script>
alert(num);
getNuem();
</script>
</body>
</html>
app.js에서 선언한 num 변수는 main.js에서 다시 선언하고 20을 할당했기 때문에 기대와는 달리 10이 아닌 20이 출력됨을 확인할 수 있다. 이 외에도 의존성이 존재하는 코드 사이에 순서를 보장하기 힘든 문제도 남아있다.
결국 개발자들은 모듈을 정의하는 방법을 고안해 CommonJS(CJS), AMD, UMD등이 생겨났고 ES6에 이르러 지금 가장 익숙하게 사용중인 모듈이 등장했다.
번들과 모듈 번들러
모듈이 등장함에 따라 이전보다 나은 상황에서 모듈 단위로 개발이 가능해졌다. 하지만 이번에는 다른 문제가 등장했으니, 여러 모듈 단위로 개발하다 보니 파일 하나하나마다 HTTP요청을 통해 가져와야 하는것. 웹 사이트의 로딩 속도를 줄이기 위해 서버로 요청하는 횟수를 최소화할 필요가 대두되었다. 이에 따라 여러 모듈들을 단일 Javascript 파일로 묶는 모듈 번들러가 탄생하게 되었다.
모듈 번들러라고 하면 뭔가 거창해보이지만 사실 우리는 실생활에서 번들 이라는 단어와 생소하지 않다. 당장 마트에만 가봐도 여러개의 과자들을 한 묶음으로 파는것을 확인할 수 있는데 이를 번들제품이라고 한다.
예전 악명높은 허니버터칩 대란 때 여러 과자들과 함께 허니버터칩을 끼워 팔았던 것 또한 번들이라 표현할 수 있겠다. 게임의 경우도 요즘에야 스팀을 통해 단일게임 위주로 구매할 수 있는데, 예전에 패키지 형식으로 팔때는 여러 게임을 묶어 번들형식으로 팔기도 했었다.
초기 번들러는 의존성 있는 Javascript 모듈들을 하나(혹은 여러개)로 묶어주기 위해 사용되었으나 React, Babel 등 다양한 도구가 등장하면서 웹 개발의 중추적인 역할을 담당하기 시작하였다. 대표적인 기능들을 간단하게 살펴보면 다음과 같다.
번들링
번들러의 가장 핵심 기능. 복잡한 의존성을 가진 JS, CSS 등의 파일들을 하나(혹은 여러개)의 파일로 묶어준다. 단일 번들 파일로 만듦으로써 HTTP 요청을 최소화한다.
트랜스파일
모든 브라우저가 최신 ES 문법을 지원하진 않는다. 구형 브라우저에서 ES6 -> ES5 혹은 리액트의 JSX -> JS로 변환 등을 도와준다.
Hot Mudule Replacement (HMR)
수정된 부분 및 관련된 코드만 교체해 페이지를 새로고침 하지 않아도 코드의 변화를 즉각 적용시켜준다.
코드 스플리팅
SPA 특성상 하나의 HTML파일에서 여러 페이지들을 로드하다보니 물리적으로 번들용량이 커지게 된다. 번들을 나눠야 할 필요성에 의해 Dynamic Import 및 React Lazy등으로 하나의 큰 번들 덩어리를 쪼갠다.
위 4가지 기능 외에도 번들 모듈러의 기능들이 추가적으로 존재하지만, 핵심 기능들만 우선적으로 요약해보았다. 번들링을 도와주는 모듈 번들러는 종류가 굉장히 많은데 1대장 Webpack을 필두로 Rollup, Parcel, Vite 최근에는 Next.js에 기본탑재된 Turbopack까지 가히 춘추전국시대라고 표현할 수 있겠다.
그중에 Rollup.js 번들러에 대해 소개해보려고 한다. 사내에서 디자인 시스템을 개발하면서 접하게 되었는데, 여러 레퍼런스를 살펴보니 덩치가 큰 어플리케이션보다 라이브러리 혹은 패키지 개발에 사용되는 듯 싶다.
Rollup.js
Rollup을 한마디로 표현하자면 경량화와 번들 최적화를 중점에 둔 ES Module 번들러라고 할 수 있다. 웹팩 이후에 등장한 모듈 번들러로서 당시 웹팩에는 없던 ESM을 지원하며 의존성 파악이 명확하여 사용하지 않는 코드를 제거하는 Tree-shaking을 더 강력하게 지원하며 각광을 받았었다.
물론 이후의 웹팩에서 ESM을 지원하기 시작하고 ESBuild, Vite, Turbopack처럼 각광받는 차세대 번들러가 등장하긴 했지만 간단한 설정과 경량화, 트리쉐이킹 등은 여전히 매력적이다.
Rollup의 특징들을 간단히 살펴보면 다음과 같다.
- ES Module 형태의 번들을 제공 (웹팩도 버전 2부터 공식 지원)
- 복잡한 웹팩보다 설정이 쉽다
- 여러 플러그인 제공
- 강력한 트리 쉐이킹 지원
- 번들 용량 경량화
오픈소스로 유명한 채널톡의 디자인 시스템 bezier-react의 코드를 살펴보면 라이브러리 대부분을 Rollup을 활용해 번들링 하고 있음을 확인할 수 있다.
https://github.com/channel-io/bezier-react/tree/main/packages/bezier-react
마치며
최근 많은 IT 기업에서 웹팩의 Module Federation을 도입하면서 마이크로 프론트엔드를 도입하고 있다. 아니, 이미 2020년에 릴리즈된 Webpack 5에 추가되었으니 벌써 많은곳에서 사용할지도 모르겠다.
Module Federation의 도입기에 대해 읽으며 애초에 Webpack에 대해 잘 알고 있는지, 정작 FE의 핵심이라 할 수 있는 모듈 번들러에 대해서는 제대로 이해하고 있는지 의문이 들어 포스팅으로 정리해보았다. 마침 회사에서 Rollup을 도입해 번들러에 대해 레퍼런스도 조금 찾아보았고.
글로 정리하다 보니 번들러의 탄생과 맥락에 대해 조금이나마 살펴볼 수 있었다. 다음 포스팅에서는 Rollup 기반의 디자인시스템 개발환경을 구성해보겠다.
'React' 카테고리의 다른 글
Micro Frontend를 위한 Module Federation (0) | 2024.06.10 |
---|---|
직장인들의 IT 개발모임 직띵(Zicdding) FE 스터디 발표 후기 (0) | 2024.05.30 |
[Next.js] Turborepo의 캐싱 과정과 build시 적용되지 않았던 이슈 (0) | 2024.05.21 |
AWSKRUG 프론트엔드 1월 Meepup 후기 (Cognito + Next-Auth) (1) | 2024.01.16 |
[Storybook] Storybook MDX 마크다운으로 템플릿 작성하기 (0) | 2023.12.29 |