๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

javascript/[TIL] ๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ 

๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ  - ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ…

728x90

์ด๋ฏธ์ง€ ์ถœ์ฒ˜ - https://velog.io/@elin_me/code-splitting-lls7eaea

๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ์™„์„ฑํ•ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๊ณตํ• ๋•Œ, ๋นŒ๋“œ ์ž‘์—…์„ ๊ฑฐ์ณ์„œ ๋ฐฐํฌํ•ด์•ผ ํ•œ๋‹ค.

๋นŒ๋“œ ์ž‘์—…์œผ๋กœ ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” .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;

 

 

728x90