๋ฆฌ์กํธ ํ๋ก์ ํธ๋ฅผ ์์ฑํด ์ฌ์ฉ์์๊ฒ ์ ๊ณตํ ๋, ๋น๋ ์์ ์ ๊ฑฐ์ณ์ ๋ฐฐํฌํด์ผ ํ๋ค.
๋น๋ ์์ ์ผ๋ก ํ๋ก์ ํธ์์ ์ฌ์ฉ๋๋ .js ์์ ๋ถํ์ํ ์ฃผ์, ๊ฒฝ๊ณ ๋ฉ์ธ์ง, ๊ณต๋ฐฑ์ ์ ๊ฑฐํด ํ์ผ ํฌ๊ธฐ๋ฅผ ์ต์ํํ๊ณ ,
๋ธ๋ผ์ฐ์ ์์ JSX ๋ฌธ๋ฒ์ด๋ ๋ค๋ฅธ ์ต์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ด ์ํํ๊ฒ ์คํ๋๋๋ก ์ฝ๋์ ํธ๋์ค ํ์ผ ์์ ๋ ํ ์ ์๋ค.
์ ์ ํ์ผ(์ด๋ฏธ์ง)์ด ์๋ค๋ฉด ํด๋น ํ์ผ์ ์ํ ๊ฒฝ๋ก๋ ์ค์ ๋๋ค.
์ด ์์ ์ webpack์ด ๋ด๋นํ๋ฉฐ, webpack์์ ๋ณ๋์ ์ค์ ์ ํ์ง ์์ผ๋ฉด ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ด ํ๋์ ํ์ผ๋ก ํฉ์ณ์ง๊ณ ๋ชจ๋ CSS ํ์ผ๋ ํ๋์ ํ์ผ๋ก ํฉ์ณ์ง๋ค.
CRA(create react-app)๋ก ํ๋ก์ ํธ๋ฅผ ๋น๋ํ ๊ฒฝ์ฐ, ์ต์ ๋ ๊ฐ ์ด์์ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ด ์์ฑ๋๋ค.
CRA์ ๊ธฐ๋ณธ webpack ์ค์ ์๋ SplitChunks ๊ธฐ๋ฅ์ด ์ ์ฉ๋์ด { node_module์์ ๋ถ๋ฌ์จ ํ์ผ, ์ผ์ ํฌ๊ธฐ ์ด์์ ํ์ผ, ์ฌ๋ฌ ํ์ผ๊ฐ ๊ณต์ ๋ ํ์ผ} ์ ์๋์ผ๋ก ๋ฐ๋ก ๋ถ๋ฆฌํด ์บ์ฑ ํจ๊ณผ๋ฅผ ๋ธ๋ค.
(์์ฃผ ๋ฐ๋์ง ์๋ ์ฝ๋๋ค์ ๋ถ๋ฆฌํด ๋ฐ๋ก ํ์ผ์ ์ ์ฅํ์ฌ ์บ์ฑ์ ์ด์ ์ ๋ ์ค๋ ๋๋ฆด ์ ์๋ค.)
์ด๋ ๊ฒ ํ์ผ์ ๋ถ๋ฆฌํ๋ ์์ ์ ์ฝ๋ ์คํ๋ฆฌํ ์ด๋ผ๊ณ ํ๋ค.
์ฝ๋ ์คํ๋ฆฌํ ์ ๋จ์ํ ํจ์จ์ ์ธ ์บ์ฑ ํจ๊ณผ๋ง ์๋ค.
SPA(์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ) ๊ฐ๋ฐ์,
์ฌ์ฉ์๊ฐ A ํ์ด์ง์ ๋ฐฉ๋ฌธํ๋ค๋ฉด B ํ์ด์ง์ Cํ์ด์ง์์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ ์ ๋ณด๋ ํ์ํ์ง ์๋ค.
์ฌ์ฉ์๊ฐ ์ค์ ๋ก B,C ํ์ด์ง๋ก ์ด๋ํ ๋๋ง ํ์ํ๋ค.
ํ์ง๋ง ๋ฆฌ์กํธ ํ๋ก์ ํธ์ ๋ณ๋๋ก ์ค์ ํ์ง ์์ผ๋ฉด A, B, C ์ปดํฌ๋ํธ์ ๋ํ ์ฝ๋๊ฐ ๋ชจ๋ ํ ํ์ผ(main)์ ์ ์ฅ๋๋ค.
๊ทธ ์์ด ๋ง์ ์ง์๋ก ๋ก๋ฉ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์ ๊ฒฝํ๋ ์ ์ข์์ง๊ณ ํธ๋ํฝ๋ ๋ง์ด ๋์จ๋ค.
์ด๋ฌํ ๋ฌธ์ ์ ์ '์ฝ๋ ๋น๋๊ธฐ ๋ก๋ฉ' ์ผ๋ก ํด๊ฒฐํ ์ ์๋ค.
์ด ๋ํ ์ฝ๋ ์คํ๋ฆฌํ ๋ฐฉ๋ฒ ์ค ํ๋๋ก, '์ฝ๋ ๋น๋๊ธฐ ๋ก๋ฉ' ์ ํตํด ์๋ฐ์คํฌ๋ฆฝํธ ํจ์, ๊ฐ์ฒด, ์ปดํฌ๋ํธ๋ฅผ ์ฒ์์๋ ๋ถ๋ฌ์ค์ง ์๊ณ ํ์ํ ์์ ์ ๋ถ๋ฌ์์ ์ฌ์ฉํ ์ ์๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ํจ์ ๋น๋๊ธฐ ๋ก๋ฉ
// notify.js
export default function notify() {
alert("์๋
ํ์ธ์.");
}
// App.js
import logo from "./logo.svg";
import "./App.css";
function App() {
const onClick = () => {
import("./notify").then((result) => result.default());
// import๋ฅผ ํจ์๋ก ์ฌ์ฉ์, Promise๋ฅผ ๋ฐํํ๋ค.
// ์ด ํจ์๋ฅผ ํตํด ๋ชจ๋์ ๋ถ๋ฌ์ฌ๋ default๋ก ๋ด๋ณด๋ธ ๊ฒ์ result.default๋ฅผ ์ฐธ์กฐํด์ผ ์ฌ์ฉ ๊ฐ๋ฅ
};
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p onClick={onClick}>Hello React!</p>
</header>
</div>
);
}
export default App;
state๋ฅผ ์ฌ์ฉํ ์ฝ๋ ์คํ๋ฆฌํ
const SplitMe = () => {
return <div>SplitMe</div>;
};
export default SplitMe;
import { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
// ํด๋์คํ ์ปดํฌ๋ํธ๋ก ์ ํ
class App extends Component {
state = {
SplitMe: null,
};
handleClick = async () => {
const loadedModule = await import("./SplitMe");
this.setState({ SplitMe: loadedModule.default });
};
render() {
const { SplitMe } = this.state;
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p onClick={this.handleClick}>Hello React!</p>
{SplitMe && <SplitMe />}
</header>
</div>
);
}
}
export default App;
React.lazy์ Suspense ์ฌ์ฉํ๊ธฐ
React.lazy : ์ปดํฌ๋ํธ๋ฅผ ๋๋๋งํ๋ ์์ ์์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ก๋ฉํ ์ ์๊ฒ ํด์ฃผ๋ ์ ํธ ํจ์
Suspense : ๋ฆฌ์กํธ ๋ด์ฅ ์ปดํฌ๋ํธ, ์ฝ๋ ์คํ๋ฆฌํ ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ก๋ฉํ๋๋ก ๋ฐ๋์ํค๊ณ ,
fallback props๋ฅผ ํตํด ๋ก๋ฉ ์ค์ ๋ณด์ฌ์ค JSX๋ฅผ ์ง์ ํ ์ ์๋ค.
import logo from "./logo.svg";
import "./App.css";
import { Suspense, useState, lazy } from "react";
const SplitMe = lazy(() => import("./SplitMe"));
function App() {
const [visible, setVisible] = useState(false);
const onClick = () => {
setVisible(true);
};
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p onClick={onClick}>Hello React!</p>
<Suspense fallback={<div> loading...</div>}>
{visible && <SplitMe />}
</Suspense>
</header>
</div>
);
}
export default App;
Loadable Components๋ฅผ ํตํ ์ฝ๋ ์คํ๋ฆฌํ
Loadable Components : ์ฝ๋ ์คํ๋ฆฌํ ๋์์ฃผ๋ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์๋ฒ ์ฌ์ด๋ ๋๋๋ง์ ์ง์ํฉ๋๋ค. (laxy, Suspense๋ ์ด๋ฅผ ์ง์ํ์ง ์์ต๋๋ค.)
๋ํ ๋๋๋งํ๊ธฐ ์ ์ ํ์ํ ๋ ์คํ๋ฆฌํ ๋ ํ์ผ์ ๋ฏธ๋ฆฌ ๋ถ๋ฌ์ฌ ์ ์๋ ๊ธฐ๋ฅ๋ ์๋ค.
(* ์๋ฒ ์ฌ์ด๋ ๋๋๋ง : ์น ์๋น์ค์ ์ด๊ธฐ ๋ก๋ฉ ์๋ ๊ฐ์ , ์บ์ฑ ๋ฐ ๊ฒ์ ์์ง ์ต์ ํ ๊ธฐ์ ๋ก,
์ด๋ฅผ ์ฌ์ฉํ๋ฉด, ์น ์๋น์ค์ ์ด๊ธฐ ๋ ๋๋ง์ ์๋ฒ ์ชฝ์์ ์ฒ๋ฆฌํ์ฌ,
์๋ฒ์์ ๋ ๋๋งํ html ๊ฒฐ๊ณผ๋ฌผ์ ๊ทธ๋๋ก ์ฌ์ฉํด ์ด๊ธฐ ๋ก๋ฉ ์๋๊ฐ ๊ฐ์ ๋๋ฉฐ,
๊ฒ์ ์์ง์์ ํฌ๋กค๋งํ ๋๋ ๋ฌธ์ ๊ฐ ์๊ธฐ์ง ์๋๋ค.
์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ์์ธํ ์์๋ณด๊ธฐ- https://chestnutsweetpotato.tistory.com/93)
import logo from "./logo.svg";
import "./App.css";
import { useState } from "react";
import loadable from "@loadable/component";
const SplitMe = loadable(() => import("./SplitMe"), {
fallback: <div> loading... </div>,
});
function App() {
const [visible, setVisible] = useState(false);
const onClick = () => {
setVisible(true);
};
const onMouseOver = () => {
// ๋ง์ฐ์ค ์ปค์๋ฅผ ์ฌ๋ฆฌ๊ธฐ๋ง ํด๋ ๋ก๋ฉ์ด ์์๋จ.
// ํด๋ฆญ์ ๋๋๋ง๋จ.
SplitMe.preload();
};
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p onClick={onClick} onMouseOver={onMouseOver}>
Hello React!
</p>
{visible && <SplitMe />}
</header>
</div>
);
}
export default App;