프론트엔드 번들링의 진화

최경식
5 min readSep 18, 2022

--

0세대: Concatenation

파일을 함께 연결하고 IIF(Immediately Invoked Function)로 래핑했습니다.

1세대: Bundlers

코드를 가져오고 내보내기 위한 적절한 구문인 ECMAScript 모듈을 입력합니다. 이것은 훌륭했지만 수천 개의 파일을 브라우저에 전달하는 것이 문제였습니다. 그래서 WebPack, Rollup, CommonJS 등과 같은 번들러가 탄생했습니다.

이제 코드 재사용이 가능해졌습니다. 그러나 npm이 종속성을 설치하고 번들로 묶는 것은 빠르게 크기가 문제가 되었습니다.

번들러는 트리 쉐이킹 및 데드 코드 제거를 수행하여 번들로 제공됩니다.

2세대: Lazy loading

큰 번들의 문제를 인식하고 번들러는 지연 로딩을 제공하기 시작했습니다. 지연 로딩은 코드를 청크로 분할하고 필요에 따라 브라우저에 전달할 수 있으므로 훌륭합니다. 가장 필요한 부분부터 시작하여 응용 프로그램을 부분적으로 전달할 수 있기 때문에 좋습니다. 하지만 다운로드, 구문 분석 및 실행을 마비시킬 수 있습니다.

문제는 프레임워크를 사용하여 앱을 빌드하고 프레임워크는 번들러가 코드를 지연 로드된 청크로 나누는 방법에 많은 영향을 미친다는 것입니다. 문제는 청크를 지연 로드하면 비동기 API 호출인 PROMISE가 발생한다는 것입니다. 그리고 프레임워크가 코드에 대한 동기 참조를 예상하는 경우 번들러는 지연 로드된 청크를 도입할 수 없습니다.

3세대: Lazy loading components not in the render tree

프레임워크는 번들러의 지연 로딩 기능을 활용하기 위해 빠르게 뒤섞여 있으며 오늘날 거의 모든 사람들이 지연 로딩을 수행하는 방법을 알고 있습니다. 하지만 큰 주의사항이 있습니다! 프레임워크는 현재 렌더링 트리에 없는 구성 요소만 지연 로드할 수 있습니다.

렌더 트리란? 현재 페이지를 구성하는 컴포넌트 집합입니다. 일반적으로 응용 프로그램에는 현재 페이지에 있는 것보다 더 많은 컴포넌트가 있습니다. 렌더 트리의 일부는 View입니다. 현재 브라우저 뷰포트에서 볼 수 있는 것입니다. 그러나 렌더 트리는 현재 View 외부의 컴포넌트까지 전체 DOM을 포함합니다.

컴포넌트가 렌더 트리에 있다고 가정합니다. 이 경우 프레임워크는 수화 또는 업데이트의 일부로 컴포넌트의 렌더 트리를 다시 빌드해야 하므로 컴포넌트를 다운로드해야 합니다. 프레임워크는 현재 렌더 트리에 없는 구성 요소만 지연 로드할 수 있습니다.

프레임워크가 컴포넌트를 지연 로드할 수 있지만 여기에는 항상 동작(behavior)이 포함된다는 것입니다. 컴포넌트 단위가 동작을 포함하기 때문에 너무 큽니다. 지연 로딩 단위가 더 작으면 더 좋을 것입니다. 컴포넌트를 렌더링할 때 컴포넌트의 이벤트 핸들러를 다운로드하지 않아도 됩니다. 프레임워크는 컴포넌트 렌더링 메서드의 일부가 아니라 사용자 상호 작용 시에만 이벤트 핸들러를 다운로드해야 합니다. 빌드하는 응용 프로그램의 종류에 따라 이벤트 핸들러가 코드의 대부분을 나타낼 수 있습니다. 따라서 컴포넌트의 렌더 및 동작 다운로드를 결합하는 것은 차선책입니다.

문제의 핵심

컴포넌트를 다시 렌더링해야 할 때만 컴포넌트 렌더링 기능을 지연 로드하고 사용자가 상호 작용하는 경우에만 이벤트 핸들러를 지연 로드하는 것이 좋습니다. 기본값은 모든 것이 지연 로드되는 것이어야 합니다.

개발자가 SSR/SSG 초기 페이지에 지연 로드 바운더리를 도입하더라도 도움이 되지 않는다는 점을 지적할 가치가 있습니다. 프레임워크는 여전히 SSR/SSG 응답의 모든 컴포넌트를 다운로드하고 실행해야 합니다. 따라서 컴포넌트가 렌더 트리에 있는 한 프레임워크는 개발자가 지연 로드를 시도한 구성 요소를 열심히 로드해야 합니다.

번들 도구는 세분화된 지연 로딩을 지원하지만 프레임워크는 지원하지 않습니다. 프레임워크 수화(hydration)는 렌더 트리의 모든 컴포넌트가 수화 시 로드되도록 합니다. 프레임워크는 또한 이벤트 핸들러가 코드의 대부분이 될 수 있고 초기 수화에 필요하지 않더라도 구성 요소와 함께 이벤트 핸들러를 다운로드합니다.

차세대: Fine-grained lazy loading(세분화된 지연 로딩)

  1. 수화(hydration) 시 렌더 트리를 열심히 로드하지 않도록 합니다.
  2. 컴포넌트 렌더링 기능이 컴포넌트 이벤트 핸들러와 독립적으로 로드되도록 허용합니다.

프레임워크가 위의 두 부분을 수행할 수 있다면 사용자는 엄청난 이점을 보게 될 것입니다. 시작 시 렌더링이 필요하지 않기 때문에 응용 프로그램에는 가벼운 시작 요구 사항이 있습니다(콘텐츠는 이미 SSR/SSG에서 렌더링됨). 더 적은 코드가 다운로드됩니다. 프레임워크가 특정 구성 요소를 다시 렌더링해야 한다고 결정하면 모든 이벤트 핸들러를 다운로드하지 않고 렌더링 기능을 다운로드하여 프레임워크에서 이를 수행할 수 있습니다.

세분화된 지연 로딩은 사이트 시작 성능에 있어 큰 이점이 될 것입니다. 다운로드한 코드의 양이 초기 렌더 트리 복잡성에 비례하는 대신 사용자 상호 작용에 비례하기 때문에 훨씬 빠릅니다. 귀하의 사이트는 더 빨라질 것입니다. 우리가 코드를 작게 만드는 것이 더 나았기 때문이 아니라 모든 것을 미리 다운로드하는 것보다 필요한 것만 다운로드하는 것이 더 나았기 때문입니다.

개발자는 오늘날과 마찬가지로 사이트를 구축하지만 사이트는 애플리케이션 시작 시 엄청난 번들과 실행으로 브라우저를 압도하지 않을 것입니다.

Marko, Astro, Elder, or Qwik

Reference

https://www.builder.io/blog/dont-blame-the-developer-for-what-the-frameworks-did

--

--

최경식
최경식

Written by 최경식

Lead Software Engineer, Client Side/Lightweight Full stack

No responses yet