🌱 ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] 번들러(Bundler)
    Front-End/React 2023. 12. 7. 23:34
    🍀 목차
    글의 목적
    CRA(Creat-React-App)
    번들러
    Webpack
    Vite

     

     

    글의 목적

     처음 React 프로젝트를 시작하게 되었을 때, 공식 문서에서는 Create React App을 추천해 줬었다.

     

    (구) React 공식 문서의 추천 툴체인. React에 낯선 사람들에게 CRA를 추천하고 있다.
    현재는 업데이트 되지 않는 https://ko.legacy.reactjs.org/ 의 "새로운 React 앱 만들기" 부분.

     

     React에 아직 익숙지 않은 개발자에게 Create-React-App은 처음부터 React로 만들어진 새로운 애플리케이션을 만드는 가장 편한 방법이었다. 모든 React App을 CRA(Create-React-APP)로 만들어야 하는 줄 알았던 때도 있었다. 시간이 지나며 Webpack, Bundler, Vite 등의 키워드를 마주치는 비율이 높아졌고, 왜 현재는 CRA를 추천하지 않는 사람들이 많은 지 알고 싶어 글을 작성하게 되었다. 글을 통해 번들러(Bundler)에 대한 개념을 대략적으로 이해하는 데 도움이 되고 싶다.

     


    CRA(Creat-React-App)

     

    Create React App의 한 줄 소개.
