리액트 애플리케이션을 개발할 때 성능 최적화는 중요한 과제 중 하나입니다. 특히 초기 로딩 시간을 줄이고, 사용자 경험을 개선하기 위해 코드 스플리팅(Code Splitting)은 필수적입니다. React에서는 이를 위해 React.lazy()
와 Suspense
를 제공합니다. 이 글에서는 Suspense
와 lazy
를 활용해 어떻게 효율적으로 코드 스플리팅을 구현할 수 있는지 자세히 설명해보겠습니다.
코드 스플리팅이란?
코드 스플리팅은 애플리케이션의 코드를 여러 개의 작은 번들로 나누어 필요할 때 로드하는 기술입니다. 예를 들어, 사용자가 특정 페이지를 방문했을 때 해당 페이지와 관련된 코드만 로드하고, 다른 페이지는 나중에 로드함으로써 초기 로딩 시간을 줄이는 것입니다.
React의 lazy
와 Suspense
는 이러한 코드 스플리팅을 쉽게 구현할 수 있게 도와주는 도구입니다. 이 두가지 도구들에 대해 조금 더 구체적으로 살펴보겠습니다.
React.lazy()란?
React.lazy()
는 동적으로 컴포넌트를 로드하기 위해 사용되는 함수입니다. 이를 통해 각 컴포넌트를 독립적인 번들로 나눌 수 있으며, 사용자가 해당 컴포넌트를 필요로 할 때만 로드됩니다. 이렇게 하면 초기 번들 크기를 줄여 애플리케이션의 로드 시간을 단축할 수 있습니다.
예를 들어, lazy
를 사용하여 컴포넌트를 다음과 같이 정의할 수 있습니다:
import React, { lazy } from 'react';
const MyComponent = lazy(() => import('./MyComponent'));
위 코드는 MyComponent
를 즉시 로드하지 않고, 실제로 해당 컴포넌트를 렌더링해야 하는 상황에서 동적으로 로드합니다.
Suspense란?
Suspense
는 lazy 로딩된 컴포넌트가 로드되는 동안 사용자에게 보여줄 대체 콘텐츠를 정의하는 데 사용됩니다. 쉽게 말해, Suspense
는 로딩 상태를 관리하는 도구입니다. 예를 들어, 컴포넌트가 로드되는 동안 사용자에게 스피너나 로딩 메시지를 보여줄 수 있습니다.
Suspense
를 사용하는 예시는 다음과 같습니다:
import React, { Suspense } from 'react';
const MyComponent = lazy(() => import('./MyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<MyComponent />
</Suspense>
);
}
위 코드에서 fallback
속성은 컴포넌트가 로딩되는 동안 보여줄 UI를 정의합니다. MyComponent
가 로드되는 동안에는 “Loading…” 메시지를 화면에 표시하고, 로딩이 완료되면 MyComponent
가 렌더링됩니다.
Suspense
와 lazy
를 함께 사용하는 이유
React에서 lazy
를 사용해 컴포넌트를 지연 로드하면, 이 컴포넌트가 로드되기 전까지는 화면에 아무런 내용도 표시되지 않습니다. 이 경우 사용자 경험이 크게 저하될 수 있으므로, 로딩 상태를 명확히 표시해주는 것이 중요합니다. Suspense
는 이를 해결하기 위해 로드 중인 컴포넌트가 준비될 때까지 대체 UI를 제공함으로써 사용자 경험을 개선합니다.
이 두 도구를 함께 사용하면:
- 초기 번들 크기를 줄여 초기 로딩 속도를 개선할 수 있습니다.
- 컴포넌트가 로드되는 동안 적절한 로딩 UI를 제공하여 사용자 경험을 매끄럽게 유지할 수 있습니다.
실전 예시: Suspense
와 lazy
로 페이지 전환 최적화하기
아래는 여러 페이지를 갖춘 애플리케이션에서 Suspense
와 lazy
를 사용하여 각 페이지를 동적으로 로드하는 예시입니다:
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));
const Contact = lazy(() => import('./Contact'));
function App() {
return (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</Router>
);
}
위 예시에서 각 페이지 컴포넌트(Home
, About
, Contact
)는 lazy
를 통해 동적으로 로딩됩니다. 페이지 전환 시 필요한 컴포넌트만 로드하므로 애플리케이션의 성능을 최적화할 수 있으며, Suspense
를 통해 로딩 중에는 로딩 메시지가 표시되어 사용자 경험이 크게 향상됩니다.
최적의 사용자 경험을 위한 팁
- 적절한 Fallback UI 제공:
Suspense
의fallback
속성에 로딩 메시지 외에도 스피너, 스켈레톤 UI 등을 활용하여 사용자 경험을 개선할 수 있습니다. - 지연 로드 전략 계획: 너무 많은 컴포넌트를
lazy
로 로딩하게 되면 오히려 성능이 저하될 수 있으므로, 꼭 필요한 경우에만 지연 로딩을 적용해야 합니다. 예를 들어, 초기 진입 페이지는 지연 로드 하지 않는 것이 좋습니다.
결론
React의 Suspense
와 lazy
는 코드 스플리팅을 통해 애플리케이션 성능을 최적화하고, 로딩 중에 사용자에게 부드러운 경험을 제공하는 데 매우 유용한 도구입니다. 이를 올바르게 사용하면 번들 크기를 줄여 초기 로딩 시간을 단축하고, 동적 로딩 중에 사용자 경험을 개선할 수 있습니다.