๐ค code splitting
react ํ๋ก์ ํธ๋ฅผ ๋น๋ํ๋ฉด, ๋ชจ๋ ์ฝ๋(์ปดํฌ๋ํธ, ์คํ์ผ)๋ฅผ ํ๋ ๋๋ ์ฌ๋ฌ ๊ฐ์ ํ์ผ๋ก ๋ฌถ๋ ๋ฒ๋ค๋ง ๊ณผ์ ์ ๊ฑฐ์น๊ฒ ๋๋ค.
์ฌ์ฉ์๊ฐ ์ฌ์ดํธ์ ์ ์ํ๋ฉด ์ด ๋ฒ๋ค๋ง๋ ํ์ผ์ ๋ค์ด๋ฐ๋๋ฐ, ์ฌ์ฉ์์๊ฒ ๋น์ฅ ํ์ํ์ง ์์ ํ์ผ๋ค๋ ํจ๊ป ํฌํจ๋์ด ๋ค์ด๋ก๋ ๋๋ค.
๋ฉ์ธ ํ์ด์ง('/')๋ง ์ด์ฉํ๋ ์ฌ์ฉ์๋ '/user', '/setting' ํ์ด์ง ๋ฑ์ ์ฝ๋๊ฐ ํฌํจ๋ ํ์ผ์ ๋ค์ด๋ฐ๋๋ค.
๋ฒ๋ค ์ฌ์ด์ฆ๊ฐ ์ปค์ง๋ฉด ์ด๊ธฐ ๋ก๋ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์๋น์ค์ ์ ์ํฅ์ ๋ผ์น ์ ์๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํ์ํ ์ฝ๋๋ง ๋ค์ด๋ฐ์ ์ ์๊ฒํ๋ code splitting์ ์ ์ฉํด ๋ณผ ์ ์๋ค. react๋ dynamic import๋ฅผ ์ํ lazy() ํจ์๋ฅผ ์ ๊ณตํ๊ณ ์๋ค.
๐ฎ ๋ผ์ฐํธ๋ณ code splitting
import HomePage from './pages/Home/HomePage';
const NotFoundPage = lazy(() => import('./pages/NotFound/NotFoundPage'));
const SearchPage = lazy(() => import('./pages/Search/SearchPage'));
const FeedbackPage = lazy(() => import('./pages/Feedback/FeedbackPage'));
๊ธฐ์กด | lazy ์ ์ฉ |
![]() |
![]() |
๋ฉ์ธ ํ์ด์ง๋ฅผ ์ ์ธํ ๋๋จธ์ง ํ์ด์ง์ lazy ์ ์ฉ ์, js ํ์ผ์ด ์ฌ๋ฌ ํ์ผ๋ก ๋ถํ ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด์ ์ฌ์ฉ์๊ฐ '/search' ์ง์ ์, ๊ฒ์ ํ์ด์ง ์ปดํฌ๋ํธ๋ฅผ ๋คํธ์ํฌ ์์ฒญ์ ํตํด ๋์ ์ผ๋ก ๊ฐ์ ธ์จ๋ค.
๐ฎ Icon code splitting
๋ ์จ ์์ด์ฝ์ ๋ชจ๋ importํ์ฌ DayIcons, NightIcons ๊ฐ์ฒด๋ก ๋งคํํ๊ณ ์๋ค. ์ด๋ก ์ธํด ํ๋ฉด์ ํ์๋์ง ์๋ ์์ด์ฝ(๋น/๋)๋ค๊น์ง ๋ชจ๋ ๋ก๋๋๊ณ ์๋ค.

