๐Ÿ’ป FE

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์กฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด Effect๋ฅผ ์“ฐ์ง€ ๋งˆ์„ธ์š”

Roy Miller 2025. 5. 24. 16:45

์œ ์ฆˆ ์ดํŽ™ํŠธ ์‚ฌ์šฉ ๋ชฉ์  : ์ปดํฌ๋„ŒํŠธ๋ฅผ React๊ฐ€ ์•„๋‹Œ ์œ„์ ฏ, ๋„คํŠธ์›Œํฌ, ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ € DOM๊ณผ ๊ฐ™์€ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ๋™๊ธฐํ™”

 

์–ด๋–ค ์ฝ”๋“œ๊ฐ€ Effect์— ์žˆ์–ด์•ผ ํ•˜๋Š”์ง€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์žˆ์–ด์•ผ ํ•˜๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ด ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ด์œ ๋ฅผ ์ž๋ฌธํ•ด ๋ณด์„ธ์š”. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ‘œ์‹œ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ์—๋งŒ Effect๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

 

ํ•ต์‹ฌ ํŒจํ„ด:

  1. ๋ Œ๋”๋ง ๋กœ์ง ๋‚ด์—์„œ ํŒŒ์ƒ ์ƒํƒœ ๊ณ„์‚ฐ:
    • ์–ด๋–ค ์ƒํƒœ $A๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ $B ์ƒํƒœ๋„ $A์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•œ๋‹ค๋ฉด, $B๋ฅผ ๋ณ„๋„์˜ useState๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ๋ณด๋‹ค๋Š” $A๋กœ๋ถ€ํ„ฐ ํŒŒ์ƒ๋œ ๊ฐ’์œผ๋กœ ๋ Œ๋”๋ง ๋กœ์ง ๋‚ด์—์„œ ์ง์ ‘ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
    • ์ด๊ฒƒ์€ $B๊ฐ€ $A์˜ ๋ณ€ํ™”์— ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ฐ˜์‘ํ•˜์—ฌ ์žฌ๊ณ„์‚ฐ๋˜์–ด์•ผ ํ•  ๋•Œ ๊ฐ€์žฅ ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
  2. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด์—์„œ ์—ฌ๋Ÿฌ ์ƒํƒœ ๋™์‹œ ์—…๋ฐ์ดํŠธ:
    • ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ(์˜ˆ: ๋ฒ„ํŠผ ํด๋ฆญ, ์ž…๋ ฅ ํ•„๋“œ ๋ณ€๊ฒฝ)์œผ๋กœ ์ธํ•ด ์—ฌ๋Ÿฌ ์ƒํƒœ๊ฐ€ ๋™์‹œ์— ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•  ๋•Œ, ํ•ด๋‹น ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ ๋‚ด์—์„œ set ํ•จ์ˆ˜๋“ค์„ ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜์—ฌ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
    • React๋Š” ์—ฌ๋Ÿฌ set ํ˜ธ์ถœ์„ ํ•˜๋‚˜์˜ ๋ Œ๋”๋ง ๋ฐฐ์น˜(batch)๋กœ ๋ฌถ์–ด ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
  3. ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ๋ฅผ ํ†ตํ•œ ์ด์ „ ์ƒํƒœ ๊ธฐ๋ฐ˜ ์—…๋ฐ์ดํŠธ:
    • ์ด์ „ ์ƒํƒœ ๊ฐ’์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ƒˆ๋กœ์šด ์ƒํƒœ ๊ฐ’์„ ๊ณ„์‚ฐํ•ด์•ผ ํ•  ๋•Œ, set ํ•จ์ˆ˜์— ๊ฐ’์„ ์ง์ ‘ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹  ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ(setCount(prevCount => prevCount + 1))๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

