[react] Effect Hook

Updated:

Categories:

Tags: ,

๐Ÿ“Œ ๊ฐœ์ธ์ ์ธ ๊ณต๊ฐ„์œผ๋กœ ๊ณต๋ถ€๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ๋ณต์Šตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ธ”๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
์ •ํ™•ํ•˜์ง€ ์•Š์€ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ๋ฐ”๋ž๋‹ˆ๋‹ค :๐Ÿ˜ธ
[ํ‹€๋ฆฐ ๋‚ด์šฉ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๋ณต๋ฐ›์œผ์‹ค๊ฑฐ์—์š”]

React์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ fetch๋ฅผ ์‚ฌ์šฉํ•ด API ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์ด๋ฒคํŠธ๋ฅผ ํ™œ์šฉํ•ด DOM ์ง์ ‘ ์กฐ์ž‘ํ•  ๋•Œ Side Effect๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๊ณ  ๋งํ•œ๋‹ค.

Pure Function (์ˆœ์ˆ˜ ํ•จ์ˆ˜)

  • ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋ž€, ์˜ค์ง ํ•จ์ˆ˜์˜ ์ž…๋ ฅ๋งŒ์ด ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค
  • ํ•จ์ˆ˜์˜ ์ž…๋ ฅ์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐ’์ด ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ฒฝ์šฐ, ์ˆœ์ˆ˜ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค.
  • ์ž…๋ ฅ์œผ๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ์ฆ‰, ์ „๋‹ฌ ์ธ์ž๊ฐ€ ์ฃผ์–ด์งˆ ๊ฒฝ์šฐ, ํ•ญ์ƒ ๋˜‘๊ฐ™์€ ๊ฐ’์ด ๋ฆฌํ„ด๋จ์„ ๋ณด์žฅ (๊ณ ๋กœ Math.random()์€ ์ˆœ์ˆ˜ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค)
  • ์ˆœ์ˆ˜ ํ•จ์ˆ˜์—๋Š” ๋„คํŠธ์›Œํฌ ์š”์ฒญ๊ณผ ๊ฐ™์€ Side Effect๊ฐ€ ์—†๋‹ค.
1
2
3
4
5
function upper(str) {
  return str.toUpperCase(); // toUpperCase ๋ฉ”์†Œ๋“œ๋Š” ์›๋ณธ์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (Immutable)
}

upper('hello') // 'HELLO'
  • ์–ด๋–ค ํ•จ์ˆ˜๊ฐ€ fetch API๋ฅผ ์ด์šฉํ•ด AJAX ์š”์ฒญ์„ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ ์ด ํ•จ์ˆ˜๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š”?

    โ‡’ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด ์–ธ์ œ๋‚˜ ๋™์ผํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ, ์™ธ๋ถ€์˜ ์–ด๋– ํ•œ ๊ฐ’์„ ์ฐธ์กฐ(ํ˜ธ์ถœ)ํ•ด์•ผ ํ•ด์„œ ๊ทธ ๊ฐ’์ด ๋‹ฌ๋ผ์ง€๋ฉด ๊ฒฐ๊ณผ๋„ ๋‹ฌ๋ผ์ง€๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ.

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

  • React์˜ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ๋Š”, props๊ฐ€ ์ž…๋ ฅ์œผ๋กœ, JSX Element๊ฐ€ ์ถœ๋ ฅ์œผ๋กœ ๋‚˜๊ฐ„๋‹ค.
  • ์—ฌ๊ธฐ์—๋Š” ๊ทธ ์–ด๋–ค Side Effect๋„ ์—†์œผ๋ฉฐ, ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋กœ ์ž‘๋™ํ•œ๋‹ค.
1
2
3
4
5
6
7
function SingleTweet({ writer, body, createdAt }) {
  return <div>
    <div>{writer}</div>
    <div>{createdAt}</div>
    <div>{body}</div>
  </div>
  }

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

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

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

React๋Š” Side Effect๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ Hook์ธ Effect Hook์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Effect Hook

  • useEffect๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ Side effect๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” Hook
  • useEffect(ํ•จ์ˆ˜, [์ข…์†์„ฑ1, ์ข…์†์„ฑ2, โ€ฆ])
  • useEffect์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” ํ•จ์ˆ˜, ํ•ด๋‹น ํ•จ์ˆ˜ ๋‚ด์—์„œ side effect๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.
  • useEffect์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” ๋ฐฐ์—ด, ๋ฐฐ์—ด์€ ์กฐ๊ฑด์„ ๋‹ด๊ณ  ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์กฐ๊ฑด์€ boolean ํ˜•ํƒœ์˜ ํ‘œํ˜„์‹์ด ์•„๋‹Œ, ์–ด๋–ค ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚  ๋•Œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ํ•ด๋‹น ๋ฐฐ์—ด์—” ์–ด๋–ค ๊ฐ’์˜ ๋ชฉ๋ก์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ด ๋ฐฐ์—ด์„ ํŠน๋ณ„ํžˆ ์ข…์†์„ฑ ๋ฐฐ์—ด์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.
    • ๋นˆ ๋ฐฐ์—ด ๋„ฃ๊ธฐ useEffect(ํ•จ์ˆ˜, []) : ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ์ƒ์„ฑ๋  ๋•Œ๋งŒ effect ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰
    • ์•„๋ฌด๊ฒƒ๋„ ๋„ฃ์ง€ ์•Š๊ธฐ(๊ธฐ๋ณธ ํ˜•ํƒœ) useEffect(ํ•จ์ˆ˜) : ๊ธฐ๋ณธํ˜•ํƒœ,