import DayClearIcon from './DayClearIcon';
import DayCloudyIcon from './DayCloudyIcon';
import DaySnowIcon from './DaySnowIcon';
import NightClearIcon from './NightClearIcon';
import NightCloudyIcon from './NightCloudyIcon';
import NightSnowFlurriesIcon from './NightSnowFlurriesIcon';
import NightSnowIcon from './NightSnowIcon';
(...import ๋ฎ/๋ฐคIcon from '';)
/**
* ์๊ฐ๋๋ณ ๋ ์จ ์์ด์ฝ ํ์
*/
const WeatherIcon = ({ fcstTime, skyStatus, rainType }: WeatherIconProps) => {
const hour = Number(fcstTime.slice(0, 2));
const icons = hour >= 6 && hour <= 18 ? DayIcons : NightIcons;
let Icon;
if (rainType === 'NONE') Icon = icons[skyStatus];
else Icon = icons[rainType];
return Icon ? <Icon /> : <img src='' alt='' />;
};
export default WeatherIcon;
const DayIcons = {
CLEAR: DayClearIcon,
PARTLY_CLOUDY: DayPartlyCloudyIcon,
CLOUDY: DayCloudyIcon,
RAIN: DayRainIcon,
RAIN_DROP: DayRainDropIcon,
RAIN_AND_SNOW: DayRainAndSnowIcon,
RAIN_AND_SNOW_FLURRIES: DayRainAndSnowFlurriesIcon,
SHOWER: DayShowerIcon,
SNOW: DaySnowIcon,
SNOW_FLURRIES: DaySnowFlurriesIcon,
};
const NightIcons = {
CLEAR: NightClearIcon,
PARTLY_CLOUDY: NightPartlyCloudyIcon,
CLOUDY: NightCloudyIcon,
RAIN: NightRainIcon,
RAIN_DROP: NightRainDropIcon,
RAIN_AND_SNOW: NightRainAndSnowIcon,
RAIN_AND_SNOW_FLURRIES: NightRainAndSnowFlurriesIcon,
SHOWER: NightShowerIcon,
SNOW: NightSnowIcon,
SNOW_FLURRIES: NightSnowFlurriesIcon,
};
๋ค์๊ณผ ๊ฐ์ด lazy๋ฅผ ์ ์ฉํ๋ฉด, ํ๋ฉด์ ๋ณด์ฌ์ง๋ ์์ด์ฝ๋ค๋ง ๋ก๋ํ ์ ์๋ค.
const WeatherIcon = ({ fcstTime, skyStatus, rainType }: WeatherIconProps) => {
const hour = Number(fcstTime.slice(0, 2));
const icons = hour >= 6 && hour <= 18 ? DayIcons : NightIcons;
let Icon;
if (rainType === 'NONE') Icon = icons[skyStatus];
else Icon = icons[rainType];
return Icon ? (
<Suspense fallback={<IconLoading $width={24} $height={24} />}>
<Icon />
</Suspense>
) : (
<img src='' alt='' />
);
};
export default WeatherIcon;
const DayIcons = {
CLEAR: lazy(() => import('./DayClearIcon')),
PARTLY_CLOUDY: lazy(() => import('./DayPartlyCloudyIcon')),
CLOUDY: lazy(() => import('./DayCloudyIcon')),
RAIN: lazy(() => import('./DayRainIcon')),
RAIN_DROP: lazy(() => import('./DayRainDropIcon')),
RAIN_AND_SNOW: lazy(() => import('./DayRainAndSnowIcon')),
RAIN_AND_SNOW_FLURRIES: lazy(() => import('./DayRainAndSnowFlurriesIcon')),
SHOWER: lazy(() => import('./DayShowerIcon')),
SNOW: lazy(() => import('./DaySnowIcon')),
SNOW_FLURRIES: lazy(() => import('./DaySnowFlurriesIcon')),
};

๋ ์จ ์์ด์ฝ๊ณผ ๋์ผํ๊ฒ ๋์ํ๋ ๋ค๋ฅธ ์์ด์ฝ๋ค์๊ฒ๋ lazy๋ฅผ ์ ์ฉํ ๊ฒฐ๊ณผ, index ๋ฒ๋ค ํ์ผ์ ํฌ๊ธฐ(597kb โ 499.36kb)๊ฐ ์ค์ด๋ค์๋ค.

๐ฉ ๊ฐ์ ๊ฒฐ๊ณผ
๋ธ๋ผ์ฐ์ ๋คํธ์ํฌ ํญ์์ ํ์ธํ ๊ฒฐ๊ณผ
๊ฐ์ ์ | ๊ฐ์ ํ | |
transferred | 629 kB | 558 kB |
resources | 1.9 MB | 1.7 MB |
๐ค code splitting
react ํ๋ก์ ํธ๋ฅผ ๋น๋ํ๋ฉด, ๋ชจ๋ ์ฝ๋(์ปดํฌ๋ํธ, ์คํ์ผ)๋ฅผ ํ๋ ๋๋ ์ฌ๋ฌ ๊ฐ์ ํ์ผ๋ก ๋ฌถ๋ ๋ฒ๋ค๋ง ๊ณผ์ ์ ๊ฑฐ์น๊ฒ ๋๋ค.
์ฌ์ฉ์๊ฐ ์ฌ์ดํธ์ ์ ์ํ๋ฉด ์ด ๋ฒ๋ค๋ง๋ ํ์ผ์ ๋ค์ด๋ฐ๋๋ฐ, ์ฌ์ฉ์์๊ฒ ๋น์ฅ ํ์ํ์ง ์์ ํ์ผ๋ค๋ ํจ๊ป ํฌํจ๋์ด ๋ค์ด๋ก๋ ๋๋ค.
๋ฉ์ธ ํ์ด์ง('/')๋ง ์ด์ฉํ๋ ์ฌ์ฉ์๋ '/user', '/setting' ํ์ด์ง ๋ฑ์ ์ฝ๋๊ฐ ํฌํจ๋ ํ์ผ์ ๋ค์ด๋ฐ๋๋ค.
๋ฒ๋ค ์ฌ์ด์ฆ๊ฐ ์ปค์ง๋ฉด ์ด๊ธฐ ๋ก๋ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์๋น์ค์ ์ ์ํฅ์ ๋ผ์น ์ ์๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํ์ํ ์ฝ๋๋ง ๋ค์ด๋ฐ์ ์ ์๊ฒํ๋ code splitting์ ์ ์ฉํด ๋ณผ ์ ์๋ค. react๋ dynamic import๋ฅผ ์ํ lazy() ํจ์๋ฅผ ์ ๊ณตํ๊ณ ์๋ค.
๐ฎ ๋ผ์ฐํธ๋ณ code splitting
import HomePage from './pages/Home/HomePage';
const NotFoundPage = lazy(() => import('./pages/NotFound/NotFoundPage'));
const SearchPage = lazy(() => import('./pages/Search/SearchPage'));
const FeedbackPage = lazy(() => import('./pages/Feedback/FeedbackPage'));
๊ธฐ์กด | lazy ์ ์ฉ |
![]() |
![]() |
๋ฉ์ธ ํ์ด์ง๋ฅผ ์ ์ธํ ๋๋จธ์ง ํ์ด์ง์ lazy ์ ์ฉ ์, js ํ์ผ์ด ์ฌ๋ฌ ํ์ผ๋ก ๋ถํ ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด์ ์ฌ์ฉ์๊ฐ '/search' ์ง์ ์, ๊ฒ์ ํ์ด์ง ์ปดํฌ๋ํธ๋ฅผ ๋คํธ์ํฌ ์์ฒญ์ ํตํด ๋์ ์ผ๋ก ๊ฐ์ ธ์จ๋ค.
๐ฎ Icon code splitting
๋ ์จ ์์ด์ฝ์ ๋ชจ๋ importํ์ฌ DayIcons, NightIcons ๊ฐ์ฒด๋ก ๋งคํํ๊ณ ์๋ค. ์ด๋ก ์ธํด ํ๋ฉด์ ํ์๋์ง ์๋ ์์ด์ฝ(๋น/๋)๋ค๊น์ง ๋ชจ๋ ๋ก๋๋๊ณ ์๋ค.

import DayClearIcon from './DayClearIcon';
import DayCloudyIcon from './DayCloudyIcon';
import DaySnowIcon from './DaySnowIcon';
import NightClearIcon from './NightClearIcon';
import NightCloudyIcon from './NightCloudyIcon';
import NightSnowFlurriesIcon from './NightSnowFlurriesIcon';
import NightSnowIcon from './NightSnowIcon';
(...import ๋ฎ/๋ฐคIcon from '';)
/**
* ์๊ฐ๋๋ณ ๋ ์จ ์์ด์ฝ ํ์
*/
const WeatherIcon = ({ fcstTime, skyStatus, rainType }: WeatherIconProps) => {
const hour = Number(fcstTime.slice(0, 2));
const icons = hour >= 6 && hour <= 18 ? DayIcons : NightIcons;
let Icon;
if (rainType === 'NONE') Icon = icons[skyStatus];
else Icon = icons[rainType];
return Icon ? <Icon /> : <img src='' alt='' />;
};
export default WeatherIcon;
const DayIcons = {
CLEAR: DayClearIcon,
PARTLY_CLOUDY: DayPartlyCloudyIcon,
CLOUDY: DayCloudyIcon,
RAIN: DayRainIcon,
RAIN_DROP: DayRainDropIcon,
RAIN_AND_SNOW: DayRainAndSnowIcon,
RAIN_AND_SNOW_FLURRIES: DayRainAndSnowFlurriesIcon,
SHOWER: DayShowerIcon,
SNOW: DaySnowIcon,
SNOW_FLURRIES: DaySnowFlurriesIcon,
};
const NightIcons = {
CLEAR: NightClearIcon,
PARTLY_CLOUDY: NightPartlyCloudyIcon,
CLOUDY: NightCloudyIcon,
RAIN: NightRainIcon,
RAIN_DROP: NightRainDropIcon,
RAIN_AND_SNOW: NightRainAndSnowIcon,
RAIN_AND_SNOW_FLURRIES: NightRainAndSnowFlurriesIcon,
SHOWER: NightShowerIcon,
SNOW: NightSnowIcon,
SNOW_FLURRIES: NightSnowFlurriesIcon,
};
๋ค์๊ณผ ๊ฐ์ด lazy๋ฅผ ์ ์ฉํ๋ฉด, ํ๋ฉด์ ๋ณด์ฌ์ง๋ ์์ด์ฝ๋ค๋ง ๋ก๋ํ ์ ์๋ค.
const WeatherIcon = ({ fcstTime, skyStatus, rainType }: WeatherIconProps) => {
const hour = Number(fcstTime.slice(0, 2));
const icons = hour >= 6 && hour <= 18 ? DayIcons : NightIcons;
let Icon;
if (rainType === 'NONE') Icon = icons[skyStatus];
else Icon = icons[rainType];
return Icon ? (
<Suspense fallback={<IconLoading $width={24} $height={24} />}>
<Icon />
</Suspense>
) : (
<img src='' alt='' />
);
};
export default WeatherIcon;
const DayIcons = {
CLEAR: lazy(() => import('./DayClearIcon')),
PARTLY_CLOUDY: lazy(() => import('./DayPartlyCloudyIcon')),
CLOUDY: lazy(() => import('./DayCloudyIcon')),
RAIN: lazy(() => import('./DayRainIcon')),
RAIN_DROP: lazy(() => import('./DayRainDropIcon')),
RAIN_AND_SNOW: lazy(() => import('./DayRainAndSnowIcon')),
RAIN_AND_SNOW_FLURRIES: lazy(() => import('./DayRainAndSnowFlurriesIcon')),
SHOWER: lazy(() => import('./DayShowerIcon')),
SNOW: lazy(() => import('./DaySnowIcon')),
SNOW_FLURRIES: lazy(() => import('./DaySnowFlurriesIcon')),
};

๋ ์จ ์์ด์ฝ๊ณผ ๋์ผํ๊ฒ ๋์ํ๋ ๋ค๋ฅธ ์์ด์ฝ๋ค์๊ฒ๋ lazy๋ฅผ ์ ์ฉํ ๊ฒฐ๊ณผ, index ๋ฒ๋ค ํ์ผ์ ํฌ๊ธฐ(597kb โ 499.36kb)๊ฐ ์ค์ด๋ค์๋ค.

๐ฉ ๊ฐ์ ๊ฒฐ๊ณผ
๋ธ๋ผ์ฐ์ ๋คํธ์ํฌ ํญ์์ ํ์ธํ ๊ฒฐ๊ณผ
๊ฐ์ ์ | ๊ฐ์ ํ | |
transferred | 629 kB | 558 kB |
resources | 1.9 MB | 1.7 MB |