We want to hear from you!Take our 2021 Community Survey!
Support Ukraine ๐Ÿ‡บ๐Ÿ‡ฆ Help Provide Humanitarian Aid to Ukraine.

Using the Effect Hook

Hooks๋Š” React 16.8๋ฒ„์ „์— ์ƒˆ๋กœ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Hook์€ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ state์™€ ๊ฐ™์€ ํŠน์ง•๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Effect Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ side effect๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import React, { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);

  // componentDidMount, componentDidUpdate์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ  useEffect(() => {    // ๋ธŒ๋ผ์šฐ์ € API๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌธ์„œ ํƒ€์ดํ‹€์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.    document.title = `You clicked ${count} times`;  });
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

์œ„์˜ ์ฝ”๋“œ๋Š” ์ด์ „ ํŽ˜์ด์ง€์˜ ์นด์šดํ„ฐ ์˜ˆ์‹œ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ•˜์ง€๋งŒ, ๋ฌธ์„œ์˜ ํƒ€์ดํ‹€์„ ํด๋ฆญ ํšŸ์ˆ˜๊ฐ€ ํฌํ•จ๋œ ๋ฌธ์žฅ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๋”ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ, ๊ตฌ๋…(subscription) ์„ค์ •ํ•˜๊ธฐ, ์ˆ˜๋™์œผ๋กœ React ์ปดํฌ๋„ŒํŠธ์˜ DOM์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ์ด ๋ชจ๋“  ๊ฒƒ์ด side effects์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ธฐ๋Šฅ๋“ค(operations)์„ side effect(ํ˜น์€ effect)๋ผ ๋ถ€๋ฅด๋Š” ๊ฒƒ์ด ์ต์ˆ™ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์•„๋งˆ๋„ ์ด์ „์— ๋งŒ๋“ค์—ˆ๋˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ์œ„์˜ ๊ธฐ๋Šฅ๋“ค์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํŒ

React์˜ class ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ์— ์นœ์ˆ™ํ•˜๋‹ค๋ฉด, useEffect Hook์„ componentDidMount์™€ componentDidUpdate, componentWillUnmount๊ฐ€ ํ•ฉ์ณ์ง„ ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•ด๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

React ์ปดํฌ๋„ŒํŠธ์—๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋‘ ์ข…๋ฅ˜์˜ side effects๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •๋ฆฌ(clean-up)๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ๊ณผ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ. ์ด ๋‘˜์„ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ•ด์•ผ ํ• ์ง€ ์ž์„ธํ•˜๊ฒŒ ์•Œ์•„๋ด…์‹œ๋‹ค.

์ •๋ฆฌ(Clean-up)๋ฅผ ์ด์šฉํ•˜์ง€ ์•Š๋Š” Effects

React๊ฐ€ DOM์„ ์—…๋ฐ์ดํŠธํ•œ ๋’ค ์ถ”๊ฐ€๋กœ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ๋ฆฌํ€˜์ŠคํŠธ, DOM ์ˆ˜๋™ ์กฐ์ž‘, ๋กœ๊น… ๋“ฑ์€ ์ •๋ฆฌ(clean-up)๊ฐ€ ํ•„์š” ์—†๋Š” ๊ฒฝ์šฐ๋“ค์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ˆ๋“ค์€ ์‹คํ–‰ ์ดํ›„ ์‹ ๊ฒฝ ์“ธ ๊ฒƒ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. class์™€ hook์ด ์ด๋Ÿฌํ•œ side effects๋ฅผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ๋น„๊ตํ•ด๋ด…์‹œ๋‹ค.

Class๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ

React์˜ class ์ปดํฌ๋„ŒํŠธ์—์„œ render ๋ฉ”์„œ๋“œ ๊ทธ ์ž์ฒด๋Š” side effect๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋•Œ๋Š” ์•„์ง ์ด๋ฅธ ์‹œ๊ธฐ๋กœ์„œ ์ด๋Ÿฌํ•œ effect๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ React๊ฐ€ DOM์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๋‚œ ์ดํ›„์ž…๋‹ˆ๋‹ค.

React class์—์„œ side effect๋ฅผ componentDidMount์™€ componentDidUpdate์— ๋‘๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์ด ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋กœ ๋Œ์•„์™€์„œ React๊ฐ€ DOM์„ ๋ฐ”๊พธ๊ณ  ๋‚œ ๋’ค ๋ฌธ์„œ ํƒ€์ดํ‹€์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” React counter ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ด…์‹œ๋‹ค.

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {    document.title = `You clicked ${this.state.count} times`;  }  componentDidUpdate() {    document.title = `You clicked ${this.state.count} times`;  }
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

์œ„ ์ฝ”๋“œ์—์„œ class ์•ˆ์˜ ๋‘ ๊ฐœ์˜ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ์— ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋˜๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•ฉ์‹œ๋‹ค