1. props ๋˜๋Š” ๋‹ค๋ฅธ ์ƒํƒœ์— ๊ธฐ๋ฐ˜ํ•œ ์ƒํƒœ ์—…๋ฐ์ดํŠธ

  • ๋ฌธ์ œ์ : firstName๊ณผ lastName์ด๋ผ๋Š” ๋‘ ๊ฐœ์˜ ์ƒํƒœ๊ฐ€ ์žˆ์„ ๋•Œ, ์ด๋“ค๋กœ๋ถ€ํ„ฐ fullName์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ํŒŒ์ƒ์‹œ์ผœ Effect ์•ˆ์—์„œ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • ์™œ Effect๊ฐ€ ๋ถˆํ•„์š”ํ•œ๊ฐ€: fullName์€ firstName๊ณผ lastName์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋‹จ์ˆœํžˆ ๊ณ„์‚ฐ๋˜๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค. Effect๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ถ”๊ฐ€์ ์ธ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜์—ฌ ๋น„ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
  • ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•: fullName์„ ๋ณ„๋„์˜ ์ƒํƒœ๋กœ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ , ๋ Œ๋”๋ง ๋‹จ๊ณ„์—์„œ firstName๊ณผ lastName์œผ๋กœ๋ถ€ํ„ฐ ์ง์ ‘ ๊ณ„์‚ฐํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋” ๋น ๋ฅด๊ณ , ๊ฐ„๋‹จํ•˜๋ฉฐ, ์˜ค๋ฅ˜ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์ด ์ ์Šต๋‹ˆ๋‹ค. -> ์—ฐ์†์ ์ธ ์—…๋ฐ์ดํŠธ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Œ. 

     

    function ProfileEditor() {
      const [firstName, setFirstName] = useState('John');
      const [lastName, setLastName] = useState('Doe');
    
      // ๋ Œ๋”๋ง ์‹œ์ ์— ์ง์ ‘ ๊ณ„์‚ฐ
      const fullName = `${firstName} ${lastName}`;
    
      // ... JSX์—์„œ fullName ์‚ฌ์šฉ
    }
    

 

2. ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๊ณ„์‚ฐ ์บ์‹ฑ

  • ๋ฌธ์ œ์ : todos ๋ชฉ๋ก์„ filter ๊ฐ’์— ๋”ฐ๋ผ ํ•„ํ„ฐ๋งํ•˜์—ฌ visibleTodos๋ฅผ ๋งŒ๋“œ๋Š” ์ƒํ™ฉ์—์„œ, visibleTodos๋ฅผ Effect ์•ˆ์—์„œ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • ์™œ Effect๊ฐ€ ๋ถˆํ•„์š”ํ•œ๊ฐ€: ํ•„ํ„ฐ๋ง ๋กœ์ง(getFilteredTodos)์ด ๊ฐ€๋ฒผ์šด ๊ณ„์‚ฐ์ด๋ผ๋ฉด, Effect ์—†์ด ๋ Œ๋”๋ง ์‹œ์ ์— ์ง์ ‘ ๊ณ„์‚ฐํ•ด๋„ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. Effect๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ์žฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•:
    • ๊ณ„์‚ฐ์ด ๊ฐ€๋ฒผ์šธ ๋•Œ: ๋ Œ๋”๋ง ์‹œ์ ์— getFilteredTodos(todos, filter)์™€ ๊ฐ™์ด ์ง์ ‘ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ๊ณ„์‚ฐ์ด ๋ฌด๊ฑฐ์šธ ๋•Œ: useMemo Hook์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•ฉ๋‹ˆ๋‹ค. useMemo๋Š” todos๋‚˜ filter์™€ ๊ฐ™์€ ์˜์กด์„ฑ ๋ฐฐ์—ด์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ๊ณ„์‚ฐ์„ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์žฌ๊ณ„์‚ฐ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.useMemo๋กœ ๊ฐ์‹ธ๋Š” ํ•จ์ˆ˜๋Š” ๋ Œ๋”๋ง ์ค‘์— ์‹คํ–‰๋˜๋ฏ€๋กœ, ์ˆœ์ˆ˜ํ•œ ๊ณ„์‚ฐ์—๋งŒ ์ž‘๋™.
    import { useMemo } from 'react';
    
    function TodoList({ todos, filter }) {
      // ๊ณ„์‚ฐ์ด ๋ฌด๊ฑฐ์šธ ๋•Œ useMemo๋กœ ์บ์‹ฑ
      const visibleTodos = useMemo(() => getFilteredTodos(todos, filter), [todos, filter]);
    
      // ... JSX์—์„œ visibleTodos ์‚ฌ์šฉ
    }
    

 

3. props ๋ณ€๊ฒฝ ์‹œ ์ƒํƒœ ์ดˆ๊ธฐํ™”

  • ๋ฌธ์ œ์ : ProfilePage ์ปดํฌ๋„ŒํŠธ์—์„œ userId prop์ด ๋ณ€๊ฒฝ๋  ๋•Œ comment ์ƒํƒœ๋ฅผ Effect ์•ˆ์—์„œ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด ์—ญ์‹œ ๋ถˆํ•„์š”ํ•œ ์žฌ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•ฉ๋‹ˆ๋‹ค.
  • ์™œ Effect๊ฐ€ ๋ถˆํ•„์š”ํ•œ๊ฐ€: React๋Š” ์ปดํฌ๋„ŒํŠธ์˜ key prop์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ์™„์ „ํžˆ ์ƒˆ๋กœ ๋งˆ์šดํŠธ(remount)ํ•˜์—ฌ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•: userId๋ฅผ ์ž์‹ ์ปดํฌ๋„ŒํŠธ(์˜ˆ: Profile)์˜ key prop์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด userId๊ฐ€ ๋‹ฌ๋ผ์งˆ ๋•Œ๋งˆ๋‹ค React๊ฐ€ Profile ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋กœ ๊ฐ„์ฃผํ•˜์—ฌ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ์ž๋™์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
    function ProfilePage({ userId }) {
      // userId๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด Profile ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ๋งˆ์šดํŠธ๋˜๋ฉด์„œ ๋‚ด๋ถ€ ์ƒํƒœ๊ฐ€ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.
      return <Profile key={userId} userId={userId} />;
    }
    

 

4. ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ

  • ๋ฌธ์ œ์ : ์‚ฌ์šฉ์ž์˜ ํด๋ฆญ์ด๋‚˜ ์ž…๋ ฅ๊ณผ ๊ฐ™์€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋กœ์ง(์˜ˆ: API ์š”์ฒญ, ์•Œ๋ฆผ ํ‘œ์‹œ)์„ Effect ์•ˆ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • ์™œ Effect๊ฐ€ ๋ถˆํ•„์š”ํ•œ๊ฐ€: ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ๋Š” ์ง์ ‘์ ์ธ ์ƒํ˜ธ์ž‘์šฉ์˜ ๊ฒฐ๊ณผ์ด๋ฉฐ, ์ด์— ๋”ฐ๋ฅธ ๋ถ€์ˆ˜ ํšจ๊ณผ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์•ˆ์—์„œ ์ฆ‰์‹œ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Effect๋Š” ๋ Œ๋”๋ง ์ดํ›„์— ์‹คํ–‰๋˜๋ฏ€๋กœ, ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ์ง€์—ฐ์„ ์ดˆ๋ž˜ํ•˜๊ฑฐ๋‚˜ ๋กœ์ง ํ๋ฆ„์„ ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•: ์‚ฌ์šฉ์ž ์ด๋ฒคํŠธ(ํ–‰๋™)์— ๋Œ€ํ•œ ๋กœ์ง์€ ํ•ด๋‹น ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ง์ ‘ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
     
    function BuyButton({ productId }) {
      const handleClick = () => {
        // ํด๋ฆญ ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ๋ฐ”๋กœ API ํ˜ธ์ถœ ๋ฐ ์•Œ๋ฆผ ํ‘œ์‹œ
        fetch(`/api/buy/${productId}`);
        showNotification('๊ตฌ๋งค ์™„๋ฃŒ!');
      };
    
      return <button onClick={handleClick}>๊ตฌ๋งคํ•˜๊ธฐ</button>;
    }
    

 

5. ๋ฐ์ดํ„ฐ ํŒจ์นญ (์ดˆ๊ธฐํ™”)

  • ๋ฌธ์ œ์ : Effect ์•ˆ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜์Œ ๊ฐ€์ ธ์˜ค๋Š”(Workspace) ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ์™œ Effect๊ฐ€ ๋ถˆํ•„์š”ํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€: Effect๋ฅผ ์‚ฌ์šฉํ•œ ๋ฐ์ดํ„ฐ ํŒจ์นญ์€ ์ผ๋ฐ˜์ ์ด์ง€๋งŒ, ๊ฒฝ์Ÿ ์ƒํƒœ(race condition) ์ฒ˜๋ฆฌ, ์บ์‹ฑ ๋“ฑ ๋ณต์žกํ•œ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์ตœ์‹  React ํ”„๋ ˆ์ž„์›Œํฌ(Next.js, Remix ๋“ฑ)๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(React Query, SWR)๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ์„ ์œ„ํ•œ ๋” ํšจ์œจ์ ์ด๊ณ  ๋‚ด์žฅ๋œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•: ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฐ์ดํ„ฐ ํŒจ์นญ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜, ๋ฐ์ดํ„ฐ ํŒจ์นญ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปค์Šคํ…€ Hook์œผ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋กœ์ง์„ ๋” ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๊ณ , ์ž ์žฌ์ ์ธ ์ตœ์ ํ™” ๊ธฐํšŒ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

'๐Ÿ’ป FE' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

NodeList vs HTMLCollection  (0) 2025.05.16
์ƒ์„ฑ!  (0) 2025.05.16
children, childNodes  (0) 2025.05.16
querySelectorAll('li'), getElementsByTagName('li')  (0) 2025.05.14
์†์„ฑ , ํ”„๋กœํผํ‹ฐ  (0) 2025.05.14