๐Ÿ’ป ์„ฑ๋Šฅ ์ตœ์ ํ™”(feat. ๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ)

waterglassesยท2022๋…„ 11์›” 28์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
47/50
post-thumbnail

โš ๏ธ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์€ ์˜คํƒ€๋‚˜ ์ž˜๋ชป๋œ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ๋ฅผ ํ™œ์šฉํ•˜์„ธ์š”

๊ธฐ๋ณธ์ ์œผ๋กœ React์—๋Š” ์œ ์šฉํ•œ ๊ฒฝ๊ณ ๊ฐ€ ๋งŽ์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค. ๊ฒฝ๊ณ ๋Š” React๋ฅผ ๋” ํฌ๊ณ  ๋Š๋ฆฌ๊ฒŒ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์„ ๋ฐฐํฌํ•  ๋•Œ ํ”„๋Ÿฌ๋•์…˜ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์•ฑ์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๊ฐœ๋ฐœ ๋ชจ๋“œ, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐฐํฌํ•  ๋•Œ๋Š” ํ”„๋กœ๋•์…˜ ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

Create React App

npm run build

๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ํ”„๋กœ์ ํŠธ์˜ build/ ํด๋”์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด์ง„๋‹ค.

๋‹จ์ผ ํŒŒ์ผ ๋นŒ๋“œ

React ๋ฐ React DOM์˜ ํ”„๋กœ๋•์…˜ ์ค€๋น„ ๋ฒ„์ „์„ ๋‹จ์ผ ํŒŒ์ผ๋กœ ์ œ๊ณตํ•œ๋‹ค.

<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

Brunch

๊ฐ€์žฅ ํšจ์œจ์ ์ธ Brunch ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ๋ฅผ ์œ„ํ•ด tenser-brunch ๋ฅผ ์„ค์น˜ํ•ด์„œ ๋นŒ๋“œ ๊ฐ€๋Šฅ

# npm์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด
npm install --save-dev terser-brunch

# Yarn์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด
yarn add --dev terser-brunch

๊ทธ ์™ธ๋กœ Browserify, Rollup, , webpack ๋“ฑ์ด ์žˆ๋‹ค.

Devtools Profiler๋กœ ์ปดํฌ๋„ŒํŠธ ํ”„๋กœํŒŒ์ผ๋ง

๊ธด ๋ชฉ๋ก ๊ฐ€์ƒํ™”ํ•˜์„ธ์š”

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ธด ๋ชฉ๋ก์„ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒจ์šฐ windowing ์ด๋ผ๋Š” ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

์ด ๊ธฐ๋ฒ•์€ ์ฃผ์–ด์ง„ ์‹œ๊ฐ„์— ๋ชฉ๋ก์˜ ๋ถ€๋ถ„ ๋ชฉ๋ก๋งŒ๋ Œ๋”๋งํ•˜๋ฉฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„๊ณผ ์ƒ์„ฑ๋œ DOM ๋…ธ๋“œ์˜ ์ˆ˜๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

react-window์™€ react-virtualized๋Š” ๋„๋ฆฌ ์•Œ๋ ค์ง„ windowing ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ป. ๋ชฉ๋ก, ๊ทธ๋ฆฌ๋“œ ๋ฐ ํ‘œ ํ˜•์‹ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

์žฌ์กฐ์ •์„ ํ”ผํ•˜์„ธ์š”

์ปดํฌ๋„ŒํŠธ์˜ prop์ด๋‚˜ state๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด React๋Š” ์ƒˆ๋กœ ๋ฐ˜ํ™˜๋œ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ด์ „์— ๋ Œ๋”๋ง๋œ ์—˜๋ฆฌ๋จผํŠธ์™€ ๋น„๊ตํ•ด์„œ ์‹ค์ œ DOM ์—…๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ๊ฐ™์ง€ ์•Š์„ ๊ฒฝ์šฐ React๋Š” DOM์„ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