์ด๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ด์ œ ๋ง‰ ๋งˆ์šดํŠธ๋œ ๋‹จ๊ณ„์ธ์ง€ ์•„๋‹ˆ๋ฉด ์—…๋ฐ์ดํŠธ๋˜๋Š” ๊ฒƒ์ธ์ง€์— ์ƒ๊ด€์—†์ด ๊ฐ™์€ side effect๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ฐœ๋…์ ์œผ๋กœ ๋ Œ๋”๋ง ์ดํ›„์—๋Š” ํ•ญ์ƒ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์ˆ˜ํ–‰๋˜๊ธฐ๋ฅผ ๋ฐ”๋ผ๋Š” ๊ฒƒ์ด์ฃ . ํ•˜์ง€๋งŒ React ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋Š” ๊ทธ๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ ๋ณ„๊ฐœ์˜ ๋ฉ”์„œ๋“œ๋กœ ๋ฝ‘์•„๋‚ธ๋‹ค๊ณ  ํ•ด๋„ ์—ฌ์ „ํžˆ ๋‘ ์žฅ์†Œ์—์„œ ํ•จ์ˆ˜๋ฅผ ๋ถˆ๋Ÿฌ๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ useEffect Hook์—์„œ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Hook์„ ์ด์šฉํ•˜๋Š” ์˜ˆ์‹œ

์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ์œ„์—์„œ ์ด๋ฏธ ๋ณด์•˜๋˜ ๊ฒƒ์ด์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ์ข€ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

import React, { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {    document.title = `You clicked ${count} times`;  });
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect๊ฐ€ ํ•˜๋Š” ์ผ์€ ๋ฌด์—‡์ผ๊นŒ์š”? useEffect Hook์„ ์ด์šฉํ•˜์—ฌ ์šฐ๋ฆฌ๋Š” React์—๊ฒŒ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ์ดํ›„์— ์–ด๋–ค ์ผ์„ ์ˆ˜ํ–‰ํ•ด์•ผํ•˜๋Š” ์ง€๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. React๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋„˜๊ธด ํ•จ์ˆ˜๋ฅผ ๊ธฐ์–ตํ–ˆ๋‹ค๊ฐ€(์ด ํ•จ์ˆ˜๋ฅผ โ€˜effectโ€™๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค) DOM ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•œ ์ดํ›„์— ๋ถˆ๋Ÿฌ๋‚ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์œ„์˜ ๊ฒฝ์šฐ์—๋Š” effect๋ฅผ ํ†ตํ•ด ๋ฌธ์„œ ํƒ€์ดํ‹€์„ ์ง€์ •ํ•˜์ง€๋งŒ, ์ด ์™ธ์—๋„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๋ช…๋ นํ˜•(imperative) API๋ฅผ ๋ถˆ๋Ÿฌ๋‚ด๋Š” ์ผ๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

useEffect๋ฅผ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๋ถˆ๋Ÿฌ๋‚ด๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”? useEffect๋ฅผ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ๋‘ ์œผ๋กœ์จ effect๋ฅผ ํ†ตํ•ด count state ๋ณ€์ˆ˜(๋˜๋Š” ๊ทธ ์–ด๋–ค prop์—๋„)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ๋ฒ”์œ„ ์•ˆ์— ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŠน๋ณ„ํ•œ API ์—†์ด๋„ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Hook์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํด๋กœ์ €๋ฅผ ์ด์šฉํ•˜์—ฌ React์— ํ•œ์ •๋œ API๋ฅผ ๊ณ ์•ˆํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

useEffect๋Š” ๋ Œ๋”๋ง ์ดํ›„์— ๋งค๋ฒˆ ์ˆ˜ํ–‰๋˜๋Š” ๊ฑธ๊นŒ์š”? ๋„ค, ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฒซ๋ฒˆ์งธ ๋ Œ๋”๋ง๊ณผ ์ดํ›„์˜ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.(๋‚˜์ค‘์— effect๋ฅผ ํ•„์š”์— ๋งž๊ฒŒ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.) ๋งˆ์šดํŒ…๊ณผ ์—…๋ฐ์ดํŠธ๋ผ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ๋Œ€์‹  effect๋ฅผ ๋ Œ๋”๋ง ์ดํ›„์— ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. React๋Š” effect๊ฐ€ ์ˆ˜ํ–‰๋˜๋Š” ์‹œ์ ์— ์ด๋ฏธ DOM์ด ์—…๋ฐ์ดํŠธ๋˜์—ˆ์Œ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

์ƒ์„ธํ•œ ์„ค๋ช…

effect์— ๋Œ€ํ•ด ์ข€ ๋” ์•Œ์•„๋ณด์•˜์œผ๋‹ˆ ์•„๋ž˜์˜ ์ฝ”๋“œ๋“ค์„ ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });
}

