npm
을 통해 다운로드하는 서드파티(Third Party) 라이브러리도 포함이 된다./* 이렇게 lodash 라이브러리를 전체를 불러와서 그 안에 들은 메서드를 꺼내 쓰는 것은 비효율적이다.*/
import _ from 'lodash';
...
_.find([]);
/* 이렇게 lodash의 메서드 중 하나를 불러와 쓰는 것이 앱의 성능에 더 좋다.*/
import find from 'lodash/find';
find([]);
lodash
라는 라이브러리를 예시로 하고 있다.lodash
라는 라이브러리는 하나의 폴더와 같고, 그 폴더 안에는 개발 시 다양한 상황에 쓰기 좋은 메서드들, 즉 함수 코드들이 들어 있다./* 기존에는 파일의 최상위에서 import 지시자를 이용해 라이브러리 및 파일을 불러왔다. */
import moduleA from "library";
form.addEventListener("submit", e => {
e.preventDefault();
someFunction();
});
const someFunction = () => {
/* 그리고 코드 중간에서 불러온 파일을 사용했다. */
}
import
구문은 문서의 상위에 위치해야 했고, 블록문 안에서는 위치할 수 없는 제약 사항이 있었다.form.addEventListener("submit", e => {
e.preventDefault();
/* 동적 불러오기는 이런 식으로 코드의 중간에 불러올 수 있게 된다. */
import('library.moduleA')
.then(module => module.default)
.then(someFunction())
.catch(handleError());
});
const someFunction = () => {
/* moduleA를 여기서 사용한다. */
}
moduleA
가 다른 곳에서 사용되지 않는 경우, 사용자가 form을 통해 양식을 제출한 경우에만 가져오도록 할 수 있다.then
함수를 사용해 필요한 코드만 가져온다.React.lazy()
React.lazy
함수를 사용하면 dynamic import를 사용해 컴포넌트를 렌더링할 수 있다.React는 SPA이므로 한 번에 사용하지 않는 컴포넌트까지 불러오는 단점이 있다.
이때 React.lazy
를 사용하면 컴포넌트를 동적으로 import
할 수 있어 초기 렌더링 지연시간을 어느 정도 줄일 수 있게 된다.
import Component from './Component';
/* React.lazy로 dynamic import를 감쌉니다. */
const Component = React.lazy(() => import('./Component'));
React.lazy
로 감싼 컴포넌트는 단독으로 쓰일 수는 없고, React.suspense
컴포넌트의 하위에서 렌더링을 해야 한다.React.Suspense
Router
로 분기가 나누어진 컴포넌트들을 위 코드처럼 lazy
를 통해 import
하면 해당 path
로 이동할 때 컴포넌트를 불러오게 되는데 이 과정에서 로딩하는 시간이 생기게 된다.Suspense
는 아직 렌더링이 준비되지 않은 컴포넌트가 있을 때 로딩 화면을 보여주고, 로딩이 완료되면 렌더링이 준비된 컴포넌트를 보여주는 기능이다.
/* suspense 기능을 사용하기 위해서는 import 해와야 한다. */
import { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
return (
<div>
{/* 이런 식으로 React.lazy로 감싼 컴포넌트를 Suspense 컴포넌트의 하위에 렌더링한다. */}
<Suspense fallback={<div>Loading...</div>}>
{/* Suspense 컴포넌트 하위에 여러 개의 lazy 컴포넌트를 렌더링시킬 수 있다. */}
<OtherComponent />
<AnotherComponent />
</Suspense>
</div>
);
}
Supense
컴포넌트의 fallback
prop은 컴포넌트가 로드될 때까지 기다리는 동안 로딩 화면으로 보여줄 React 엘리먼트를 받아들인다.
Suspense
컴포넌트 하나로 여러 개의 lazy
컴포넌트를 보여줄 수도 있다.
앱에 코드 분할을 도입할 곳을 결정하는 것은 사실 까다롭기 때문에, 중간에 적용시키는 것보다는 웹 페이지를 불러오고 진입하는 단계인 Route
에 이 두 기능을 적용시키는 것이 좋다.
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 = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
</Router>
);
라우터에 Suspense
를 적용하는 것은 간단한 편이다.
라우터가 분기되는 컴포넌트에서 각 컴포넌트에 React.lazy
를 사용하여 import
한다.
그리고 Route
컴포넌트들을 Suspense
로 감싼 후 로딩 화면으로 사용할 컴포넌트를 fallback
속성으로 설정해 주면 된다.
초기 렌더링 시간이 줄어드는 분명한 장점이 있으나 페이지를 이동하는 과정마다 로딩 화면이 보이기 때문에 서비스에 따라서 적용 여부를 결정해야 한다.