React๊ฐ€ ๋ณ€๊ฒฝ๋œ DOM ๋…ธ๋“œ๋งŒ ์—…๋ฐ์ดํŠธํ•˜๋”๋ผ๋„ ๋ฆฌ๋ Œ๋”๋ง์—๋Š” ์—ฌ์ „ํžˆ ๋‹ค์†Œ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—” ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์ง€๋งŒ ์†๋„ ์ €ํ•˜๊ฐ€ ๋ˆˆ์— ๋„๋Š” ๊ฒฝ์šฐ shouldComponentUpdate๋กœ ์ด ๊ธฐ๋Šฅ์„ ๋ฌด์‹œํ•จ์œผ๋กœ์จ ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

sholudComponentUpdate In Action

SCU๋Š”ย shouldComponentUpdate๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ,ย vDOMEq๋Š” React ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ๋™์ผํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ์›์˜ ์ƒ‰์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

shouldComponentUpdate๋Š” C2์— ๋ฟŒ๋ฆฌ๋ฅผ ๋‘” ํ•˜์œ„ํŠธ๋ฆฌ์—์„œย false๋ฅผ ๋ฐ˜ํ™˜ โ‡’ C4 ๋ฐ C5์—์„œย shouldComponentUpdate๋ฅผ ํ˜ธ์ถœํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

C1๊ณผ C3์˜ ๊ฒฝ์šฐย shouldComponentUpdate๊ฐ€ย true๋ฅผ ๋ฐ˜ํ™˜ โ†’ React๊ฐ€ ํŠธ๋ฆฌ์˜ ๊ฐ€์žฅ ํ•˜์œ„์— ๊ฐ€์„œ ํ™•์ธ โ†’ C6์˜ ๊ฒฝ์šฐย shouldComponentUpdate๋Š”ย true๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ๊ณ  ๋ Œ๋”๋ง ๋œ ์—˜๋ฆฌ๋จผํŠธ๋Š” ๋™์ผํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— React๋Š” DOM์„ ์—…๋ฐ์ดํŠธ, C8์˜ ๊ฒฝ์šฐ ์ด์ „์— ๋ Œ๋”๋ง ๋œ React ์—˜๋ฆฌ๋จผํŠธ์™€ ๋™์ผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— DOM์„ ์—…๋ฐ์ดํŠธํ•  ํ•„์š”๊ฐ€ ์—†์Œ

๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค์ง€ ์•Š์Œ์œผ๋กœ์จ ์–ป๋Š” ํšจ๊ณผ

์ด ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•์€ props์™€ state๋กœ ์‚ฌ์šฉ์ค‘์ธ ๊ฐ’์˜ ๋ณ€๊ฒฝ์„ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

class ListOfWords extends React.PureComponent {
  render() {
    return <div>{this.props.words.join(',')}</div>;
  }
}

class WordAdder extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      words: ['marklar']
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // This section is bad style and causes a bug
    const words = this.state.words;
    words.push('marklar');
    this.setState({words: words});
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick} />
        <ListOfWords words={this.state.words} />
      </div>
    );
  }
}

์œ„์™€ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” PureComponent๊ฐ€ย this.props.words์˜ ์ด์ „ ๊ฐ’๊ณผ ์ƒˆ๋กœ์šด ๊ฐ’์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋น„๊ตํ•˜์—ฌ ๋ฐฐ์—ด์˜ ์‹ค์ œ ๋‹จ์–ด๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค ํ•˜๋”๋ผ๋„ ๋ Œ๋”๋ง์ด ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด์„œ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

handleClick() {
  this.setState(state => ({
    words: state.words.concat(['marklar'])
  }));
}


handleClick() {
  this.setState(state => ({
    words: [...state.words, 'marklar'],
  }));
};

๐Ÿ”ฅ ๋Š๋‚€์ 

ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ๋ฅผ ํ™œ์šฉํ•ด์„œ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์•Œ๊ณ  ์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ๋งŽ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜๋‹ค. ๋˜ํ•œ sholudComponentUpdate๋ฅผ ํ™œ์šฉํ•ด์„œ ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ๋„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

Refer

profile
๋งค ์ˆœ๊ฐ„ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

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