count state ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•œ ๋’ค React์—๊ฒŒ effect๋ฅผ ์‚ฌ์šฉํ•จ์„ ๋งํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. useEffect Hook์— ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์ด ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ effect์ž…๋‹ˆ๋‹ค. ์ด effect ๋‚ด๋ถ€์—์„œ document.title์ด๋ผ๋Š” ๋ธŒ๋ผ์šฐ์ € API๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌธ์„œ ํƒ€์ดํ‹€์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์‹ ์˜ count๋ฅผ ๋ฐ”๋กœ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ React๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ด์šฉํ•œ effect๋ฅผ ๊ธฐ์–ตํ•˜์˜€๋‹ค๊ฐ€ DOM์„ ์—…๋ฐ์ดํŠธํ•œ ์ดํ›„์— ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋งจ ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง์€ ๋ฌผ๋ก  ๊ทธ ์ดํ›„์˜ ๋ชจ๋“  ๋ Œ๋”๋ง์— ๋˜‘๊ฐ™์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ˆ™๋ จ๋œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด useEffect์— ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋“  ๋ Œ๋”๋ง์—์„œ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฑ˜์„์ง€๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ์ด๋Š” ์˜๋„๋œ ๊ฒƒ์œผ๋กœ์„œ, count ๊ฐ’์ด ์ œ๋Œ€๋กœ ์—…๋ฐ์ดํŠธ ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ๊ฑฑ์ • ์—†์ด effect ๋‚ด๋ถ€์—์„œ ๊ทธ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋ถ€๋ถ„์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ๋ Œ๋”๋งํ•˜๋Š” ๋•Œ๋งˆ๋‹ค ๋ชจ๋‘ ์ด์ „๊ณผ ๋‹ค๋ฅธ effect๋กœ ๊ต์ฒดํ•˜์—ฌ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์ ์ด ๋ Œ๋”๋ง์˜ ๊ฒฐ๊ณผ์˜ ํ•œ ๋ถ€๋ถ„์ด ๋˜๊ฒŒ ๋งŒ๋“œ๋Š” ์ ์ธ๋ฐ, ๊ฐ๊ฐ์˜ effect๋Š” ํŠน์ •ํ•œ ๋ Œ๋”๋ง์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŽ˜์ด์ง€์˜ ๋’ท๋ถ€๋ถ„์—์„œ ์ด๊ฒƒ์ด ์™œ ์œ ์šฉํ•œ์ง€์— ๋Œ€ํ•ด์„œ ๋” ์ž์„ธํžˆ ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํŒ

componentDidMount ํ˜น์€ componentDidUpdate์™€๋Š” ๋‹ฌ๋ฆฌ useEffect์—์„œ ์‚ฌ์šฉ๋˜๋Š” effect๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์„ ์ฐจ๋‹จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐ˜์‘์„ฑ์„ ํ–ฅ์ƒํ•ด์ค๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ effect๋Š” ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ”ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ (๋ ˆ์ด์•„์›ƒ์˜ ์ธก์ •๊ณผ ๊ฐ™์€) ๋™๊ธฐ์  ์‹คํ–‰์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” useEffect์™€ ๋™์ผํ•œ API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” useLayoutEffect๋ผ๋Š” ๋ณ„๋„์˜ Hook์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

์ •๋ฆฌ(clean-up)๋ฅผ ์ด์šฉํ•˜๋Š” Effects

์œ„์—์„œ ์ •๋ฆฌ(clean-up)๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์€ side effect๋ฅผ ๋ณด์•˜์ง€๋งŒ, ์ •๋ฆฌ(clean-up)๊ฐ€ ํ•„์š”ํ•œ effect๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ์— ๊ตฌ๋…(subscription)์„ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ์ •๋ฆฌ(clean-up)ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. class์™€ Hook์„ ์‚ฌ์šฉํ•˜๋Š” ๋‘ ๊ฒฝ์šฐ๋ฅผ ๋น„๊ตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Class๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ

React class์—์„œ๋Š” ํ”ํžˆ componentDidMount์— ๊ตฌ๋…(subscription)์„ ์„ค์ •ํ•œ ๋’ค componentWillUnmount์—์„œ ์ด๋ฅผ ์ •๋ฆฌ(clean-up)ํ•ฉ๋‹ˆ๋‹ค. ์นœ๊ตฌ์˜ ์˜จ๋ผ์ธ ์ƒํƒœ๋ฅผ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ๋Š” ChatAPI ๋ชจ๋“ˆ์˜ ์˜ˆ๋ฅผ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ class๋ฅผ ์ด์šฉํ•˜์—ฌ ์ƒํƒœ๋ฅผ ๊ตฌ๋…(subscribe)ํ•˜๊ณ  ๋ณด์—ฌ์ฃผ๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

class FriendStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {    ChatAPI.subscribeToFriendStatus(      this.props.friend.id,      this.handleStatusChange    );  }  componentWillUnmount() {    ChatAPI.unsubscribeFromFriendStatus(      this.props.friend.id,      this.handleStatusChange    );  }  handleStatusChange(status) {    this.setState({      isOnline: status.isOnline    });  }
  render() {
    if (this.state.isOnline === null) {
      return 'Loading...';
    }
    return this.state.isOnline ? 'Online' : 'Offline';
  }
}

