3 minute read


๐Ÿ‘‰ React์˜ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ

์—ฌํƒœ๊นŒ์ง€ ํ•™์Šตํ•œ React์˜ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š”, props๊ฐ€ ์ž…๋ ฅ์œผ๋กœ, JSX Element๊ฐ€ ์ถœ๋ ฅ์œผ๋กœ ๋‚˜๊ฐ„๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๊ทธ ์–ด๋–ค Side Effect๋„ ์—†์œผ๋ฉฐ, ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋กœ ์ž‘๋™ํ•œ๋‹ค.

function Singletweet({ writer, body, createdAt }) {
  return (
    <div>
      <div>{writer}</div>
      <div>{createdAt}</div>
      <div>{body}</div>
    </div>
  );
}

ํ•˜์ง€๋งŒ ๋ณดํ†ต React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž‘์„ฑํ•  ๋•Œ์—๋Š”, AJAX ์š”์ฒญ์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ LocalStorage ๋˜๋Š” ํƒ€์ด๋จธ์™€ ๊ฐ™์€ React์™€ ์ƒ๊ด€ ์—†๋Š” API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” React์˜ ์ž…์žฅ์—์„œ๋Š” ์ „๋ถ€ Side Effect์ด๋‹ค. React๋Š” Side Effect๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ Hook์ธ Effect Hook์„ ์ œ๊ณตํ•œ๋‹ค.


โ–ถ๏ธ React ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ Side Effect

  • ํƒ€์ด๋จธ ์‚ฌ์šฉ (setTimeout)
  • ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ (fetch API,localStorage)


๐Ÿ‘‰ Effect Hook