์‹คํ–‰๋˜๋Š” ์‹œ๊ธฐ

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

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

Hook์„ ์“ธ ๋•Œ ์ฃผ์˜ํ•  ์ 

์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ AJAX ์š”์ฒญ

๋ชฉ๋ก ๋‚ด ํ•„ํ„ฐ๋ง์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘ ๊ฐ€์ง€ ์ ‘๊ทผ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

  1. ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ํ•„ํ„ฐ๋ง: ์ „์ฒด ๋ชฉ๋ก ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋ชฉ๋ก์„ ๊ฒ€์ƒ‰์–ด๋กœ filter ํ•˜๋Š” ๋ฐฉ๋ฒ•
  2. ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ ํ•„ํ„ฐ๋ง: ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€๋กœ API ์š”์ฒญ์„ ํ•  ๋•Œ, ํ•„ํ„ฐ๋งํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋ฐฉ๋ฒ• (๋ณดํ†ต, ์„œ๋ฒ„์— ๋งค๋ฒˆ ๊ฒ€์ƒ‰์–ด์™€ ํ•จ๊ป˜ ์š”์ฒญํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ด์— ํ•ด๋‹นํ•œ๋‹ค.)

    ย  ์žฅ์  ๋‹จ์ 
    ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌ HTTP ์š”์ฒญ์˜ ๋นˆ๋„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค ๋ธŒ๋ผ์šฐ์ €(ํด๋ผ์ด์–ธํŠธ)์˜ ๋ฉ”๋ชจ๋ฆฌ ์ƒ์— ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๊ฒŒ ๋˜๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ์˜ ๋ถ€๋‹ด์ด ๋Š˜์–ด๋‚œ๋‹ค
    ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ ์ฒ˜๋ฆฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„ํ„ฐ๋ง ๊ตฌํ˜„์„ ์ƒ๊ฐํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค ๋นˆ๋ฒˆํ•œ HTTP ์š”์ฒญ์ด ์ผ์–ด๋‚˜๊ฒŒ ๋˜๋ฉฐ, ์„œ๋ฒ„๊ฐ€ ํ•„ํ„ฐ๋ง์„ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ์„œ๋ฒ„๊ฐ€ ๋ถ€๋‹ด์„ ๊ฐ€์ ธ๊ฐ„๋‹ค

AJAX ์š”์ฒญ ๋ณด๋‚ด๊ธฐ

์ž„์˜๋กœ ๊ตฌํ˜„ํ•œ storageUtil.js ๋Œ€์‹ , fetch API๋ฅผ ์จ์„œ ์„œ๋ฒ„์— ์š”์ฒญํ• ๋•Œ,

๋ช…์–ธ์„ ์ œ๊ณตํ•˜๋Š” API์˜ ์—”๋“œํฌ์ธํŠธ๊ฐ€ http://์„œ๋ฒ„์ฃผ์†Œ/proverbs๋ผ๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

1
2
3
4
5
6
7
useEffect(() => {
  fetch(`http://์„œ๋ฒ„์ฃผ์†Œ/proverbs?q=${filter}`)
    .then(resp => resp.json())
    .then(result => {
      setProverbs(result);
    });
}, [filter]);

Loading indicator์˜ ๊ตฌํ˜„

1
2
3
4
const [isLoading, setIsLoading] = useState(true);

// ์ƒ๋žต, LoadingIndicator ์ปดํฌ๋„ŒํŠธ๋Š” ๋ณ„๋„๋กœ ๊ตฌํ˜„ํ–ˆ์Œ์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค
return {isLoading ? <LoadingIndicator /> : <div>๋กœ๋”ฉ ์™„๋ฃŒ ํ™”๋ฉด</div>}

fetch ์š”์ฒญ์˜ ์ „ํ›„๋กœ setIsLoading์„ ์„ค์ •ํ•ด ์ฃผ์–ด ๋ณด๋‹ค ๋‚˜์€ UX๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
8
9
useEffect(() => {
  setIsLoading(true);
  fetch(`http://์„œ๋ฒ„์ฃผ์†Œ/proverbs?q=${filter}`)
    .then(resp => resp.json())
    .then(result => {
      setProverbs(result);
      setIsLoading(false);
    });
}, [filter]);

react ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด ๋‹ค๋ฅธ ๊ธ€ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

Leave a comment