componentDidMount์™€ componentWillUnmount๊ฐ€ ์–ด๋–ป๊ฒŒ ๋Œ€์นญ์„ ์ด๋ฃจ๊ณ  ์žˆ๋Š”์ง€๋ฅผ ๋ด…์‹œ๋‹ค. ๋‘ ๊ฐœ์˜ ๋ฉ”์„œ๋“œ ๋‚ด์— ๊ฐœ๋…์ƒ ๋˜‘๊ฐ™์€ effect์— ๋Œ€ํ•œ ์ฝ”๋“œ๊ฐ€ ์žˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๋Š” ์ด๋ฅผ ๋ถ„๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ฃผ์˜

๋ˆˆ์ฐ๋ฏธ๊ฐ€ ์ข‹์€ ๋…์ž๋“ค์€ ์ด ์˜ˆ์‹œ๊ฐ€ ์™„์ „ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” componentDidUpdate๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ˆˆ์น˜์ฑ˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค์Œ ์„น์…˜์—์„œ ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Hook์„ ์ด์šฉํ•˜๋Š” ์˜ˆ์‹œ

์ด์ œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ Hook์„ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ด๋ด…์‹œ๋‹ค.

์ •๋ฆฌ(clean-up)์˜ ์‹คํ–‰์„ ์œ„ํ•ด ๋ณ„๊ฐœ์˜ effect๊ฐ€ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ตฌ๋…(subscription)์˜ ์ถ”๊ฐ€์™€ ์ œ๊ฑฐ๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ๋Š” ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’๊ธฐ ๋•Œ๋ฌธ์— useEffect๋Š” ์ด๋ฅผ ํ•จ๊ป˜ ๋‹ค๋ฃจ๋„๋ก ๊ณ ์•ˆ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. effect๊ฐ€ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด React๋Š” ๊ทธ ํ•จ์ˆ˜๋ฅผ ์ •๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๋•Œ์— ์‹คํ–‰์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {    function handleStatusChange(status) {      setIsOnline(status.isOnline);    }    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);    // effect ์ดํ›„์— ์–ด๋–ป๊ฒŒ ์ •๋ฆฌ(clean-up)ํ•  ๊ฒƒ์ธ์ง€ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.    return function cleanup() {      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);    };  });
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

effect์—์„œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”? ์ด๋Š” effect๋ฅผ ์œ„ํ•œ ์ถ”๊ฐ€์ ์ธ ์ •๋ฆฌ(clean-up) ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  effect๋Š” ์ •๋ฆฌ๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ์ด ๊ตฌ๋…(subscription)์˜ ์ถ”๊ฐ€์™€ ์ œ๊ฑฐ๋ฅผ ์œ„ํ•œ ๋กœ์ง์„ ๊ฐ€๊นŒ์ด ๋ฌถ์–ด๋‘˜ ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ๋…(subscription)์˜ ์ถ”๊ฐ€์™€ ์ œ๊ฑฐ๊ฐ€ ๋ชจ๋‘ ํ•˜๋‚˜์˜ effect๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

React๊ฐ€ effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•˜๋Š” ์‹œ์ ์€ ์ •ํ™•ํžˆ ์–ธ์ œ์ผ๊นŒ์š”? React๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ ํ•ด์ œ๋˜๋Š” ๋•Œ์— ์ •๋ฆฌ(clean-up)๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์œ„์˜ ์˜ˆ์‹œ์—์„œ ๋ณด์•˜๋“ฏ์ด effect๋Š” ํ•œ๋ฒˆ์ด ์•„๋‹ˆ๋ผ ๋ Œ๋”๋ง์ด ์‹คํ–‰๋˜๋Š” ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. React๊ฐ€ ๋‹ค์Œ ์ฐจ๋ก€์˜ effect๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ์ด์ „์˜ ๋ Œ๋”๋ง์—์„œ ํŒŒ์ƒ๋œ effect ๋˜ํ•œ ์ •๋ฆฌํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ฐ”๋กœ ์ด ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฒ„๊ทธ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ์— ์–ด๋–ป๊ฒŒ ๋„์›€์ด ๋˜๋Š”์ง€ ๊ทธ๋ฆฌ๊ณ  ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ effect๋ฅผ ๊ฑด๋„ˆ๋›ฐ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์ด๋‹ค์Œ์œผ๋กœ ๋…ผ์˜ํ•ด๋ด…์‹œ๋‹ค.

์ฃผ์˜

effect์—์„œ ๋ฐ˜๋“œ์‹œ ์œ ๋ช…ํ•จ์ˆ˜(named function)๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ชฉ์ ์„ ๋ถ„๋ช…ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ์ •๋ฆฌ(clean-up)๋ผ๊ณ  ๋ถ€๋ฅด๊ณ  ์žˆ์ง€๋งŒ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ๋ถˆ๋Ÿฌ๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค.

์š”์•ฝ

