[React] React.lazy() & <Suspense />
1. Code Spliting
-리액트 렌더링 최적화와 관련 있는 내용이다.
-많은 모듈들이 번들링 된 자바스크립트는 무겁다. 이는 렌더링을 지연시킨다.
-페이지 로딩 속도를 개선하기 위해 코드 분할 아이디어가 도입되었다.
-렌더링 속도가 느린 페이지를 파악하여 해당 페이지에서 사용되는 코드 번들을 분할한 뒤에 당장 뷰를 그리는데에 필요한 코드만 불러오고 나머지는 나중에 불러온다.
-이를 위해 모듈을 동적으로 불러오는 기술이 요구된다.
*참고로 라이브러리 등 외부 모듈을 로드할 때에는 필요한 코드 몇 개만 가져다 쓰는 식으로 개발해야한다. 해당 모듈의 모든 코드를 로드하면 앱의 크기가 방대해진다.
import _ from 'lodash';
_.find([]);
// 이렇게 lodash 라이브러리를 전체를 불러와서 그 안에 들은 메소드를 꺼내 쓰는 것은 비효율적임
import find from 'lodash/find';
find([]);
// 이렇게 lodash의 메소드 중 하나를 불러와 쓰는 것이 앱의 성능에 더 좋다!
2. Dynamic import
-자바스크립트에서 외부 리소스를 불러오는 import 구문은 반드시 파일의 최상단, 즉 전역에서 실행되어야 하는데 이를 Static import 방식이라 부른다.
-Static import는 블록문 내부 등 로컬 스콥에 위치할 수 없다. 그 이유는 번들링 시 코드 구조를 분석을 통해 모듈을 한 곳에 모으고 사용하지 않는 모듈과 코드는 제거하는 등의 작업이 수행되는데, 이는 코드 구조가 간단하고 고정되어 있을 때 가능하기 때문이다.
-Dynamic import는 함수 내부 등 로컬 스콥에서 외부 모듈을 불러올 수 있게 한다.
form.addEventListener("submit", e => {
e.preventDefault();
import('library.moduleA') // 이런 식으로 코드의 중간에서 모듈을 불러올 수 있다.
.then(module => module.default)
.then(someFunction())
.catch(handleError());
});
const someFunction = () => {
/* moduleA를 여기에서 사용 */
}
-위와 같이 사용자가 form 양식을 제출하는 상황에서만 모듈A를 불러와 사용할 수 있다.
-then() 메소드를 거치면서 필요한 코드만 정제하여 사용한다.
3. React.lazy() & <Suspense />
-리액트는 SPA이어서 렌더링 할 때 한 번에 모든 컴포넌트를 불러오는데, React.lazy()를 이용하여 바로 사용하지 않는 컴포넌트를 상황에 따라 동적으로 import 시켜 초기 렌더링 시간을 줄일 수 있다.
* <Suspense />: 리액트가 비동기 로직(데이터 로딩, 코드 분할 등)과 관련된 시나리오에서 컴포넌트가 로딩을 완료할 때 까지 대체 컨텐츠(Loading Spinner, Placeholder 등)를 렌더링하는 컴포넌트이다.
import { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
</BrowserRouter>
);
-여러 페이지를 진입하는 단계인 Routes 컴포넌트에서 함께 적용한다.
-각 링크에 따라 불러올 컴포넌트를 lazy() 메소드로 임포트하고, 컴포넌트가 렌더링 되는 Route 컴포넌트를 <Suspense />로 감싸준다.
-Suspense 컴포넌트의 fallback 속성에는 로딩시 보여줄 컴포넌트를 전달한다.