Lazy Loading(지연 로딩) 이란?
Lazy Loading은 특정 코드를 필요할 때만 로딩하게 해준다는 개념이다.
컴포넌트, 라이브러리 같은 것들을 import 문으로 불러오는데 이 import 문들은 화면에 무언가 뜨기 전에 먼저 처리되어야 한다. 사용자에게 전달되기 전에 모든 코드가 불러와져야 한다는 의미이다.
이것은 규모가 작은 애플리케이션에서는 문제가 되지 않지만, 규모가 크고 복잡한 애플리케이션의 경우 초기에 모든 코드를 불러오려면 첫 페이지의 로딩이 느려질 수 밖에 없다.
이를 위해서 특정 컴포넌트를 필요할 때 불러올 수 있는 lazy loading을 이용할 수 있다.
Lazy Loading 적용하기
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import BlogPage, { loader as postsLoader } from './pages/Blog';
import HomePage from './pages/Home';
import PostPage, { loader as postLoader } from './pages/Post';
import RootLayout from './pages/Root';
const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
children: [
{
index: true,
element: <HomePage />,
},
{
path: 'posts',
children: [
{ index: true, element: <BlogPage />, loader: postsLoader },
{ path: ':id', element: <PostPage />, loader: postLoader },
],
},
],
},
]);
function App() {
return <RouterProvider router={router} />;
}
export default App;
이 애플리케이션에서 HomePage를 보고 있을 때는 BlogPage의 코드가 필요하지 않다. 블로그 페이지에 방문했을 때만 필요하기 때문에 그 때 다운로드되어도 된다. 그래서 블로그페이지에 지연 로딩을 적용해볼 것이다.
현재 Blog컴포넌트에서 BlogPage와 loader를 import 하고 있기 때문에 이 2개에 모두 지연 로딩을 적용해야 한다.
loader에 지연 로딩 적용하기
{
index: true,
element: <BlogPage />,
loader: () => import('./pages/Blog').then((module) => module.loader()),
},
이전에 사용하던 loader를 다른 loader함수로 대체한다. 대체한 loader 함수는 import를 호출해 import 하려는 경로를 입력한다.
import를 함수로 호출하게 되면 동적으로 필요할 때만 import 하게 되고, import 함수는 Promise를 반환한다.
Promise를 반환하기 때문에 then을 붙여서 로딩된 파일(모듈)을 받아서 그 파일의 loader함수를 실행한다.
이렇게 되면 전체 loader함수는 마지막에 호출한 loader함수에 의해 Proimse를 반환하기 때문에 모든게 지연되어 로딩되는 것이다.
만약 동적 라우팅이 되어있어 loader에 params이 필요한 경우라면
loader: (meta) => import('./pages/Post').then((module) => module.loader(meta)),
리액트 라우터로부터 받는 meta 객체 전체 또는 { params }를 loader에 전달할 수 있다.
컴포넌트에 지연 로딩 적용하기
컴포넌트 함수로 정의해 동적으로 import한 블로그 페이지 컴포넌트를 반환하게 할 수 있다.
const BlogPage = () => import('./pages/Blog');
하지만 이것은 JSX 코드를 반환하지 않기 때문에 유효한 컴포넌트 함수가 아니다.
이것을 해결하기 위해 react에서 lazy라는 함수를 제공한다.
import { lazy } from 'react';
const BlogPage = lazy(() => import('./pages/Blog'));
lazy 함수는 실행될 때 동적으로 import하는 함수를 인자로 받는다.
따라서 () => import(경로) 이 함수를 lazy 함수의 인수로 넣어주면 반환된 값으로 컴포넌트로 사용할 수 있다.
이제 그 컴포넌트의 코드를 불러오려면 시간이 걸리기 때문에 리액트에서 제공하는 Suspense 컴포넌트로 감싸주어 지연로딩되는 컴포넌트의 로딩을 기다리는 데 사용할 수 있다.
import { lazy, Suspense } from 'react';
element: (
<Suspense fallback={<p>Loading...</p>}>
<BlogPage />
</Suspense>
),
BlogPage 컴포넌트는 렌더링을 시도하기 전까지 코드가 로드되지 않는다.
이제 블로그 페이지에 방문할 때, 개발자 도구의 Network 탭을 확인하면
자바스크립트 파일이 동적으로 다운로드된 것을 확인할 수 있고, 이 파일엔 loader의 코드와 블로그페이지 컴포넌트가 포함되어 있다.
이렇게 지연 로딩을 적용하면 복잡한 애플리케이션에서 필요할 때만 코드를 불러올 수 있게 최적화할 수 있다.
'React' 카테고리의 다른 글
[React] TanStack Query - 데이터 전송하기, Optimistic Update (0) | 2023.10.01 |
---|---|
[React] TanStack Query (React-Query) (0) | 2023.09.30 |
[React] react-router-dom의 defer (0) | 2023.09.27 |
[React] useFetcher (0) | 2023.09.27 |
[React] React Router - action, 데이터 전송하기 (0) | 2023.09.26 |