티스토리 뷰
빠름의 민족인 우리는 웹사이트가 조금만 느려도 매우 화를 내며 사이트를 이용하지 않는다.( = 는 나) 그래서 프론트앤드 개발자는 성능에 민감하게 반응하는 편이라 사이트가 무거운 것을 두고 볼 수가 없다.(이것도 나)
여러 코드를 통해 SPA를 개발하고 나면 웹팩을 이용하여 번들링 하고, 번들된 자바스크립트 파일을 html에서 불러와 실행하는 코스는 웹을 공부해본 사람이라면 몰라도 아는(?) 개념이다. 번들링이란 여러 작업 코드를 하나의 파일로 병합해주는 것을 의미한다.
그런데 코드가 점점 많아지면 번들 파일도 함께 커지면서 성능이 현저하게 느려질 수 밖에 없다. 여담으로 현직에서 보면 라이브러리를 사용하길 싫어하는 개발자들을 꽤나 만날 수 있는데, 많은 라이브러리 혹은 무거운 라이브러리를 사용하게 되면 번들 크기가 금방 커지고 성능에 영향을 미치기 때문이다.
이럴 때, 해결하는 방안이 code splitting, 즉 코드 분할이다. 코드 분할이라 함은 하나의 무거운 번들 파일의 코드를 분할하여 여러개의 번들 파일로 나누고, 해당 페이지에서 필요한 코드들만 불러오는 개념이다. 코드 분할을 통해 앱 코드의 양을 줄이지 않고, 사용자가 필요로 하지 않은 코드를 불러오지 않아 초기화 로딩에 필요한 비용을 줄여줄 수 있다.
리액트 공식 홈페이지에서는 코드 분할에 대한 여러가지 방법을 제안해준다.
dynamic import
동적 import() 문법은 앱에 코드 분할을 도입하는 가장 좋은 방법이다.
// before
import { add } from './math';
console.log(add(16, 26));
// After
import("./math").then(math => {
console.log(math.add(16, 26));
});
웹팩이 해당 구문을 만나면 코드를 분할하게 되는데, CRA를 사용하고 있다면 즉시 사용이 가능하며, Babel을 사용할 때는 라이브러리를 설치해줘야한다.
더불어 동적 import 문법은 위치에 상관 없이 필요로 하는 부분에서 사용할 수 있다.
React.lazy
react lazy는 말 그대로 react component를 lazy loading 시켜주는 것을 의미한다. 웹 사이트를 여러 컴포넌트 단위의 코드로 나누고, 사용자가 당장 필요로 하지 않은 코드는 불러오지 않게 하여 앱의 초기 로딩에 필요한 비용을 줄여주는 효과를 가져온다. 당연히 사용자도 빠르다고 체감할 수 있게 된다.
React.lazy와 Suspense(하단에 설명있음)는 서버 사이드 렌더링에서 동작하지 않으니, 리액트 공식 홈페이지에서는 SSR에서 코드 분할하기를 원한다면 Loadable Components 를 추천해주고 있다.
React.lazy 사용 방법은 매우 간단하다. 기존에 import 방식에서
import OtherComponent from './OtherComponent';
다음과 같은 방식으로 변경해주기만 하면 된다.
const OtherComponent = React.lazy(() => import('./OtherComponent'));
해당 문법은 동적 import를 통하여 컴포넌트를 랜더링 할 때 사용한다. 다르게 말하면 상단의 동적 import 방법은 컴포넌트 랜더링이 불가하다는 의미이다.
React.lazy는 default export로 가진 모듈 객체가 이행되는 Promise를 반환해야하며, Suspense 컴포넌트 하위에서 렌더링되어야한다. Suspense는 여러개의 컴포넌트를 감쌀 수 있으며, lazy 컴포넌트가 로드되길 기다리는 동안 fallback을 통하여 컴포넌트가 로드될 때까지 기다리는 동안 렌더링해주는 element를 지정할 수 있다.
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
Error boundaries
import React, { Suspense } from 'react';
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
const MyComponent = () => (
<div>
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</MyErrorBoundary>
</div>
);
Route based code splitting
사용자의 경험을 해치지 않으면서 번들을 균등하게 분배하기 좋은 곳은 라우트이다.
import React, { 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>
);
Named Exports
React.lazy는 default exports에서만 동작한다. named exports를 사용하기 위해서는 중간 모듈 생성을 통하여 적용할 수 있다.
// ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;
// MyComponent.js
export { MyComponent as default } from "./ManyComponents.js";
// MyApp.js
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));
참고 사이트
https://ko.reactjs.org/docs/code-splitting.html
'JavaScript > react' 카테고리의 다른 글
리액트 create portal 이란 무엇인가. 이제 여기에 모달 예제를 곁들여보자. 토스트 메세지도 가능하다. (0) | 2022.06.08 |
---|---|
[React Context Api] 리액트에서 데이터를 자유롭게 주고받는 법. (0) | 2022.05.30 |
리액트 합성이벤트(syntheticEvent)란? 합성 이벤트 정의와 종류, 사용 (0) | 2022.05.12 |
react query : 리액트쿼리가 대체 무엇인가요? 왜 필요하죠? (0) | 2022.05.08 |
리액트 온라인 코드 편집기 (0) | 2022.04.20 |
- Total
- Today
- Yesterday
- BFCache
- javascript
- gitRebase
- 리코일
- 리액트훅
- reacthook
- TIL
- 센트리
- 깃
- 자바스크립트
- js
- vue
- CSS
- 모바일사파리
- react
- js테스트
- Git
- sentry
- 리액트상태관리
- 김민태
- 크롬
- 깃명령어
- 리액트
- 프론트엔드
- 사파리
- 프론트앤드
- storybookUI
- 센트리모니터링
- frontend
- npm
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |