[๐Ÿ’ป ์ฝ”๋“œ์Šคํ…Œ์ด์ธ  FE 44๊ธฐ] React ์‹ฌํ™” - Custom Hooks, Code Spliting

JiEunยท2023๋…„ 5์›” 22์ผ
0
post-thumbnail

โœ”๏ธ ์‹œ์ž‘

Custom Hooks, ์ฝ”๋“œ ๋ถ„ํ• ์— ๋Œ€ํ•ด ํ•™์Šตํ–ˆ๋‹ค.


๐Ÿ“ ๋ฐฐ์šด ๊ฒƒ

Custom Hooks

  • ๊ฐœ๋ฐœ์ž๊ฐ€ ์Šค์Šค๋กœ ์ปค์Šคํ…€ํ•œ Hook์„ ์˜๋ฏธํ•œ๋‹ค.
    - ์ด๋ฅผ ์ด์šฉํ•ด ๋ฐ˜๋ณต๋˜๋Š” ๋กœ์ง์„ ํ•จ์ˆ˜๋กœ ๋ฝ‘์•„๋‚ด์–ด ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฃผ๋กœ ์—ฌ๋Ÿฌ url์„ fetchํ•  ๋•Œ, ์—ฌ๋Ÿฌ input์— ์˜ํ•œ ์ƒํƒœ ๋ณ€๊ฒฝ ๋“ฑ ๋ฐ˜๋ณต๋˜๋Š” ๋กœ์ง์„ ๋™์ผํ•œ ํ•จ์ˆ˜์—์„œ ์ž‘๋™ํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

์žฅ์ 

  • ์ƒํƒœ๊ด€๋ฆฌ ๋กœ์ง์˜ ์žฌํ™œ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ํด๋ž™์Šค ์ปดํฌ๋„ŒํŠธ ๋ณด๋‹ค ์ ์€ ์–‘์˜ ์ฝ”๋“œ๋กœ ๋™์ผํ•œ ๋กœ์ง์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜ํ˜•์œผ๋กœ ์ž‘์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณด๋‹ค ๋ช…๋ฃŒํ•˜๋‹ค.
  • ์ผ๋ฐ˜ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋Š” React๋‚ด๊ฐ€ Hook์„ ๋ถˆ๋Ÿฌ ์‚ฌ์šฉํ•  ์—†์ง€๋งŒ Custom Hook์€ ๊ฐ€๋Šฅํ•˜๋‹ค.

์‚ฌ์šฉ ๊ทœ์น™

  • Custom Hook ์ •์˜ ํ•  ๋•Œ๋Š” ํ•จ์ˆ˜ ์ด๋ฆ„ ์•ž์— use๋ฅผ ๋ถ€์—ฌ์•ผ ํ•œ๋‹ค.
  • ๋Œ€๊ฐœ์˜ ๊ฒฝ์šฐ ํ”„๋กœ์ ํŠธ ๋‚ด์˜ hooks ๋””๋ ‰ํ† ๋ฆฌ์— Custom Hook์„ ์œ„์น˜ํ•œ๋‹ค.
  • Custom Hook ๋งŒ๋“ค ๋•Œ ํ•จ์ˆ˜๋Š” ์กฐ๊ฑด๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ์—ฌ์•ผํ•œ๋‹ค. (retrun ํ•˜๋Š” ๊ฐ’์€ ์กฐ๊ฑด๋ถ€์—ฌ์„œ๋Š” ์•ˆ๋œ๋‹ค.)

๊ฐ™์€ Custom Hook์„ ์‚ฌ์šฉํ–ˆ๋‹ค๊ณ  ๊ฐ™์€ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š”๊ฒŒ ์•„๋‹Œ ๋กœ์ง๋งŒ ๊ณต์œ ํ•œ๋‹ค. ์ƒํƒœ๋Š” ๊ฐ ์ปดํฌ๋„ŒํŠธ ๋งˆ๋‹ค ๋…์ง‘์ ์„ ์ •์˜๋œ๋‹ค.

//fetch ์ „์šฉ Hook์„ ๋งŒ๋“ค์–ด url์„ ์ธ์ž๋กœ ๋ฐ›์•„  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
export default function useFetch(url){
    //๋‹ค๋ฅธ ํ•จ์ˆ˜์™€ ๋‹ค๋ฅด๊ฒŒ ๋‚ด๋ถ€์— hook์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
	const [data, setData] = useState();
    useEffect(() => {
    	fetch(url)
      	.then(res => {
        	return res.json();
        })
      	.then(data => {
        	setData(data);
        });
    }, [url]);
  //data(ํ•ด๋‹น ๊ฐ’)์„ ๋ฐ˜ํ™˜ํ•ด ์ฃผ์–ด์•ผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  return data;
}
.
.
.
// API ์ฃผ์†Œ๋งŒ ๋ณ€๊ฒฝํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
import useFetch from "๊ฒฝ๋กœ"
const data = useFeuch("API ์ฃผ์†Œ")

์ฝ”๋“œ๋ถ„ํ•  (Code Spliting)

  • React๋Š” SPA(Single-Page-Application)์ด๋‹ค. ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ ๊นŒ์ง€ ํ•œ ๋ฒˆ์— ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์ฒซ ํ™”๋ฉด์ด ๋ Œ๋”๋ง ๋  ๋•Œ ๊นŒ์ง€์˜ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค.
    (์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ๋‚˜์ค‘์— ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ ๋ถ„ํ•  ๊ฐœ๋…์ด ๋„์ž… ๋˜์—ˆ๋‹ค.)

static import(์ •์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ)?

  • ์ฝ”๋“œ ์ตœ์ƒ์œ„์— import๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ/ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

React์—์„œ ์ฝ”๋“œ๋ถ„ํ•  ๋ฐฉ๋ฒ•์€ dynamic(๋™์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ)์ด๋‹ค.

  • ์ฝ”๋“œ ์ค‘๊ฐ„์— ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
form.addEventListener("submit", e => {
  e.preventDefault();
	//๋™์  ๋ถˆ๋Ÿฌ์˜ค๊ธฐ๋Š” ์ด๋Ÿฐ ์‹์œผ๋กœ ์ฝ”๋“œ์˜ ์ค‘๊ฐ„์— ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
  import('library.moduleA')
    .then(module => module.default)
    .then(someFunction())
    .catch(handleError());
});
const someFunction = () => {
    //moduleA๋ฅผ ์—ฌ๊ธฐ์— ์‚ฌ์šฉ
}
  • dynamic import๋Š” thenํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ํ•„์š”ํ•œ ์ฝ”๋“œ๋งŒ ๊ฐ€์ ธ์˜จ๋‹ค.
    ๊ฐ€์ ธ์˜จ ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋ชจ๋“  ํ˜ธ์ถœ์€ ํ•ด๋‹น ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ํ•ด๋‹น ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋ฒˆ๋“ค๋ง ์‹œ ๋ถ„ํ•  ๋œ ์ฝ”๋“œ(์ฒญํฌ)๋ฅผ ์ง€์—ฐ ๋กœ๋”ฉ์‹œํ‚ค๊ฑฐ๋‚˜ ์š”์ฒญ ์‹œ์— ๋กœ๋”ฉํ•  ์ˆ˜ ์žˆ๋‹ค.

dynamic import๋Š” React.lazy์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

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

  • ์•„์ง ๋ Œ๋”๋ง์ด ์ค€๋น„๋˜์ง€ ์•Š์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์„ ๋•Œ ๋กœ๋”ฉ ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๊ณ , ๋กœ๋”ฉ์ด ์™„๋ฃŒ๋˜๋ฉด ๋ Œ๋”๋ง์ด ์ค€๋น„๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
  • Supense ์ปดํฌ๋„ŒํŠธ์˜ fallback prop์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ๋กœ๋”ฉ ํ™”๋ฉด์œผ๋กœ ๋ณด์—ฌ์ค„ React ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋ฐ›์•„๋“ค์ธ๋‹ค. Suspense ์ปดํฌ๋„ŒํŠธ ํ•˜๋‚˜๋กœ ์—ฌ๋Ÿฌ ๊ฐœ์˜ lazy ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.
// suspense ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด import
import { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));

function MyComponent() {
  return (
    // React.lazy๋กœ ๊ฐ์‹ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ Suspense ์ปดํฌ๋„ŒํŠธ์˜ ํ•˜์œ„์— ๋ Œ๋”๋ง
    // Suspense ์ปดํฌ๋„ŒํŠธ ํ•˜์œ„์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ lazy ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋ง ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
		<AnotherComponent />
      </Suspense>
    </div>
  );
}
  • ์›น ํŽ˜์ด์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์ง„์ž…ํ•˜๋Š” ๋‹จ๊ณ„์ธ Route์— ์ด ๋‘ ๊ธฐ๋Šฅ์„ ์ ์šฉ์‹œํ‚ค๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
import { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

// ๋ผ์šฐํ„ฐ๊ฐ€ ๋ถ„๊ธฐ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ฐ ์ปดํฌ๋„ŒํŠธ์— React.lazy๋ฅผ ์‚ฌ์šฉํ•ด import
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  //Route ์ปดํฌ๋„ŒํŠธ๋“ค์„ Suspense๋กœ ๊ฐ์‹ผ ํ›„ ๋กœ๋”ฉ ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉํ•  ์ปดํฌ๋„ŒํŠธ๋ฅผ fallback ์†์„ฑ์œผ๋กœ ์„ค์ •
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  </Router>
);

โœ๏ธ ๋งˆ์น˜๋ฉฐ

Custom Hook์„ ์ด์šฉํ•ด ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์†Œ์Šค๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์•„ ์งˆ ๊ฒƒ ๊ฐ™๋‹ค.
์†”๋กœ ํ”„๋กœ์ ํŠธ ํ–ˆ๋˜ ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋ง ํ•˜๊ธฐ ๋”ฑ ์ข‹์„ ๋“ฏ ์‹ถ๋‹ค.

์ฝ”๋“œ ๋ถ„ํ• ์„ ํ†ตํ•ด ๋ Œ๋”๋ง ์‹œ ๋ถˆํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ๋ Œ๋”๋ง ๋˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋‹จ ์‹œ๊ฐ„์— ๋งŽ์€ ์ •๋ณด๋ฅผ ํ•™์Šตํ•ด์„œ ์ผ๋‹จ ๊ฐ„๋‹จํ•œ ๊ฐœ๋…์ด๋ผ๋„ ํŒŒ์•…ํ•ด ๋‘๋ ค๊ณ  ํ•œ๋‹ค.

profile
๐Ÿ’ป ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋ชฉํ‘œ๋กœ ์„ฑ์žฅ ์ค‘! (์•Œ์•„๋ดค๋˜ ๋‚ด์šฉ ๋“ฑ์„ ์ •๋ฆฌํ•˜๊ธฐ)

0๊ฐœ์˜ ๋Œ“๊ธ€