useEffect๊ฐ€ ์ปดํฌ๋„ŒํŠธ์˜ ๋ Œ๋”๋ง ์ดํ›„์— ๋‹ค์–‘ํ•œ side effects๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Œ์„ ์œ„์—์„œ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. effect์— ์ •๋ฆฌ(clean-up)๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

์ •๋ฆฌ(clean-up)๊ฐ€ ํ•„์š”์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ค ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

์ด์ฒ˜๋Ÿผ effect Hook์€ ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ํ•œ ๊ฐœ์˜ API๋กœ ํ†ตํ•ฉํ•ฉ๋‹ˆ๋‹ค.


effect hook์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ์ถฉ๋ถ„ํžˆ ์ดํ•ดํ–ˆ๊ฑฐ๋‚˜, ๋‚ด์šฉ์ด ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ต๋‹ค๊ณ  ์ƒ๊ฐ๋œ๋‹ค๋ฉด ๋‹ค์Œ ํŽ˜์ด์ง€์˜ Hook์˜ ๊ทœ์น™๋กœ ๋„˜์–ด๊ฐ€๋„ ์ข‹์Šต๋‹ˆ๋‹ค.


effect๋ฅผ ์ด์šฉํ•˜๋Š” ํŒ

์ด์ œ ์ˆ™๋ จ๋œ React ์‚ฌ์šฉ์ž๋“ค์ด๋ผ๋ฉด ๋ณด๋‹ค ๊ถ๊ธˆํ•ดํ•  useEffect์— ๋Œ€ํ•ด ์ข€ ๋” ๊นŠ์ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์ง€๊ธˆ ๋ฐ”๋กœ ์ฝ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, ์–ธ์ œ๋ผ๋„ effect hook์˜ ์ž์„ธํ•œ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋Œ์•„์™€์„œ ์ฝ์–ด๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

ํŒ: ๊ด€์‹ฌ์‚ฌ๋ฅผ ๊ตฌ๋ถ„ํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด Multiple Effect๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

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

class FriendStatusWithCounter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0, isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  handleStatusChange(status) {
    this.setState({
      isOnline: status.isOnline
    });
  }
  // ...

document.title์„ ์„ค์ •ํ•˜๋Š” ๋กœ์ง์ด componentDidMount์™€ componentDidUpdate์— ๋‚˜๋ˆ„์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ๋…(subscription)๋กœ์ง ๋˜ํ•œ componentDidMount์™€ componentWillUnmount์— ๋‚˜๋ˆ„์–ด์ ธ ์žˆ๋„ค์š”. componentDidMount๊ฐ€ ๋‘ ๊ฐ€์ง€์˜ ์ž‘์—…์„ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Hook์„ ์ด์šฉํ•˜์—ฌ ์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? State Hook์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ effect ๋˜ํ•œ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Effect๋ฅผ ์ด์šฉํ•˜์—ฌ ์„œ๋กœ ๊ด€๋ จ์ด ์—†๋Š” ๋กœ์ง๋“ค์„ ๊ฐˆ๋ผ๋†“์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {    document.title = `You clicked ${count} times`;
  });

  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  // ...
}

Hook์„ ์ด์šฉํ•˜๋ฉด ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ์— ๋”ฐ๋ผ์„œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ฝ”๋“œ๊ฐ€ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€์— ๋”ฐ๋ผ ๋‚˜๋ˆŒ ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. React๋Š” ์ปดํฌ๋„ŒํŠธ์— ์‚ฌ์šฉ๋œ ๋ชจ๋“  effect๋ฅผ ์ง€์ •๋œ ์ˆœ์„œ์— ๋งž์ถฐ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์„ค๋ช…: effect๊ฐ€ ์—…๋ฐ์ดํŠธ ์‹œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š” ์ด์œ 

class์— ์ต์ˆ™ํ•˜๋‹ค๋ฉด ์™œ effect ์ •๋ฆฌ(clean-up)๊ฐ€ ๋งˆ์šดํŠธ ํ•ด์ œ๋˜๋Š” ๋•Œ์— ํ•œ๋ฒˆ๋งŒ์ด ์•„๋‹ˆ๋ผ ๋ชจ๋“  ๋ฆฌ๋ Œ๋”๋ง ์‹œ์— ์‹คํ–‰๋˜๋Š”์ง€๊ฐ€ ๊ถ๊ธˆํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋””์ž์ธ์ด ๋ฒ„๊ทธ๊ฐ€ ์ ์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ์— ์–ด๋–ป๊ฒŒ ๋„์›€์ด ๋˜๋Š”์ง€ ๋‹ค์Œ์˜ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ด…์‹œ๋‹ค.