useEffect๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ Side Effect๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” Hook์ด๋‹ค.

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

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

  useEffect(() => {
    // ๋ธŒ๋ผ์šฐ์ € API๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌธ์„œ ํƒ€์ดํ‹€์„ ์—…๋ฐ์ดํŠธ
    document.title = `You cliked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

์œ„์˜ ์ฝ”๋“œ๋Š” useEffect๋ฅผ ์‚ฌ์šฉํ•ด ๋ฌธ์„œ์˜ ํƒ€์ดํ‹€์„ ํด๋ฆญ ํšŸ์ˆ˜๊ฐ€ ํฌํ•จ๋œ ๋ฌธ์žฅ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค.

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


โ–ถ๏ธ ์–ธ์ œ ์‹คํ–‰๋ ๊นŒ?

001

  • ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ํ›„ ์ฒ˜์Œ ํ™”๋ฉด์— ๋ Œ๋”๋ง(ํ‘œ์‹œ)
  • ์ปดํฌ๋„ŒํŠธ์— ์ƒˆ๋กœ์šด props๊ฐ€ ์ „๋‹ฌ๋˜๋ฉฐ ๋ Œ๋”๋ง
  • ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ(state)๊ฐ€ ๋ฐ”๋€Œ๋ฉฐ ๋ Œ๋”๋ง

์ด์™€ ๊ฐ™์ด ๋งค๋ฒˆ ์ƒˆ๋กญ๊ฒŒ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ Effect Hook์ด ์‹คํ–‰๋œ๋‹ค.


โ–ถ๏ธ Hook์„ ์“ธ ๋•Œ ์ฃผ์˜ํ•  ์ 

  • ์ตœ์ƒ์œ„์—์„œ๋งŒ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

    ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ ํ˜น์€ ์ค‘์ฒฉ๋œ ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์„  ์•ˆ๋œ๋‹ค. early return์ด ์‹คํ–‰๋˜๊ธฐ ์ „์— ํ•ญ์ƒ React ํ•จ์ˆ˜์˜ ์ตœ์ƒ์œ„์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค. ์ด ๊ทœ์น™์„ ๋”ฐ๋ฅด๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ ๋งˆ๋‹ค ํ•ญ์ƒ ๋™์ผํ•œ ์ˆœ์„œ๋กœ Hook์ด ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ์ ์€ React๊ฐ€ useState์™€ useEffect๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœ๋˜๋Š” ์ค‘์—๋„ Hook์˜ ์ƒํƒœ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

  • ์˜ค์ง React ํ•จ์ˆ˜ ๋‚ด์—์„œ Hook์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

    Hook์„ ์ผ๋ฐ˜์ ์ธ JavaScript ํ•จ์ˆ˜ ๋‚ด์—์„œ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ๋Œ€์‹  ์•„๋ž˜์™€ ๊ฐ™์ด ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

    • React ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ Hook์„ ํ˜ธ์ถœ
    • Custom Hook์—์„œ Hook์„ ํ˜ธ์ถœ

์ด ๊ทœ์น™์„ ์ง€ํ‚ค๋ฉด ์ปดํฌ๋„ŒํŠธ์˜ ๋ชจ๋“  ์ƒํƒœ ๊ด€๋ จ ๋กœ์ง์„ ์†Œ์Šค์ฝ”๋“œ์—์„œ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์ด๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ‘‰ ์กฐ๊ฑด๋ถ€ effect ๋ฐœ์ƒ (dependency array)

useEffect์˜ ๋‘๋ฒˆ์งธ ์ธ์ž๋Š” ๋ฐฐ์—ด์ด๋‹ค. ์ด ๋ฐฐ์—ด์€ ์กฐ๊ฑด์„ ๋‹ด๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋•Œ ์กฐ๊ฑด์€ boolean ํ˜•ํƒœ์˜ ํ‘œํ˜„์‹์ด ์•„๋‹Œ ์–ด๋–ค ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚  ๋•Œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ํ•ด๋‹น ๋ฐฐ์—ด์—” ์–ด๋–ค ๊ฐ’์˜ ๋ชฉ๋ก์ด ๋“ค์–ด๊ฐ„๋‹ค. ์ด ๋ฐฐ์—ด์„ ํŠน๋ณ„ํžˆ ์ข…์†์„ฑ ๋ฐฐ์—ด (dependency array)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

useEffect๋Š” ํ™”๋ฉด์— ์ฒซ ๋ Œ๋”๋ง ๋  ๋•Œ, ๊ทธ๋ฆฌ๊ณ  ์ข…์†์„ฑ ๋ฐฐ์—ด์˜ value ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.


์˜ˆ์ œ

import { useEffect, useState } from "react";
import { getProverbs } from "./storageUtil";

export default function App() {
  const [proverbs, setProverbs] = useState([]);
  const [filter, setFilter] = useState("");
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("์–ธ์ œ effect ํ•จ์ˆ˜๊ฐ€ ๋ถˆ๋ฆด๊นŒ?");
    const result = getProverbs(filter);
    setProvervs(result);
  }, [filter]);

  const handleChange = (e) => {
    setFilter(e.target.value);
  };

  const handleCounterClick = () => {
    setCount(count + 1);
  };

  return (
    <div className="App">
      ํ•„ํ„ฐ
      <input type="text" value={filter} onChange={handleChange} />
      <ul>
        {provervs.map((prvb, i) => (
          <Proverb saying={prvb} key={i} />
        ))}
      </ul>
    </div>
  );
}

function Proverb({ saying }) {
  return <li>{saying}</li>;
}

์œ„ ์˜ˆ์ œ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ธ ์ƒํƒœ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

  • ๋ช…์–ธ ๋ชฉ๋ก (proverbs)
  • ํ•„ํ„ฐ๋งํ•  ๋ฌธ์ž์—ด (filter)
  • ์นด์šดํŠธ (count)

์œ„ ์˜ˆ์ œ๋Š” filter๊ฐ€ ๋ณ€ํ•  ๋•Œ์—๋งŒ effect ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

์นด์šดํŠธ๋ฅผ ์˜ฌ๋ฆฌ๋Š” ๋ฒ„ํŠผ์€ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๊ณ  ์—…๋ฐ์ดํŠธ ๋˜์ง€๋งŒ, ์•„๋ฌด๋ฆฌ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋„ effect ํ•จ์ˆ˜๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค. ์™œ๋ƒํ•˜๋ฉด, ์ข…์†์„ฑ ๋ฐฐ์—ด์—๋Š” filter๋งŒ ์กด์žฌํ•˜๊ณ  count๋Š” ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

โ“ ์นด์šดํŠธ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ์—๋„ effect ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•

useEffect(() => {
  console.log("์–ธ์ œ effect ํ•จ์ˆ˜๊ฐ€ ๋ถˆ๋ฆด๊นŒ?");
  const result = getProverbs(filter);
  setProvervs(result);
}, [filter, count]);

useEffect์˜ ์ข…์†์„ฑ ๋ฐฐ์—ด (dependency array)์— count๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด filter ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ count๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ์—๋„ useEffect ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.


๐Ÿ‘‰ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” Effect ํ•จ์ˆ˜

์ข…์†์„ฑ ๋ชฉ๋ก์— ์•„๋ฌด๋Ÿฐ ์ข…์†์„ฑ๋„ ์—†๋‹ค๋ฉด, ์ฆ‰ ๋‘๋ฒˆ์งธ ์ธ์ž์ธ ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ๋นˆ ๋ฐฐ์—ด ([])๋กœ ๋‘˜ ๊ฒฝ์šฐ์—๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ์ƒ์„ฑ๋  ๋•Œ๋งŒ effect ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

์ด ๊ฒฝ์šฐ๋Š” ๋‘๋ฒˆ์งธ ์ธ์ž๋ฅผ ์•„์˜ˆ ๋„˜๊ธฐ์ง€ ์•Š๋Š” ๊ฒƒ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ๋‘๋ฒˆ์งธ ์ธ์ž๋ฅผ ์•„์˜ˆ ๋„˜๊ธฐ์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜, props๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๊ฑฐ๋‚˜, state(์ƒํƒœ)๊ฐ€ ์—…๋ฐ์ดํŠธ ๋  ๋•Œ effect ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.


์˜ˆ์ œ

useEffect(() => {
  console.log(๋ช‡ ๋ฒˆ ํ˜ธ์ถœ๋ ๊นŒ์š”?)
})

โ†ณ โŒ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜, state๊ฐ€ ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.

useEffect(() => {
  console.log(๋ช‡ ๋ฒˆ ํ˜ธ์ถœ๋ ๊นŒ์š”?)
}, [dep])

โ†ณ โŒ dep์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.

useEffect(() => {
  console.log(๋ช‡ ๋ฒˆ ํ˜ธ์ถœ๋ ๊นŒ์š”?)
}, [])

โ†ณ โœ… ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ์ƒ์„ฑ๋  ๋•Œ๋งŒ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.


Leave a comment