[Frontend] Lazy Loading, Suspense 그리고 SSR

이승준·2023년 2월 26일
0

Tlog.Frontend

목록 보기
2/3

Lazy Loading

🛏️ 탄생 배경

웹 프로젝트의 규모가 커지면서 모듈화된 여러 javascript 파일을 로드하는데 시간이 오래걸린다는 이유에서 번들링이 등장하게 됐습니다. 번들링을 통해 개발 단계에서는 모듈 단위로 개발하는 편의를 즐김과 동시에, 베포단계에서는 하나의 javascript 파일을 로딩하여 성능면에서 이점을 누릴 수 있게 됐습니다.

문제는 번들링 결과로 나온 하나의 javascript 파일의 크기가 너무 크다면, 파일을 로드하는데에 너무 많은 시간이 걸려버리는 상황이 발생하게 됩니다.

이런 상황에서 등장한 것이 바로 Lazy Loading이죠.
저희가 제공하는 웹 사이트에는 바로 로드됐으면 하는 컴포넌트와 그렇지 않은 컴포넌트가 있습니다. 가령 서버에서 데이터를 불러오는 일부 컴포넌트, 혹은 상대적으로 용량이 큰 이미지를 로드하느라 전반적인 UI를 불러오지 못한다면 좋지 않은 사용자 경험을 제공하게 됩니다.

작동 방식

React에서는 React.Lazy를 통해 javascript 번들을 분리할 수 있는데요, 덕분에 페이지 내부에서 데이터를 가져오는데에 시간이 걸리는 느린 컴포넌트 때문에 로드가 빠른 컴포넌트까지 못보게되는 일을 막을 수 있게 됩니다.

예시

import React, {lazy} from 'react';
...
const LazyComponent = lazy(() => import('{Component path}'));

위의 lazyComponent는 분리된 번들로 로드가 되며, 해당 컴포넌트가 필요할 때 비동기적으로 컴포넌트를 로딩하게 됩니다.

그럼 데이터가 로딩중일 때, 해당 컴포넌트가 로드되어야 할 자리는 어떻게 처리할 까요? 이를 처리하기 위해 React.lazy는 항상 <Suspense/>와 같이 쓰입니다.

import React, {lazy, Suspense} from 'react';
...
const LazyComponent = lazy(() => import('{Component path}'));

const Page = () => {
	return <Suspense fallback={<>Loading Component</>}>
    	  <LazyComponent/>
    </Suspense>
};

export default Page;

위와같이, Suspensefallback prop을 함께 사용하여 데이터가 아직 로딩중일 때 보여줄 컴포넌트를 설정할 수 있습니다.

SSR

SSR은 Server Side Rendering으로, javascript 번들이 로드되기 전까지는 빈 html 파일을 봐야하는 사용자 경험을 개선하기 위해 등장했습니다.

💡 구글같은 검색엔진이 빈 페이지를 크롤링해서 무의미한 페이지로 인식하는 것을 방지하기 위함도 있습니다.

일반적인 React 어플리케이션에서는 사용자가 페이지를 요청하면 우선 빈 HTML 파일을 받게 됩니다. 그리고 React의 javascript 번들이 로드되면, 그 때 html DOM에 변화를 주며 컨텐츠를 제공하는 형태죠. 이를 CSR, Client Side Rendering이라고 부릅니다.

SSR에서는 다음과 같은 순서로 사용자에게 컨텐츠가 제공됩니다.

  1. 서버에서 HTML을 로딩하는데에 필요한 데이터를 로드합니다.
  2. 데이터가 로드되면, HTML으로 렌더링 후, 클라이언트에게 전달합니다.
  3. 클라이언트에서 Javascript 번들을 로드합니다.
  4. 클라이언트에서 HTML과 Javascript 로직을 연결시킵니다. (Hydrate)

위와같은 과정 덕분에, 사용자는 빈 HTML 파일을 볼 필요가 없어졌고, 검색엔진으로부터의 크롤링도 가능해지면서 웹 사이트를 노출시키는 데에도 유리해졌습니다.

React 18

react 18 이전에는, Lazy loading과 Suspense는 CSR에서 코드 분할(번들 분할)과 지연로딩을 위해서 사용되었습니다.
react18 이후에, Suspense는 SSR을 지원하기 위한 기능들이 추가됩니다.

우선 SSR에서 지연로딩과 Suspense를 지원하지 않으면 앞서 언급한 SSR을 통해 사용자에게 컨텐츠를 제공할 때, 서버에서 모든 데이터가 로딩될때 까지 기다려야합니다. 위의 1~4번부터의 순서가 꼭 지켜져야하고, 이전 순서가 완료되지 않으면 다음 순서는 계속 오지 않는다는 뜻이죠.

react18 이후, Suspense에 SSR을 위한 기능이 추가되면서, 데이터를 불러오는 부분별로 SSR 작동 순서를 적용할 수 있게 됩니다.

React 18: Suspense를 이용한 새로운 SSR 아키텍처
위 링크에서 정말 자세하게 설명하고 있으니 참고하시면 좋을것 같습니다.

위의 글을 참고해서 정리해보면,
데이터를 로드하는데 오래걸리는 부분(Suspense로 감싸진 컴포넌트)은 ssr 방식이 따로 적용됩니다. 그래서 아래와 같이 Loading상태로 표시할 수 있죠.

그리고 로딩이 다 되면, 아래 그림과 같이 HTML 구조를 보여줍니다.

그런데 SSR에서는 클라이언트가 렌더링된 HTML을 받고, Javascript 번들이 로드되면 HTML과 javascript 로직을 연결시키는 Hydrate 과정이 발생하는데요.

이렇게 컴포넌트가 각각 따로 로드되게 되면 hydrate 과정도도 분리되어 작동되어야합니다. 물론 react18의 Suspense는 이 과정을 지원하고, 이를 선택적 하이드레이션(Selective Hydration)이라고 부릅니다.

그 이외에도, 사용자가 상호작용하려는 컴포넌트부터 hydrate 과정이 일어난다거나, 그게 아니면 순서대로 hydrate과정이 일어나도록 하여 사용자 중점적으로 기능이 발전된 모습을 확인할 수 있습니다.

profile
인터랙티브 웹부터 풀스택, web3 등 다양한 분야에 관심을 가지고 다양한 일을 이루기위한 수단으로서 개발합니다.

0개의 댓글