์ด ํŽ˜์ด์ง€์˜ ์œ„์—์„œ ๋ดค๋˜ ์นœ๊ตฌ๊ฐ€ ์˜จ๋ผ์ธ์ธ์ง€ ์•„๋‹Œ์ง€ ํ‘œ์‹œํ•˜๋Š” FriendStatus ์ปดํฌ๋„ŒํŠธ ์˜ˆ์‹œ๋ฅผ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค. class๋Š” this.props๋กœ๋ถ€ํ„ฐ friend.id๋ฅผ ์ฝ์–ด๋‚ด๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋œ ์ดํ›„์— ์นœ๊ตฌ์˜ ์ƒํƒœ๋ฅผ ๊ตฌ๋…ํ•˜๋ฉฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋ฅผ ํ•ด์ œํ•  ๋•Œ์— ๊ตฌ๋…์„ ํ•ด์ง€ํ•ฉ๋‹ˆ๋‹ค.

  componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

๊ทธ๋Ÿฐ๋ฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜์–ด์žˆ๋Š” ๋™์•ˆ friend prop์ด ๋ณ€ํ•œ๋‹ค๋ฉด ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ ๊นŒ์š”? ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค๋ฅธ ์นœ๊ตฌ์˜ ์˜จ๋ผ์ธ ์ƒํƒœ๋ฅผ ๊ณ„์† ํ‘œ์‹œํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฒ„๊ทธ์ธ ๊ฑฐ์ฃ . ๋˜ํ•œ ๋งˆ์šดํŠธ ํ•ด์ œ๊ฐ€ ์ผ์–ด๋‚  ๋™์•ˆ์—๋Š” ๊ตฌ๋… ํ•ด์ง€ ํ˜ธ์ถœ์ด ๋‹ค๋ฅธ ์นœ๊ตฌ ID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋‚˜ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์ด๋Ÿฐ ๊ฒฝ์šฐ๋“ค์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด componentDidUpdate๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentDidUpdate(prevProps) {    // ์ด์ „ friend.id์—์„œ ๊ตฌ๋…์„ ํ•ด์ง€ํ•ฉ๋‹ˆ๋‹ค.    ChatAPI.unsubscribeFromFriendStatus(      prevProps.friend.id,      this.handleStatusChange    );    // ๋‹ค์Œ friend.id๋ฅผ ๊ตฌ๋…ํ•ฉ๋‹ˆ๋‹ค.    ChatAPI.subscribeToFriendStatus(      this.props.friend.id,      this.handleStatusChange    );  }
  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ”ํ•œ ๋ฒ„๊ทธ ์ค‘์˜ ํ•˜๋‚˜๊ฐ€ componentDidUpdate๋ฅผ ์ œ๋Œ€๋กœ ๋‹ค๋ฃจ์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ์—๋Š” Hook์„ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค.

function FriendStatus(props) {
  // ...
  useEffect(() => {
    // ...
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

์ด ๊ฒฝ์šฐ์—๋Š” ๋ฒ„๊ทธ์— ์‹œ๋‹ฌ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.(๋‹ฌ๋ฆฌ ๋ฐ”๊พผ ๊ฒƒ๋„ ์—†๋Š”๋ฐ ๋ง์ด์ฃ .)

useEffect๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— ๋”๋Š” ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ํŠน๋ณ„ํ•œ ์ฝ”๋“œ๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์˜ effect๋ฅผ ์ ์šฉํ•˜๊ธฐ ์ „์— ์ด์ „์˜ effect๋Š” ์ •๋ฆฌ(clean-up)ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ๋…๊ณผ ๊ตฌ๋… ํ•ด์ง€ ํ˜ธ์ถœ์„ ๋ฐ˜๋ณตํ•ด์„œ ๋งŒ๋“ค์–ด๋‚ด๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ๊ฐ€์‹œํ™”ํ•ด๋ด…์‹œ๋‹ค.

// { friend: { id: 100 } } state์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์šดํŠธํ•ฉ๋‹ˆ๋‹ค.
ChatAPI.subscribeToFriendStatus(100, handleStatusChange);     // ์ฒซ๋ฒˆ์งธ effect๊ฐ€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

// { friend: { id: 200 } } state๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // ์ด์ „์˜ effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•ฉ๋‹ˆ๋‹ค.
ChatAPI.subscribeToFriendStatus(200, handleStatusChange);     // ๋‹ค์Œ effect๊ฐ€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

// { friend: { id: 300 } } state๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // ์ด์ „์˜ effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•ฉ๋‹ˆ๋‹ค.
ChatAPI.subscribeToFriendStatus(300, handleStatusChange);     // ๋‹ค์Œ effect๊ฐ€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

// ๋งˆ์šดํŠธ๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // ๋งˆ์ง€๋ง‰ effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•ด์ฃผ๋ฉฐ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ํ”ํžˆ ์—…๋ฐ์ดํŠธ ๋กœ์ง์„ ๋นผ๋จน์œผ๋ฉด์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„๊ทธ๋ฅผ ์˜ˆ๋ฐฉํ•ฉ๋‹ˆ๋‹ค.

ํŒ: Effect๋ฅผ ๊ฑด๋„ˆ๋›ฐ์–ด ์„ฑ๋Šฅ ์ตœ์ ํ™”ํ•˜๊ธฐ

๋ชจ๋“  ๋ Œ๋”๋ง ์ดํ›„์— effect๋ฅผ ์ •๋ฆฌ(clean-up)ํ•˜๊ฑฐ๋‚˜ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋•Œ๋•Œ๋กœ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ์—๋Š” componentDidUpdate์—์„œ prevProps๋‚˜ prevState์™€์˜ ๋น„๊ต๋ฅผ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

componentDidUpdate(prevProps, prevState) {
  if (prevState.count !== this.state.count) {
    document.title = `You clicked ${this.state.count} times`;
  }
}

์ด๋Ÿฌํ•œ ์š”๊ตฌ ์กฐ๊ฑด์€ ํ”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— useEffect Hook API์— ์ด๋ฏธ ๋‚ด์žฌํ•˜์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠน์ • ๊ฐ’๋“ค์ด ๋ฆฌ๋ Œ๋”๋ง ์‹œ์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด React๋กœ ํ•˜์—ฌ๊ธˆ effect๋ฅผ ๊ฑด๋„ˆ๋›ฐ๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. useEffect์˜ ์„ ํƒ์  ์ธ์ˆ˜์ธ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋ฐฐ์—ด์„ ๋„˜๊ธฐ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // count๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งŒ effect๋ฅผ ์žฌ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์œ„์˜ ์˜ˆ์‹œ์—์„œ ์šฐ๋ฆฌ๋Š” [count]๋ฅผ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋„˜๊น๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. count๊ฐ€ 5์ด๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋œ ์ดํ›„์—๋„ ์—ฌ์ „ํžˆ count๋Š” ๋ณ€ํ•จ์—†์ด 5๋ผ๋ฉด React๋Š” ์ด์ „ ๋ Œ๋”๋ง ์‹œ์˜ ๊ฐ’ [5]๋ฅผ ๊ทธ๋‹ค์Œ ๋ Œ๋”๋ง ๋•Œ์˜ [5]์™€ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด ๋‚ด์˜ ๋ชจ๋“  ๊ฐ’์ด ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์—(5 === 5) React๋Š” effect๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์‹์œผ๋กœ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

count๊ฐ€ 6์œผ๋กœ ์—…๋ฐ์ดํŠธ๋œ ๋’ค์— ๋ Œ๋”๋งํ•˜๋ฉด React๋Š” ์ด์ „์— ๋ Œ๋”๋ง๋œ ๊ฐ’ [5]๋ฅผ ๊ทธ๋‹ค์Œ ๋ Œ๋”๋ง ์‹œ์˜ [6]์™€ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ 5 !== 6 ์ด๊ธฐ ๋•Œ๋ฌธ์— React๋Š” effect๋ฅผ ์žฌ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด ๋‚ด์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์ด ์žˆ๋‹ค๋ฉด ๊ทธ์ค‘์˜ ๋‹จ ํ•˜๋‚˜๋งŒ ๋‹ค๋ฅผ์ง€๋ผ๋„ React๋Š” effect๋ฅผ ์žฌ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ •๋ฆฌ(clean-up)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” effect์˜ ๊ฒฝ์šฐ์—๋„ ๋™์ผํ•˜๊ฒŒ ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค.

useEffect(() => {
  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
  return () => {
    ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  };
}, [props.friend.id]); // props.friend.id๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งŒ ์žฌ๊ตฌ๋…ํ•ฉ๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” ๋นŒ๋“œ ์‹œ ๋ณ€ํ™˜์— ์˜ํ•ด ์ž๋™์œผ๋กœ ์ถ”๊ฐ€๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜

์ด ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ฐฐ์—ด์ด ์ปดํฌ๋„ŒํŠธ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋ฐ”๋€Œ๋Š” ๊ฐ’๋“ค๊ณผ effect์— ์˜ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฐ’๋“ค์„ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด์ฃผ์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ˜„์žฌ ๊ฐ’์ด ์•„๋‹Œ ์ด์ „์˜ ๋ Œ๋”๋ง ๋•Œ์˜ ๊ฐ’์„ ์ฐธ๊ณ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•ด์„œ๋Š” ํ•จ์ˆ˜๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•๊ณผ ์˜์กด์„ฑ ๋ฐฐ์—ด์ด ์ž์ฃผ ๋ฐ”๋€” ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€์—์„œ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

effect๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ด๋ฅผ ์ •๋ฆฌ(clean-up)ํ•˜๋Š” ๊ณผ์ •์„ (๋งˆ์šดํŠธ์™€ ๋งˆ์šดํŠธ ํ•ด์ œ ์‹œ์—)๋”ฑ ํ•œ ๋ฒˆ์”ฉ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋นˆ ๋ฐฐ์—ด([])์„ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋„˜๊ธฐ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ React๋กœ ํ•˜์—ฌ๊ธˆ ์—ฌ๋Ÿฌ๋ถ„์˜ effect๊ฐ€ prop์ด๋‚˜ state์˜ ๊ทธ ์–ด๋–ค ๊ฐ’์—๋„ ์˜์กดํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋”ฐ๋ผ์„œ ์žฌ์‹คํ–‰๋˜์–ด์•ผ ํ•  ํ•„์š”๊ฐ€ ์—†์Œ์„ ์•Œ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์˜์กด์„ฑ ๋ฐฐ์—ด์˜ ์ž‘๋™ ๋ฐฉ๋ฒ•์„ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ผ ๋ฟ์ด๋ฉฐ ํŠน๋ณ„ํ•œ ๋ฐฉ๋ฒ•์ธ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

๋นˆ ๋ฐฐ์—ด([])์„ ๋„˜๊ธฐ๊ฒŒ ๋˜๋ฉด, effect ์•ˆ์˜ prop๊ณผ state๋Š” ์ดˆ๊นƒ๊ฐ’์„ ์œ ์ง€ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋นˆ ๋ฐฐ์—ด([])์„ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋„˜๊ธฐ๋Š” ๊ฒƒ์ด ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ componentDidMount์™€ componentWillUnmount ๋ชจ๋ธ์— ๋” ๊ฐ€๊น์ง€๋งŒ, effect์˜ ์žฆ์€ ์žฌ์‹คํ–‰์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋Š” ๋” ๋‚˜์€ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ React๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ค ๊ทธ๋ ค์งˆ ๋•Œ๊นŒ์ง€ useEffect์˜ ์‹คํ–‰์„ ์ง€์—ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์„ ๋”ํ•˜๋Š” ๊ฒƒ์ด ํฐ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

exhaustive-deps ๊ทœ์น™์„ eslint-plugin-react-hooks ํŒจํ‚ค์ง€์— ํฌํ•จํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ์ด ํŒจํ‚ค์ง€๋Š” ์˜์กด์„ฑ์ด ๋ฐ”๋ฅด์ง€ ์•Š๊ฒŒ ์ง€์ •๋˜์—ˆ์„ ๋•Œ ๊ฒฝ๊ณ ํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„

์—ฌ๊ธฐ๊นŒ์ง€ ์˜ค๋Š๋ผ ์ˆ˜๊ณ ๊ฐ€ ๋งŽ์œผ์…จ์Šต๋‹ˆ๋‹ค. ๊ธด ๊ธ€์ด์ง€๋งŒ ๋๊นŒ์ง€ ์ฝ์œผ๋ฉด์„œ ๋งŽ์€ ๊ถ๊ธˆ์ฆ์ด ํ•ด๊ฒฐ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด State Hook๊ณผ Effect Hook์„ ๊ฒฐํ•ฉํ•˜๋ฉด ๋งŽ์€ ๊ฒƒ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. class๋ฅผ ์ด์šฉํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌํ˜„๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋Š” additional Hooks์ด ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋™๊ธฐ์— ์„œ์ˆ ๋˜์–ด์žˆ๋Š” ๋ฌธ์ œ๋“ค์„ Hook์ด ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ effect์˜ ์ •๋ฆฌ(clean-up)๊ฐ€ componentDidUpdate์™€ componentWillUnmount์—์„œ์˜ ์ค‘๋ณต์„ ํ”ผํ•˜๊ณ , ๊ด€๋ จ ์žˆ๋Š” ์ฝ”๋“œ๋“ค์„ ํ•œ๊ณณ์— ๋ชจ์ด๊ฒŒ ํ•˜๋ฉฐ ๋ฒ„๊ทธ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š”์ง€ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ effect๋ฅผ ๊ทธ ๋ชฉ์ ์— ๋”ฐ๋ผ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ•˜๋Š”์ง€๋„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ํ•  ์ˆ˜ ์—†๋Š” ์ผ์ด์—ˆ์ฃ .

์ง€๊ธˆ ์ด ์‹œ์ ์—์„œ ์—ฌ๋Ÿฌ๋ถ„์€ Hook์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ๊ถ๊ธˆํ•ดํ•˜๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ React๋Š” ๋ฆฌ๋ Œ๋”๋ง ์‹œ์— ํŠน์ •ํ•œ useState์˜ ์‹คํ–‰์ด ์–ด๋–ค state ๋ณ€์ˆ˜์— ์ƒ์‘ํ•˜๋Š”์ง€ ์•„๋Š” ๊ฒƒ์ผ๊นŒ์š”? ์–ด๋–ป๊ฒŒ React๋Š” ์ด์ „๊ณผ ๊ทธ๋‹ค์Œ effect๋ฅผ ์—…๋ฐ์ดํŠธ ๋•Œ๋งˆ๋‹ค โ€œ๋งค์น˜์—…ํ•˜๋Š”(์ผ์น˜ํ•˜๋Š”)โ€ ๊ฒƒ์ผ๊นŒ์š”? ์ด์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค์Œ ์žฅ์—์„œ Hook์˜ ์ž‘๋™์— ํ•ต์‹ฌ์ ์ธ Hook์˜ ๊ทœ์น™์„ ํ†ตํ•ด์„œ ๋ฐฐ์›Œ๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Is this page useful?Edit this page