Set up a modern web app by running one command.
    출처 : https://create-react-app.dev/

     

     CRA는 내부적으로 번들러 Webpack을 사용하여 만들어진 React 애플리케이션 툴 체인(Tool Chain : 개발도구 모음)이다. Create React App 페이지에 작성된 특징은 아래와 같다. 

     

    Less to Learn

     많은 빌드 도구를 배울 필요 없이 즉시 개발에만 집중하는 데 도움을 준다. 배포 시에는 번들은 자동으로 최적화된다.

     

    npx create-react-app my-app
    cd my-app
    npm start

     

    위 커맨드 만으로도 개발자는 React 프로젝트를 시작할 수 있다!

     

     

    Only One Dependency

     애플리케이션은 하나의 빌드 종속성만 필요하다. CRA를 테스트하여 기본 요소가 버전 불일치 없이 원활하게 작동하는지 확인한다. 

     

     

    CRA로 프로젝트를 만들고 시작하면 뜨는 로그들.
    CRA로 프로젝트를 만들고 시작하면 뜨는 로그들.
    CRA로 프로젝트를 만들고 package.json을 확인해보면...
    package.json을 확인해보면...

     

    react-scripts가 자주 보인다. 확인해 보자.

     

    react-scripts는 CRA에서 사용하는 스크립트와 구성이 포함되어 있다.
    CRA에서 사용하는 스크립트와 구성이 포함되어 있다.
    Webpack도 보이고...
    보다보면 Webpack도 보이고...

     

     react-scripts로 설정이나 종속들을 관리하고 있다. 그렇기에 우리는 간단한 명령으로 업그레이드, 유지할 수 있다. 

     

     

    No Lock-In

    고급 구성을 원할 경우 CRA에서 eject함으로써 구성 파일을 직접 편집할 수 있다. 

     

    eject를 해보면... 되돌릴 수 없다는 경고가 뜬다.
    eject를 해보면...경고가?!
    CRA의 jest, webpack등의 설정을 이제 직접 접근 가능하다.
    CRA의 jest, webpack등의 설정을 이제 직접 접근 가능하다.
    모든 것들이 밖으로 추출된다.
    모든 것들이 밖으로 추출된다.

     

     eject를 하게 되면 숨겨져 있던 설정파일, 종속성등의 모든 것이 밖으로 추출된다. 그래서 Webpack, Babel 등 각종 설정에 직접 접근하여 수정이 가능하다. 다만 eject시에는 다시 되돌릴 수 없다. eject를 하게 되면 CRA에서 제공해 줬던 여러 설정들의 유지보수, 의존성 관리(새로운 패키지 설치 시 기존 패키지와의 의존성을 체크)도 개발자가 신경 써야 한다. CRA의 "Only One Dependency"의 장점을 잃을 수도 있는 것이다. 

     

     라이브러리인 React는 처음 시작하기에 혼란스러울 수 있다. 여러 도구를 설치해야 하고, Webpack(의존 파일을 전부 모아 하나의 파일로 만들어줌), Babel(JSX문법은 React만의 문법이기에 JavaScript로 변경해줘야 하는 등의 일을 수행)등 알아야 할 것들이 많다. CRA의 목표는 대부분의 React 사용자에게 새로운 웹앱을 시작하는 가장 좋은 방법을 제공하는 것이었다. 그를 위해 여러 도구를 하나의 패키지로 결합, 합리적인 기본 구성을 선택하여 업데이트해 나갔다.

     

     다만 CRA의 이러한 추상화는 자신만의 구현을 원하거나 내부 수행 작업을 이해하는 데 어려웠다. 나도 처음에는 CRA만이 React 프로젝트를 실행할 수 있는 방법이라 생각했었다. 하지만 react-scripts만이 앱을 실행하는 유일한 종속성이 아니라 Babel, Webpack 등의 다른 기술도 주요 종속성임을 알아야 할 때가 있다. Babel, Webpack 등의 설정을 개발자가 직접 하지 않아도 된다는 장점이 어느 상황에서는 단점이 될 수도 있는 것이다.

     

     시간이 지남에 따라 경쟁 도구들이 등장하였고, CRA의 장점보다 더 큰 장점을 가진 도구들도 나오게 되었다. Vite의 경우에는 CRA처럼 간단한 명령으로 프로젝트를 설정할 수 있고, 속도도 매우 빠르다. CRA가 코드 변경 후 전체 코드를 다시 번들링 한다면 Vite는 변경된 파일만 번들링 하여 빌드 프로세스를 빠르게 만든 것이다. 

    빌드(Build)
     브라우저는 HTML, CSS, JS를 해석할 수 있다.
    React의 JSX, TSX 등은 해석할 수 없기에 코드들이 빌드과정을 거쳐 브라우저가 해석할 수 있는 파일로 변환되어 담기게 된다. 빌드 과정을 거친 내용물을 서버에 올려 배포할 수 있다. 

     

    빌드는 npm run build로 할 수 있다.
    빌드는 npm run build로 할 수 있다.
    빌드 후의 결과물 사진
    결과물.

     

     CRA는 좋은 개발 경험을 제공했으나 프로젝트마다 효율적인 React 설정은 다를 수 있고, 그 설정을 위해서는 eject 해야 했다. 이러한 eject는 CRA의 장점을 무효로 하기도 했다. 

     React는 라이브러리임으로 라우팅, 데이터 패칭(서버로부터 데이터를 가져오는 기능)에 대한 틀을 제공하지 않는다. CRA 또한 마찬가지이다. CRA에서 지적당하고 있는 기능들은 서로 연결되어 있다(번들링, 라우팅, 데이터 패칭과 사용자 경험이나 Server Side Rendering 등). CRA는 기본적으로 작성된 변경 없는 코드들이 존재하고, 이러한 보일러 플레이트(Boiler Plate)는 프레임워크를 대체해서는 안 된다. 프레임워크는 프로젝트에 대한 전반적인 표준화와 전체 구조를 논한다면 보일러 플레이트는 초기 설정과 시작 부분에 필요한 코드를 제공하는 것이다. 그렇기에 CRA는 이러한 문제를 해결할 수 없다. 

     

      'Create React App 권장을 Vite로 대체' PR에 대한 Dan Adramov의 답변 번역본을 읽고 정말 좋은 PR과 답변이라고 생각했다. CRA의 등장 배경부터 목적, 솔루션, 그 솔루션에 대한 견해까지 React 개발자의 여러 넓은 고민들을 읽을 수 있었다. 결과적으로 현재의 React는 권장 프레임워크 목록을 제시하고 CRA 같은 전통적인 접근 방식은 마지막 옵션으로 두고 있다. 

     

     

    새로운 React 프로젝트를 시작함에 프레임워크를 먼저 추천하고 있다.
    출처 : https://ko.react.dev/learn/start-a-new-react-project

     

    프레임워크 없이 React를 사용할 수 있나요?
     당연히 프레임워크 없이도 React를 사용할 수 있습니다.
    하지만 새로운 앱이나 사이트를 React로 완전히 작성한다면 프레임워크를 사용하는 것을 권장합니다.
    라우터, 데이터 통신 기능이 처음에는 필요하지 않더라도 나중에 추가하고 싶어질 수 있습니다.
    이 페이지에 있는 React 프레임워크는 사용자의 추가적인 노력 없이 이러한 문제를 기본적으로 해결하고 있습니다. 

    인용 : https://ko.react.dev/learn/start-a-new-react-project#can-i-use-react-without-a-framework

     

     

    번들러

     

     묶음을 뜻하는 단어 Bundle은 코드, 모듈의 종속성을 하나로 합친 결과물 정도로 이해할 수 있다. 웹 애플리케이션의 규모가 점차 커지게 되고 그로 인해 기능의 분리가 필요하게 되었다. 이 문제를 해결하기 위해 모듈(module)은 기능을 분리시킴에 따라 유지보수성과 재사용성을 높였으나...

     수많은 사용자가 이용하는 웹 사이트에서는 몇 천 개의 파일이 요청-응답을 통해 네트워크에 큰 부담을 주게 되었다. 파일들끼리 의존성도 있을 경우 수동으로 오류를 고쳐줘야 했다. 그렇게 네트워크 비용은 줄이며 모듈을 정의하는 방법을 고민하며 번들러(Bundler)들이 탄생되었다. 

     

    번들링(Bundling)을 통해 번들(Bundle)을 만들어주는 번들러(Bundler)들은 선택적으로 아래의 기능들을 담고 있다(라임이 엄청나다).

     

    1. 번들링(Bundlinig) : 복잡한 의존성을 가진 js파일을 정리하여 하나의 파일로 합친다.

     

    2. 트랜스파일(Transpile) : HTML, CSS, JavaScript을 보완하고자 만들어진 슈퍼셋(Superset : 기존 기술에 더해 만들어진 기술) 들을 번들링 하며 다시 HTML, CSS, JavaScript로 바꿔준다.

     

    3. 코드 분할(Code Splitting) : SPA는 당장 필요하지 않은 페이지의 소스도 번들링 되는데, 번들러에게 필요에 따라 통제할 수 있게 기능을 제공한다.

     

    4. 트리 쉐이킹(Tree Shaking) : 여러 모듈을 묶어 하나의 번들로 만들어 줄 때, 사용되지 않는 코드는 포함하지 않는다. 결과적으로 파일의 크기가 줄어든다. 

     

    5. 소스압축(Minification) : 소스코드, 식별자를 짧은 이름으로 바꾸고 주석과 공백 문자를 삭제하여 소스 파일을 감소시키고 보안을 높인다.

     

    6. 소스맵(Sourcemap) : 번들링과 소스압축을 거치면 원형이 거의 남아있지 않는데, 이는 디버깅을 어렵게 하므로 번들러는 소스맵을 생성하여 브라우저에서의 디버깅을 돕는다. 소스압축 전의 소스 정보를 보존한 메타 파일이다. (그래서 우리는 개발자 도구를 통해 브라우저 디버깅 시스템을 이용할 수 있다).

     

    7. 빠른 모듈 교체(Hot Module Replacement) : 소스코드를 살짝 수정할 때마다 전체적으로 빌드하면 시간이 오래 걸린다. 수정된 부분만 교체하고 재부팅을 하지 않아도 상태를 변경해 주는 기능을 빠른 모듈 교체라고 한다. 

     

    빌드 과정에서 Webpack같은 번들러를 사용하여 하나의 파일로 만들게 된다.
    빌드 과정에서 Webpack같은 번들러를 사용하여 하나의 파일로 만들게 된다.
    빌드 결과물에 소스압축이 적용된 사진
    빌드 결과물들은 소스압축이 되어있다.


    Webpack

     CRA의 문제점 중 하나는 실제로 사용하지 않는 설정이나 라이브러리까지 포함되어 있어 번들 자체가 무거워 빌드 시간이 오래 걸린다는 것이었다. 이를 eject로 커스텀하기에는 차라리 Webpack으로 처음부터 설정하는 것이 덜 번거로울 수도 있다. 

     React에서의 SEO 개선도 Webpack을 사용하여 해결할 수 있다. 서버와 클라이언트 각각의 설정파일을 만들어 서버에서 빌드된 html을 읽어와 App을 렌더링 시켜 클라이언트 측에 보내는 식으로 설정할 수 있다.

     

    2022 state of js에서 발표된 Webpack의 awareness
    출처 : https://2022.stateofjs.com/en-US/libraries/build-tools/
    2022 state of js에서 발표된 Webpack의 usage
    출처 : https://2022.stateofjs.com/en-US/libraries/build-tools/

     

     State of JavaScript 2022에서는 Webpack이 Awarencess(얼마나 들어봤는지), Usage(얼마나 사용하는지)에서 가장 높은 순위를 기록한 것을 볼 수 있다. 대중적인 번들러임에는 분명하다. 

     

    Webpack 공식 홈페이지의 대표사진
    출처 : https://webpack.js.org/

     

     기본적으로 Webpack은 설정 파일을 필요로 하지 않으나 특정 상황에 따라 설정이 가능하고, 핵심 개념은 다음과 같다.

    • Entry(엔트리) : 프로젝트에 필요한 모든 모듈을 매핑하고 하나 이상의 번들을 생성하는 디펜던시 그래프를 만들 때 Entry Point로 어디서부터 만들기 시작해야 할지 지정한다. 여러 개일 수도 있다. 시작했으면 하는 경로를 적어주고, default값은 ./src/index.js이다. 

     

    CRA의 Entry 설정
    CRA의 Entry 설정
    기본값으로 설정되어있다.
    기본값으로 설정되어 있다.

     

    • Output(출력) : Webpack에 의해 생성된 번들을 내보낼 위치와 이름을 지정한다. default는 ./dist/main.js이다. 

    CRA의 Output설정.
    CRA의 Ouptput 설정

     

    • Loaders(로더) : Webpack은 JavaScript 파일과 JSON 파일밖에 이해하지 못한다. 로더를 사용하여 그 외의 파일들을 애플리케이션에서 사용 가능한 유효 모듈 형태로 변환, 디펜던시 그래프에 추가한다. 어떤 파일인지 찾는 test와 해당 파일을 변환하기 위해 어떤 로더를 사용해야 하는지 명시하는 use 프로퍼티를 사용한다.

     

    scss, sass 파일을 찾아 sass-loader과 잇는다.
    CRA의 Loaders의 한 부분

     

     위의 사진은 sassRegex(scss, sass로 끝나는 파일)에 매칭되는 파일을 찾아 변환에 사용되는 로더인 sass-loader를 가리키게 된다. 

     

    • Plugins(플러그인) : Webpack의 장점 중 하나는 다양한 플러그인을 제공한다는 것이다. 우리가 특정 라이브러리를 밖에서 import해오듯이, Webpack도 플러그인을 들고 와 최적화, 환경 변수 주입 같은 기능을 구현할 수 있다. 코드 분할도 플러그인을 통해 도움을 받을 수 있다.
      다만, 많은 플러그인에서 적절한 것을 찾고 활용하는 것도 중요하다.

     

    CRA의 plugins
    CRA의 plugins

     

    • Mode(모드) : 모드를 통해 development, production, none 같은 환경별 최적화를 활성화시킬 수 있다. default는 production이다. 

     

    환경 변수 설정에 따라 결정한다.
    환경 변수 설정에 따라 결정된다.

     

    • Browser Compatibility(브라우저 호환성) : Webpack은 ES5가 호횐되는 모든 브라우저를 지원한다. 구형 브라우저를 지원하려면 폴리필(구현이 누락된 새로운 기능을 메꿔주는 코드)을 로드해야 한다. 

     

     Webpack은 많은 사용자와 오랜 개발 기간 동안 쌓은 안정성도 있으나, 새롭게 등장하는 번들러에 비해 속도가 느린 편이다. 특히 다음에 기술될 Vite(비트) 번들러의 경우 위협적으로 점유율을 높이고 있다.

     


    Vite

     

    출처 : https://ko.vitejs.dev/

     

     

    2022 state of js에서 발표된 Vite의 interest
    출처 : https://2022.stateofjs.com/en-US/libraries/build-tools/
    2022 state of js에서 발표된 Vite의 retention
    출처 : https://2022.stateofjs.com/en-US/libraries/build-tools/

     

     Webpack이 Awarencess, Usage에서 가장 높은 순위를 기록했다면 Vite는 Interest(관심도), Retention(계속 이용할 것이다)에서 가장 높은 순위를 기록했다. 

    Vite는 두 번들러를 사용하여 성능과 유연성을 챙겼다.

     

    • ESBuild : Go 언어를 사용하여 높은 성능을 챙긴 번들러. Vite는 사전 번들링(Pre-bundling : 로컬에 사이트를 불러오기 전에 프로젝트 디펜던시를 사전 번들링시킨)을 ESBuild를 사용하여 빠른 속도로 통합한다. 

     

    esbuild의 빠른 속도에 대한 사진

     

    • Rollup : 다양한 환경에 맞춰 다르게 빌드시키는 유연성을 가진 번들러. 빠른 ESBuild보다 더 유연한 플러그인과 API를 제공하는 Rollup을 통해 번들링 시킨다. 

     

     

    그 외에도 템플릿을 제공하여 편리한 App 설정도 가능하다. Vue의 창시자가 만들었으나 Vue 뿐만 아니라 React, Preact, Svelte 등에서도 사용할 수 있다. 

     

     

    Vite가 현재 지원하는 템플릿
    Vite가 현재 지원하는 템플릿

     

    프롬프트 창에서 메세지만 따라가도 프로젝트가 만들어진다.
    프롬프트 창에서 메세지만 따라가도 프로젝트가 만들어진다.

     

      서버 측 렌더링도 가능하다. 공식 문서에서 가이드를 제공하고 있으며, vite-plugin-ssr같은 플러그인도 존재한다. 이러한 빠른 빌드 도구와 편리한 개발 세팅 경험으로 빠르게 성장한 Vite는 자신만의 생태계도 만들어지고 있다. 깊숙이 들어갈 경우 여러 호환성 문제라던지 단점도 존재할 것이나, 현재로서 가장 매력적인 번들러임은 분명한 것 같다.

     

     

     

     

     글을 작성하며 CRA가 주었던 좋은 개발 경험도 많이 생각이 났다. 많은 초보 개발자들을 위해 이 러닝 커브를 개선하고자 만들어졌던 툴 체인이고, 이러한 CRA가 있었기에 다른 번들러들도 단점들을 고민하며 발전할 수 있었다고 생각해 본다. 불편함을 지속해서 개선시키고자 적극적으로 발전하는 문화가 참 멋진 것 같다. ⚡

     

     아래 그림은 모듈, 번들러에 대한 개념을 전혀 몰랐을 때는 무슨 소리인지 몰라 웃음도 나오지 않았던 짤인데, 글을 마치는 이 시점에는 박장대소까지는 아니더라도 조금이나마 유쾌함은 느낄 수 있게 되어 첨부해 본다.

     

    자바스크립트 모듈과 번들러의 역사를 조선시대 붕당정치에 빗대어 만든 그림
    출처 : https://wormwlrm.github.io/2020/08/12/History-of-JavaScript-Modules-and-Bundlers.html

     

     

     

    참고자료

    https://junghan92.medium.com/%EB%B2%88%EC%97%AD-create-react-app-%EA%B6%8C%EC%9E%A5%EC%9D%84-vite%EB%A1%9C-%EB%8C%80%EC%B2%B4-pr-%EB%8C%80%ED%95%9C-dan-abramov%EC%9D%98-%EB%8B%B5%EB%B3%80-3050b5678ac8

    https://medium.com/@JedaiSaboteur/creating-a-react-app-from-scratch-f3c693b84658

    https://medium.com/naver-place-dev/javascript-%EB%B2%88%EB%93%A4%EB%9F%AC%EC%9D%98-%EC%9D%B4%ED%95%B4-3-%EB%B2%88%EB%93%A4%EB%9F%AC-%EA%B0%9C%EB%A1%A0-32e51414b503

    https://webpack.kr/concepts/

    https://www.reason-to-code.com/blog/why-do-we-have-to-bundle-javascript/

    https://ko.vitejs.dev/

    댓글

🍀 Y0ungZ dev blog.
스크롤 버튼