2022. 1. 26. 22:38ใ์นดํ ๊ณ ๋ฆฌ ์์
๐ฎ ์ฝ๋ ์ฑ๋ฅ ์ํฅ ์์ ์ ๊ฒ ์์น
- ํจํค์ง ์ต์ ํ
- ๋ฒ๋ค ์ฌ์ด์ฆ ์ธก์ ๊ฒฐ๊ณผ ๋ถ์
- ๋น๋ ์๊ฐ๊ณผ ๋ฒ๋ค๋ง ์ฌ์ด์ฆ์ ์ํฅ
- ์น ํ์ด์ง ๋ฆฌ์์ค ๋ก๋ฉ ์๋ ๊ฐ์ ๊ธฐ๋
- ๋ ๋๋ง ์ต์ ํ
- Page ๋จ์ Server-side Data Fetching ํ์ฉ
- ์ ์ ์ ๋๊ธฐ์๊ฐ ์ต์ ํ
- ๋ ๋๋ง ์๋(์น ํ๋ฉด ๊ทธ๋ ค์ง๋ ๋ก์ง) ๊ฐ์ ๊ธฐ๋
- ๋ก์ง ์ต์ ํ
- Memory Leak ๋ฑ ์ฑ๋ฅ ์ํฅ ๋ก์ง ์์
- ๋ธ๋ผ์ฐ์ ์ํธ์์ฉ ์๋ ๊ฐ์ ๊ธฐ๋
์ด๋ฒ ํฌ์คํ ์์ ๊ฐ๋ฐ ๊ณผ์ ์์ ์ ์ฉํ ์ ์๋ ๋ฒ๋ค ์ฌ์ด์ฆ ์ต์ ํ๋ฅผ ๋ค๋ฃน๋๋ค.
๋ฒ๋ค ์ต์ ํ
01. ์์ธ ๋ถ์
๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ๋ถ์ํ ์ ์๋ ๋ค์ํ ๋๊ตฌ๋ค์ด ์กด์ฌํ๋ค.
ํ๋ก์ ํธ ๋ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ณ ๋น์ค์ ํ์ ํด๋ณด๊ณ ๊ทธ์ ๋ง๋ ์ต์ ํ ์ง๋จ์ ์์ํด๋ณด์.
- Webpack Analyse ( ๊ฐ์ฅ ๋ค์ํ ์ ๋ณด ์ ๊ณต but ์ฌ์ฉ๋ฒ ๋ณต์ก & ๋๋ฆผ )
- Visualizer ( ๊น๋ํ ์๊ฐํ but ๊ธฐ๋ฅ ๋ถ์กฑ )
- Bundler Analyzer ( ์์ธ ๋น ๋ฅด๊ฒ ์ฐพ๊ธฐ ์ํด ์ถ์ฒ )
- ์ฉ๋๋ณ๋ก ์๊ฐํ ์ ๊ณต ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ง์ด ์ฌ์ฉ๋๊ณ ์๋์ง ํ์ ๊ฐ๋ฅ
- ๋ด๊ฐ ์๊ฐํ๋ ๋ฒ๋ค ์ต์ ํ : More lighter, Minimize duplication, code Optimization, write only you use
02. ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ๊ณ ๋ คํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์
์์ธ ๋ถ์์ ๋๋ฌํ๊ธฐ ์ , ๊ฐ๋ฐ ๊ณผ์ ์์ ์ ๊ท ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ์ ๋ฒ๋ค ํผ๋์(https://bundlephobia.com/) ์ฌ์ดํธ์ ์ ์ํ์ฌ ๋์ผํ ๊ธฐ๋ฅ์ ์ง์ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์๋์ง ์ฉ๋์ ๋น๊ตํ๊ณ , ์์กด์ฑ์ด๋ ํธ๋ฆฌ์์ดํน ์ง์ ์ฌ๋ถ, ๊ฐ ๋ฒ๋ค์ฌ์ด์ฆ ํ์ธํด ๊ฐ๋ฒผ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ ํ ์ ์๋๋ก ๊ณ ๋ คํด์ผํ๋ค. (์ด๋ฐ๊ฑธ ๊ณ์ ๊ณ ๋ คํ๋ค๋ณด๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ณ์ด ์๊ฒจ๋ฒ๋ฆฐ๋ค. ์ฌ์ค ๋ชจ๋ ๊ฑด ์์ ์ฝ๋๋ก ํด๊ฒฐํ ์ ์์ผ๋..ใ ๊ทธ๋ผ์๋ ๋์ ์ ์ ์ฃผ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋ํด '๊ณผ์ฐ ํ์ํ๊ฒ์ธ๊ฐ์' ๋ํ ๋ค๋ฐฉ๋ฉด์ ์ธ ๊ณ ๋ฏผ์ด ํ์ํ๋ค.)
03. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค๋ณต ํผํ๊ธฐ
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ๋ง์ถ๊ฑฐ๋ ๋์ผ ๊ธฐ๋ฅํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ณํํด ์ค๋ณต๋ ๊ตฌํ ํผํ ์ ์๋ค.
- ๋ฒ์ ์ด ๋ฌ๋ผ ์ค๋ณต๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํจํค์ง๋งค๋์ npm ์ด๋ yarn๋ฅผ ํ์ฉํด ๊ฐ์ ๊ฐ๋ฅ
- npm์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ํ์ํ ๋ชจ๋ ์์กด์ฑ์ ๊ด๋ฆฌํ๋ ํ์์ด์ง๋ง ์ค๋ณต๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ด๊ฒ ๋๋ฉด ๋ฒ๋ค์ฌ์ด์ฆ๋ ๋ฌผ๋ก node_modules๋ ๊ณผ๋ํ ์ฉ๋์ ์ฐจ์งํ๊ฒ ๋๋ค.
- yarn์ ๊ฒฝ์ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ๊ณผ์ ์์ ์๋ง๊ฒ ์ฒ๋ฆฌํด์ฃผ๋๋ฐ ๋ณด๋ค ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ์ํด yarn dedupelicate ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ด์ฉํด ๋ค์ํ ์ ๋ต์ ํตํด ์ค๋ณต๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ฑฐํด์ค๋ค.
04. ๋ฌด๊ฑฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ํฅ ์ต์ํ
Single Common Chunk๋ ์๋ก์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ถ๊ฐ๋๋ฉด ๋ชจ๋ ํ์ด์ง ์ฉ๋์ด ํ๋ฒ์ ์ฆ๊ฐํ๋ ๋ฌธ์ ์ ์ด ์กด์ฌํ๋ค.
์ด ๋ฌธ์ ์ ์ ํด๊ฒฐํ๊ธฐ ์ํด ํ์ด์ง๋ณ ์ฒญํฌ ํ์ผ์ ์ํฅ ์ต์ํํ์ฌ ์ฌ์ฉ์ ์ด๋์ ๋ฐ๋ผ ํ์ํ ์ฒญํฌ๋ง ๋ฐ์์ฌ ์ ์๋๋ก ๋ถ๋ฆฌํ๋ค.
- ๊ฐ์ ๋ ์ฒญํฌ ํ์ผ ์ข
๋ฅ
- Framework Chunk (ํ๋ ์์ํฌ) : react, react-dom, next ๋ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ
- Commons Chunk (๊ณตํต) : ๋ชจ๋ ํ์ด์ง์์ ์ฌ์ฉํ๋ ์ฝ๋ ๋ชจ์๋ ์ฒญํฌ
- Shared Chunk : 2ํ์ด์ง ์ด์ ๊ณต์ ํ๋ ์ฝ๋ ๋ชจ์๋ ์ฒญํฌ
- Page๋ณ Chunk : ํน์ ํ์ด์ง์์๋ง ์ฌ์ฉํ๋ ์ฒญํฌ
โจ ํ๋ ์์ํฌ์ ๊ณตํต ์ฒญํฌ ํ์ผ์ ๋ชจ๋ ํ์ด์ง์์ ๋ฐ์์ง๋ฉฐ ๋จผ์ ์ง์ ํ ํ์ด์ง์์ ์บ์ฑ๋์ด ํจ์จ์ ์ผ๋ก ๋ฆฌ์์ค ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค.
05. ์ฝ๋ ์คํ๋ฆฌํ
๋๋ถ๋ถ ์นํ์ด์ง๋ ๊ฐ๊ฐ์ ํ์ด์ง๋ณ๋ก ๋๋ ์ ธ์์ด ๋ค๋ฅธ ํ์ด์ง์ ์ฝ๋๊ฐ ์กด์ฌํ ํ์๊ฐ ์๋ค. ํ์ํ ๊ฒ๋ง ๋จ๊ธฐ๋ ๋ชจ๋ ํ์ผ์ ํ๋๋ก ํฉ์น์ง ์๊ณ ๋ฐ๋ก ๋ถ๋ฆฌํ๋ ๊ฒ, ์ด๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ์ ์ํ ํ์ด์ง์ ์ฝ๋๋ง ๋ก๋ํ์ฌ ๋ก๋ฉ์๊ฐ๊ณผ ํธ๋ํฝ ์ค์ด๋ค๊ฒ ํด์ฃผ๋ ํจ๊ณผ๋ฅผ ์ ๊ณตํ๋ค.
๋ฒํผ์ ๋๋ฅด๋ ์์ ์ useState ๊ฐ์ด true๊ฐ ๋๊ณ , <SplitComponent>๊ฐ ๋ ๋๋ง ๋๋ฏ๋ก ๋ก๋ฉ์ ์์ํ๋ ๊ตฌ์กฐ
- import( ) ์ฌ์ฉ
- ํ์ํ ์์ ์ ์ปดํฌ๋ํธ ๋ถ๋ฌ์ค๋๋ก import๋ฅผ ํจ์๋ก ์ฌ์ฉํ๋ฉด, Promise ๋ฅผ ๋ฐํํ๋ค.
- ์ด ํจ์๋ ๋ชจ๋์ ๋น๋๊ธฐ์ ์ผ๋ก CommonJS ํํ๋ก ๋ถ๋ฌ์ค๋, ๋ฐ๋ก default ๋ฅผ ๋ช ์ํด์ฃผ์ด์ผ ํ๋ค
- ๊ฐ๋ฐ์๋๊ตฌ์์ Network ํญ์์ ํ์ธํ๋ฉด ๋ถ๋ฆฌ๋ ์ฒญํฌ ํ์ผ(chunk.js)์ splitting ์ฝ๋๊ฐ ๋ถ๋ฌ์ค๊ฒ ๋๋ค
- import ๋ฅผ ํจ์๋ก ์ฌ์ฉํด์ฃผ๋ฉด, ์นํฉ์ด ์์์ ์ฝ๋๋ฅผ ๋ถ๋ฆฌ๋ฅผ ํ์ฌ ๋ฐ๋ก ์ ์ฅํ๊ณ , import ๊ฐ ํธ์ถ ๋ ๋ ๋ถ๋ฌ์์ ์ฌ์ฉ ํ ์ ์๊ฒ ํด์ค๋ค
import { useState } from "react"; export const App = () => { const [component, setComponent] = useState(null); const onClick = () => { import('์ปดํฌ๋ํธ๊ฒฝ๋ก').then(result => setComponent(result.default)); // 1. ์ปดํฌ๋ํธ ๋ฐฉ์ 1 import('./์ปดํฌ๋ํธ๊ฒฝ๋ก').then(({ default: SplitMe }) => {setSplitMe({SplitMe})}); 1. ์ปดํฌ๋ํธ ๋ฐฉ์ 2 import('./notify').then(({ default: notify }) => {notify()}); // 2. ํจ์ } return ( <div> <button type="button">click me</button> {component && <component />} </div> ); };
- HoC ์์ฑ์ ํตํด splitting ์ปดํฌ๋ํธ ์ฌํ์ฉ
- ์ฝ๋ ์คํ๋ฆฌํ ํ ๋ ๋ฐ๋ณต๋๋ ๋ก์ง์ ํจ์ํ
- ๋ ๊ฐํธํ ์ฝ๋ ์คํ๋ฆฌํ ๋ฐ ๋ก์ง ์ต์ ํ๋ฅผ ๋๋๋ค
import React, { Component } from 'react'; const withSplitting = getComponent => { const [Splitted, setSplitted] = (null); const preload = () => { // Splitted ๊ธฐ๋ณธ๊ฐ์ null์ด์ง๋ง preload ํธ์ถ๋๋ฉด Splitted ๊ฐ ์ค์ ๋๊ณ getComponent().then(({ default: Splitted }) => { setSplitted(Splitted); }); } // ์ฌ๊ธฐ์ getComponent๋ () => import('./SplitMe')์ ํํ๋ก ํจ์๊ฐ ์ ๋ฌ๋์ผ ํ๋ค. const handle = (getComponent) => { getComponent().then(({ default: Splitted }) => { setSplitted(Splitted); }); } // ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋๋ ์์ ์์ Splitted ์ฌ์ฉํ๊ฒ ๋๋ฏ๋ก null ์ด๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ฒ๋จ if (!Splitted) return null; return <Splitted />; }; export default withSplitting;
import React, { Component } from 'react'; import withSplitting from './withSplitting'; // HoC import const SplitMe = withSplitting(() => import('./SplitMe')); // ์คํ๋ฆฌํ ์ฝ๋ ์๋จ์ ์์ฑํด์ฃผ๋ฉด ๋! export const App = () => { const [visible, setVisible] = (false); const handleClick = () => setVisible(true); return ( <div> <button onClick={handleClick}>Click Me</button> {visible && <SplitMe />} </div> ); }
- ๋ผ์ฐํฐ ์์ฑ
import withSplitting from '../withSplitting'; export const Home = withSplitting(() => import('./Home')); export const About = withSplitting(() => import('./About'));
import React, { Component } from 'react'; import { Route, Link } from 'react-router-dom'; import { About, Home } from './pages'; export const App = () => { return ( <div> <Link to="/">Home</Link> <Link to="/about" onMouseOver={About.preload()}> <hr /> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> </div> ); }
- Dymanic Import ์ฌ์ฉ
webpack ์์ ์ง์ํด์ฃผ๊ณ ์๋ ํจ์๋ก ๋ณ๋์ ์ค์ ์์ด ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
๋์ ์ฝ๋ ๋ถํ , lazy-load = ๊ฒ์ผ๋ฅธ ๋ก๋ฉ
๋ฐํ์์์ ํ์ํ module ์ import ๊ฐ๋ฅ
ํ์ด์ง ์ง์ ์์ ํ์ํ ์ต์ํ์ ์ฝ๋๋ง ๋ค์ด๋ฐ์ ์ฒซ ํ์ด์ง์ ์ด๊ธฐ ์ฑ๋ฅ์ฌ๋ฆด ์ ์๋ค
์ฌ์ฉ์๊ฐ ํด๋ฆญํ ๋๋ง๋ค Import ํจ์ผ๋ก์, ๋ถํ ํ์ฌ ๊ด๋ฆฌํ ์ ์๊ฒ ๋๋ค.
Webpack ์์ Dynamic Import ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ babel-plugin-syntax-dynamic-import ํ๋ฌ๊ทธ์ธ์ด ํ์
// babel.config.json { "plugins": ["@babel/plugin-syntax-dynamic-import"] }โ
chunk ํ์ผ ๋ช ์ webpack ์ output ์ ์ธํ ํ ํ์ผ๋ช ์ ๋ฐ๋ผ๊ฐ๋ค
module.exports = { output: { filename: '[name].js', chunkFilename: '[name].chunk.js', }, }
import dynamic form 'next/dynamic'; const PageA = dynamic(() => import('./PageA')); const PageB = dynamic(() => import('./PageB')); // webpackPrefetch : trueโ
- ์นํฉ magic comment ์ด์ฉ์ prefetch ๊ธฐ๋ฅ ์ด์ฉํ ์ ์๋ค.
- ์ฌ์ ๋ก์ด ์๊ฐ์ ๋ฏธ๋ฆฌ ๋ฐ์๋์ด ์ฌ์ฉ์์๊ฒ ์ต์ํ์ ์ง์ฐ ์๊ฐ ์ค ์ ์๋ค.
- ์ ์ ํ DI์ Prefetch ์ด์ฉํด ์ด๊ธฐ ๋ก๋ฉ ์๋๋ฅผ ์ ๋ฐ ๊ฐ๊น์ด ์ค์ผ ์ ์์๋ค.
- React.lazy() + <Suspense> ์ฌ์ฉ
- React.lazy() : ์ปดํฌ๋ํธ ๋๋๋ง์์ ์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ก๋ฉํ๊ฒ ํด์ฃผ๋ ํจ์
- <Suspense> : ์ฝ๋ ์คํ๋ฆฌํ ๋ ์ปดํฌ๋ํธ ๋ก๋ฉ & ๋ก๋ฉ์ ๋ณด์ฌ์ค ์ปดํฌ๋ํธ ์ง์ ๊ฐ๋ฅ
import React, { useState, Suspense, lazy } from "react"; const SplitComponent = lazy(() => import('์ปดํฌ๋ํธ๊ฒฝ๋ก')); export const App = () => { const [visible, setVisible] = useState(false); const onClick = () => {setVisible(prev => !prev)}; return( <div> <button type='button' onClick={onClick}></button> <Suspense fallback={<div>...loading</div>}> {visible && <SplitComponent />} <Suspense/> </div> ); }
- loadable ์ฌ์ฉ
npm i @loadable/component
- ์ฌ์ฉ๋ฒ React.lazy()์ ๋น์ท & <Suspence> ์ฌ์ฉ์์ด ๋ก๋ฉ ํ๋ฉด ๋ฐ ํธ๋ฆฌํ preload ๊ธฐ๋ฅ ์ง์
- ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ๋ง์ฐ์ค๋ฅผ ์ฌ๋ฆฌ๋ฉด ์ปดํฌ๋ํธ ๋ก๋
import { useState } from "react"; import loadable from "@loadable/component"; export const App = () => { const SplitComponent = loadable(() => import('์ปดํฌ๋ํธ ๊ฒฝ๋ก'), {fallback: <div> loading </div>}) const [visible, setVisible] = useState(false); const onClick = () => {setVisible(prev => !prev)}; const onMouseOver = () => {SplitComponent.preload()}; return( <div> <button type='button' onClick={onClick} onMouseOver={onMouseOver}>Click!</button> <Suspense fallback={<div>...loading</div>}> {visible && <SplitComponent />} <Suspense/> </div> ); }
5. react-loadable (๋์ ์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ง์ง ํ์ํ๊ฐ!! ๊ณ ๋ฏผํ๊ธฐ)
import React from 'react';
import Loadable from 'react-loadable';
const Loading = () => {
return <div>๋ก๋ฉ์ค...</div>;
};
// ๋ก๋ฉ์ค์ผ๋ ๋ ๋๋ง ํ ์ปดํฌ๋ํธ๋ฐ๋ก ์ง์ ๊ฐ๋ฅ
export const Home = Loadable({
loader: () => import('./Home'),
loading: Loading
});
export const About = Loadable({
loader: () => import('./About'),
loading: Loading
});
import React, { Component } from 'react';
import { Route, Link } from 'react-router-dom';
import { About, Home } from './pages';
export const App = () => {
const handleMouseOver = () => {About.preload()};
return (
<div>
<Link to="/">Home</Link>
<Link to="/about" onMouseOver={handleMouseOver}>About</Link>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</div>
);
}
6. SSR (Next.js ๊ฐ์ ํ๋ ์์ํฌ ํ์ฉ)
ssr ์์ ์์ ํ์ด์ง ๋จ์๋ก ์ฌ์ฉ์์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ถํ์ ๋ฐ์์ค๋ฉด์ ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ์ค์ผ ์๋ ์๋ค.
react-query์ useQuery์ ์ ์ฌํ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๋ `useResource`๋ฅผ ๋์ ํด ๊ธฐ์กด ์ฝ๋๋ฅผ ๋ง์ด๊ทธ๋ ์ด์ ํด๋ณด๋๊ฒ๋ ์ถ์ฒํ๋ค!
์์ฒ์ค์ด ๋๋ ์๋น์ค๋ฅผ ๋ง์ด๊ทธ๋ ์ด์ ํด์ผ๋ ๊ฒฝ์ฐ ๋น์ฉ์ ์ค์ด๋ ๊ฒ์ ์์ฃผ ์ค์ํ ์ผ์ด๋ฏ๋ก, ํญ์ ์ต์ํ์ ๋ฆฌํฉํ ๋ง ๋ฆฌ์์ค ๋ํด ๊ณ ๋ฏผํ๋ ๊ฒ๋ ๊ฐ๋ฐ์๋ก์ ์ค์ํ ์์ง์ด๋ผ๊ณ ๋๊ปด์ง๋ ํ ์ฃผ์๋ค.
์ฝ๋ ์ต์ ํ์ ๋ํ ๋์ ์๊ฐ
ํ๋ก ํธ ํธ๋ ๋๋ ์ ๋ง ๋ง์ด ๋ฐ๋๊ณ ์ด์ธ์๋ ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ์ค์ผ ์ ์๋ ๋ค์ํ ๋ฐฉ์์ด ์กด์ฌํ๋ค. ๋ณธ์ง์ ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ์ค์ฌ - ์ ์ ์๊ฒ ํ๋ฉด์ด ๊ทธ๋ ค์ง๋ ์๋, ์น์ฌ์ดํธ์ ์ค์ง์ ์ธ ํผํฌ๋จผ์ค ํฅ์์ ์ํ ์์ ์ด๋ค. ์ด์ ๋ถํฐ ์ด๋ค ๋ฐฉ๋ฒ๋ค์ด ์ฐ์ฌ์ ธ ์๋์ง ๊ทธ๊ธธ์ ๊ณต๋ถํด๋ณด๋ฉด ๋ด ๊ธฐ์ค์์์ ์ข์ ๋ฐฉ์๋ฅผ ์ฐพ๊ฒ ๋๋ ๊ฒ ๊ฐ๋ค. ๐โ๏ธ ์ฝ๋๋ฅผ ์ต์ ํํ ์ ์๋ ๋ค์ํ ๋ฐฉ๋ฒ์ ์์ผ๋ก๋ ์์๊ฐ๊ณ , ์ ์ ๊ฐ ๊ธฐ๋ค๋ฆฌ๋ ๊ทธ๋ฆฌ๊ณ ๊ฐ๋ฐ์์ ์๊ฐ์ ์๊ปด์ฃผ๋ ๋๋ฃ๊ฐ ๋๋ฉด ์ข๊ฒ ๋ค :)
๋์์ ์ค ํฌ์คํธ
- ์น ์ ํ๋ฆฌ์ผ์ด์ ํจํค์ง ์ต์ ํ
์ฝ๊ฒ ๋ฐ๋ผํ๋ ํ๋ก ํธ์๋ ์น ์ดํ๋ฆฌ์ผ์ด์ ํจํค์ง ์ต์ ํ
๋ณธ ํฌ์คํธ๋ Next.js ๊ธฐ๋ฐ ํ๋ก์ ํธ์ ํธ๋ฆฌ์ ฐ์ดํน ์งํ ๊ณผ์ ์ ๋ฐ๋ผํ ์ ์๋๋ก ์ค๋ช ๊ณผ ํจ๊ป ์ ๋ฆฌํ ๊ธ์ ๋๋ค. ๋น๋ก ๊ฐ๋ฅํ ๋ชจ๋ ์ต์ ํ๋ฅผ ์งํํ์ง๋ ๋ชปํ์ง๋ง, ๋ฐฉ๋ฒ์ ๋ฌธ์ ๋ ์๋์์ผ๋ฉฐ ๊ฒฐ๊ณผ
velog.io
- React.lazy() & <Suspense>
react.lazy()์ Suspense
์ฝ๋์คํ๋ฆฟ์ด ๋ญ๊ฐ? ๊ทธ๋ฅ ์ง๋์ณค๋ ๋ด์ฉ์ธ๋ฐ ํ๋ฒ ์์๋ณด์์ผ๋ฐ์ ์ผ๋ก lazy๋ฅผ ์ฌ์ฉํ์ง์๊ณ home/ktw๋ก ๋ผ์ฐํ ์ ํ๊ฒ๋๋ฉด ์๋ ๊ทธ๋ฆผ๊ณผ๊ฐ์ด ๋ชจ๋ ํ์ผ์ ๋ฆฌ๋ก๋ฉํ๋ค.ํ์ง๋ง, React.lazy()๋ฅผ ์ฌ์ฉํ๋ฉด
velog.io
Posted by Ang