front/react

[react] React Hooks 1 (useState, useEffect)

๋ฐฐ๊ณ ํŒŒ์š” 2026. 1. 4. 17:29
728x90

๐Ÿ“ React Hook ??

  • ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ ๊ด€๋ฆฌ์™€ ์ƒ๋ช…์ฃผ๊ธฐ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ.

 

 

๐Ÿ“ useState

  • ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์ƒํƒœ(state)๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉ.
  • ์ดˆ๊ธฐํ™”
    • const [name, setName] = useState("ํ™๊ธธ๋™");
    • const [ ์Šคํ…Œ์ดํŠธ ๋ณ€์ˆ˜, ์ด ์Šคํ…Œ์ดํŠธ ๋ณ€์ˆ˜๋ฅผ update ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜ ] = useState("์ดˆ๊ธฐ๊ฐ’ ๋„ฃ๊ธฐ");
    • --> name = "ํ™๊ธธ๋™" ์œผ๋กœ ์ดˆ๊ธฐ๊ฐ’์ด ๋„ฃ์–ด์ง„ ์ƒํƒœ๋กœ ์‹œ์ž‘ํ•จ.
  • ๋‹จ์ผ ๋ฌธ์ž, ๋‹จ์ผ ์ˆซ์ž, ๋ฐฐ์—ด, ๊ฐ์ฒด ๋ชจ๋‘ ์ƒํƒœ๊ฐ’ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ.
  • setCar(previousState => {
                    return { ...previousState, color:"white" };
                }
            );
    • ** previousState ** ์ด ๋ถ€๋ถ„ ์ค‘์š”!! 
      • ์ด์ „ ์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณ€๊ฒฝ ํ•  ๋•Œ --> ๊ผญ ์จ์•ผํ•จ!!
      • ๊ฐ์ฒด / ๋ฐฐ์—ด state๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ prev => ์“ด๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์•ˆ์ „ํ•˜๋‹ค.!
import { createRoot } from 'react-dom/client';
import { useState } from 'react';


function App() {
    const [car, setCar] = useState({
        brand : "ํ˜„๋Œ€",
        model : "์ œ๋„ค์‹œ์Šค",
        color : "black"
    });

    const updateCarInfo = () => {
        setCar(previousState => {
                return { ...previousState, color:"white" };
            }
        );
    };

    return (
        <>
            <p>{car.brand} {car.model} {car.color}</p>
            <button onClick={updateCarInfo}>ํด๋ฆญ</button>
        </>
    );
}

createRoot(document.getElementById('react4')).render( <App /> );

 

 


 

๐Ÿ“ uesEffect ?

  • ๋ฆฌ์•กํŠธ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ side effects ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํ›….
  • ๋žœ๋”๋ง์€ ๋˜๋‚˜, ์‹ค์ œ DOM ์—…๋ฐ์ดํŠธ๋Š” ์ƒ๋žตํ•จ.
  • state ์˜ ๊ฐ’์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•ด์„œ ์ž‘๋™ํ•จ.
  • useEffect( () => {
        console.log(`${count} useEffect ์‹คํ–‰๋จ`);
    }, [ ] );
    • ๋งจ ์ฒ˜์Œ์— ๋กœ๋“œ(๋งˆ์šดํŠธ) ๋  ๋•Œ๋Š” ๋‹น์—ฐํžˆ ์‹คํ–‰๋˜๊ณ .
      state ๊ฐ’์ด ๋ณ€ํ™”ํ•˜๋ฉด ์ž‘๋™ํ•จ. 
    • ๋’ค์— ์žˆ๋Š” [] ์—๋Š” ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•  ๋ณ€์ˆ˜์— ๋Œ€ํ•ด์„œ ์ ์Œ. 
      • ์ด ๋ฐฐ์—ด์˜ ์ด๋ฆ„?? --> ์˜์กด์„ฑ ๋ฐฐ์—ด
      • ex) useEffect( () => {console.log(`${count} useEffect ์‹คํ–‰๋จ`);}, [ count ] );
      • ๋ผ๋ฉด --> count ๋ณ€์ˆ˜๊ฐ’์˜ ๋ณ€ํ™”๋งŒ ๊ฐ์ง€ํ•จ.
    • ์ „๋ถ€ ๋‹ค ๊ฐ์ง€ํ•˜๋ฉด [] ๋ฅผ ์ƒ๋žต! 
  • ํ† ๊ธ€ ์‚ฌ์šฉํ•˜๋Š” ๊ณต์‹ !! 
    • setState(prev => !prev);
  • useEffect์˜ return์€ “์ •๋ฆฌ(cleanup) ํ•จ์ˆ˜”๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
    • “์ด effect๊ฐ€ ๋๋‚˜๊ฑฐ๋‚˜, ๋‹ค์‹œ ์‹คํ–‰๋˜๊ธฐ ์ง์ „์—, ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์งˆ ๋•Œ ์ด ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด๋ผ.”
  • ์˜์กด์„ฑ ๋ฐฐ์—ด์ด ํ•˜๋Š” ์ผ??
    • ์˜์กด์„ฑ ๋ฐฐ์—ด = "์•Œ๋žŒ ์กฐ๊ฑด"
    •  ๋ฆฌ์•กํŠธ๋Š” ๋งค ๋ Œ๋”๋ง ๋งˆ๋‹ค ์˜์กด์„ฑ ๋ฐฐ์—ด ์•ˆ์˜ ๊ฐ’์ด ๋ฐ”๊ผˆ๋Š” ์ง€ ํ™•์ธํ•จ.
      • ๋ฐ”๊ผˆ์œผ๋ฉด --> cleanup --> effect ์žฌ์‹คํ–‰.
      • ์•ˆ ๋ฐ”๊ผˆ์œผ๋ฉด --> ์•„๋ฌด๊ฒƒ๋„ ์•ˆํ•จ.
    • 3๊ฐ€์ง€ ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•จ.
      1. [] ๋นˆ ๋ฐฐ์—ด
        • ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” effect
        • ์ด๋ฒคํŠธ ๋“ฑ๋ก, ํƒ€์ด๋จธ ์‹œ์ž‘, ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์š”์ฒญ ๋“ฑ๋“ฑ --> ์ดˆ๊ธฐ 1ํšŒ ์ž‘์—…์— ์“ฐ์ž„.
        • “์ด effect๋Š” ์–ด๋–ค state / props ๋ณ€ํ™”์—๋„ ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค”
        • ์‹คํ–‰ ํƒ€์ด๋ฐ
          • ์ฒ˜์Œ ํ™”๋ฉด ๋“ฑ์žฅ (mount)
            → effect ์‹คํ–‰

            ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์งˆ ๋•Œ (unmount)
            → cleanup ์‹คํ–‰
      2. [value] (์˜์กด์„ฑ ์žˆ์Œ.)
        • ๋ Œ๋”๋ง ๋ฐœ์ƒ. --> ์ด์ „ value ์™€ ๋น„๊ตํ•ด์„œ --> ๊ฐ’์ด ๋‹ค๋ฅด๋ฉด effect ์‹คํ–‰.
        • ์‹คํ–‰ ํ๋ฆ„ 
          • ์ดˆ๊ธฐ ๋ Œ๋” → effect
            value ๋ณ€๊ฒฝ
            → cleanup
            → effect ์žฌ์‹คํ–‰
      3. ์˜์กด์„ฑ ๋ฐฐ์—ด ์ƒ๋žต.
        • ์กฐ๊ฑด์ด ์—†์œผ๋ฉด?? --> ๋งค ๋ Œ๋”๋ง๋งˆ๋‹ค ์‹คํ–‰ํ•จ.
        • ๊ฒฐ๊ณผ
          • ๋ Œ๋”๋ง๋งˆ๋‹ค effect ์‹คํ–‰
            ๋ Œ๋”๋ง๋งˆ๋‹ค cleanup ์‹คํ–‰
          • --> ๋‚ด ์ฝ”๋“œ์—์„œ๋Š” ์‹œ์ž‘ํ•˜์ž๋งˆ์ž ๊บผ์งˆ ๊บผ์ž„.
import {createRoot} from 'react-dom/client';
import { useState, useEffect } from 'react';
import Counter from './Counter';

function App() {

    const [count, setCount] = useState(0);
    const [name, setName] = useState("");

    const updateCounter = () => {
        setCount(count + 1);
        console.log("usestate ์‹คํ–‰")
    };

    const handleNameChange = (e) => {
        setName(e.target.value);
    }

    useEffect( () => {
        console.log(`${count} count - useEffect ์‹คํ–‰๋จ`);
    }, [count]);

    useEffect( () => {
        console.log(`${name}  name - useEffect ์‹คํ–‰๋จ`);
    }, [name]);

    return (
        <div>
            <p>{count}</p>
            <button onClick={updateCounter}>์นด์šดํŠธ ์ฆ๊ฐ€</button>
            <input type="text" onChange={handleNameChange} />
            <p>{name}</p>
        </div>
    );
}

function App2() {
    const [showCounter, setShowCounter] = useState(false);

    return(
        <>
            { showCounter && <Counter /> }
            <button onClick={ () => {setShowCounter(prev => !prev)} }>ํด๋ฆญ</button>
        </>
    );
}

createRoot(document.getElementById('react4')).render( <App2 /> );

 

## Counter.jsx

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

const Counter = (props) => {
    const [cnt, setCnt] = useState(0);

    useEffect(() => {
        const counter = setInterval( () => {
            console.log(`${cnt} --- counter works`);
            setCnt( cnt + 1 );
            
            /* ์ •์„์€ ์ด๊ฑฐ! 
            effect ๋„ ํ•œ๋ฒˆ๋งŒ ํ˜ธ์ถœํ•˜๊ณ , cnt ๋Š” ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋จ.
            setCnt(prev => {
                console.log(`${cnt} --- counter works -- ${prev} `);
                return prev + 1;
            });
            */
        }, 1000);
		
        
        
        
        return () => {
            clearInterval(counter);
            console.log("stop!12313!");
        };
    }, []);
   
    

    return (
        <div>
            <p>counter is working!!</p>
        </div>
    )
}

export default Counter;

 

 

 

๐Ÿ“ ๋‚ด ์ฝ”๋“œ์—์„œ ์˜์กด์„ฑ ๋ฐฐ์—ด์ด ์žˆ๊ณ  ์—†๊ณ ์˜ ์ฐจ์ด?

  • [] ๋นˆ ๋ฐฐ์—ด์ธ ๊ฒฝ์šฐ
    • [Log] 0 --- counter works (Counter.jsx, line 9, x3)
      [Log] stop!12313! (Counter.jsx, line 14)
    • count ๊ฐ€ 0๋งŒ ๋‚˜์˜ด.
    • ๋นˆ ๋ฐฐ์—ด []์ด๋ฉด
      useEffect๋Š” ์ฒ˜์Œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๊ณ ,
      interval์€ ์ฒ˜์Œ์˜ cnt = 0๋งŒ ๊ธฐ์–ตํ•œ ์ฑ„ ๊ณ„์† ๋ˆ๋‹ค.
    • JS ํ•จ์ˆ˜๋Š” “๋งŒ๋“ค์–ด์ง„ ์ˆœ๊ฐ„์˜ ๋ณ€์ˆ˜ ๊ฐ’์„ ๊ธฐ์–ต”ํ•œ๋‹ค. --> ์ด effect๊ฐ€ ์‹คํ–‰๋  ๋‹น์‹œ์˜ cnt๋ฅผ ๊ธฐ์–ตํ•ด.
    • ํด๋กœ์ €๊ฐ€ ์ฒ˜์Œ ๊ฐ’์„ ๋ถ™์žก๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ.
    • start / stop ์„ ๋ฐ˜๋ณตํ•ด๋„ ๊ณ„์†ํ•ด์„œ cnt = 0 ์ธ๋ฐ...
      • ์ด๊ฑด cnt๊ฐ€ 1๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š”
        cleanup ํ›„์— “์ด์ „ interval์ด ์žฌ๊ฐœ๋˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ”,
        “์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง€๋ฉด์„œ state์™€ effect๊ฐ€ ๋‹ค์‹œ ์ดˆ๊ธฐํ™”๋˜๊ธฐ ๋•Œ๋ฌธ”์ด์•ผ.
      • ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ์˜ ์žฌ์‹œ์ž‘ ์•„๋‹˜ !!!! โŒ โŒ
      • โญ๏ธโญ๏ธ ์™„์ „ํžˆ ์ƒˆ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ. โญ•๏ธ โญ•๏ธ
      •      ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ์ผ์–ด๋‚˜๋Š” ์ผ.    
        • Counter ์–ธ๋งˆ์šดํŠธ

          cleanup ์‹คํ–‰

          interval ์ œ๊ฑฐ

          ์ปดํฌ๋„ŒํŠธ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ œ๊ฑฐ

          state(cnt)๋„ ํ•จ๊ป˜ ์‚ฌ๋ผ์ง
        • โ— ์ด ์‹œ์ ์— cnt = 1 ์ด์—ˆ๋‹ค๊ณ  ํ•ด๋„
          ๐Ÿ‘‰ ๊ทธ ๊ฐ’์€ ํ๊ธฐ๋จ
      • ์™œ "์ด์ „ cnt=1" ์ด ์ด์–ด์ง€์ง€ ์•Š๋Š”๊ฐ€???
        • ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์ง€๋ฉด → state๋„ ์‚ฌ๋ผ์ง
        • ๋‹ค์‹œ ์ƒ๊ธฐ๋ฉด → ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ƒ์„ฑ (--> cnt = 0)
      • cleanup ์ดํ›„์— ๋‹ค์‹œ ์‹œ์ž‘๋˜๋Š” ๊ฑด “์ด์ „ effect์˜ ์žฌ๊ฐœ”๊ฐ€ ์•„๋‹ˆ๋ผ “์ƒˆ ์ปดํฌ๋„ŒํŠธ์˜ ์ฒซ ์‹คํ–‰”์ด๋‹ค.
      • ์ด์ „ state ์œ ์ง€ํ•˜๊ณ  ์‹ถ์œผ๋ฉด → ๋ถ€๋ชจ๋กœ ๋Œ์–ด์˜ฌ๋ ค์•ผ ํ•จ
        • ๋”๋ณด๊ธฐ
          ๋”๋ณด๊ธฐ
          function App() {
            const [cnt, setCnt] = useState(0);
            const [show, setShow] = useState(false);
          
            return (
              <>
                <button onClick={() => setShow(p => !p)}>toggle</button>
                {show && <Counter cnt={cnt} setCnt={setCnt} />}
              </>
            );
          }

           

          Counter ๊ฐ€ ์‚ฌ๋ผ์ ธ๋„ 

          cnt ๋Š” App ์— ๋‚จ์•„ ์žˆ์Œ.

          "์ƒˆ ์ปดํฌ๋„ŒํŠธ์˜ ์ฒซ ์‹คํ–‰" ์„ ํ•  ๋•Œ? 

          props ๋ฅผ ๊ฐ€์ง€๊ณ  ์ƒˆ๋กœ Counter ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ฒŒ ๋จ.

          ์ด Counter ์ปดํฌ๋„ŒํŠธ ์•ˆ์— useEffect ๊ฐ€ ๋“ค์–ด์žˆ๊ณ !

  • ์ƒ๋žตํ•œ ๊ฒฝ์šฐ
    • [Log] 8 --- counter works (Counter.jsx, line 9)
      [Log] stop!12313! (Counter.jsx, line 14)
    • count ๊ฐ€ ๋Š˜์–ด๋‚จ.
    • ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์ƒ๋žตํ•˜๋ฉด
      useEffect๊ฐ€ ๋งค ๋ Œ๋”๋ง๋งˆ๋‹ค ๋‹ค์‹œ ์‹คํ–‰๋˜๊ณ ,
      ๊ทธ๋•Œ๋งˆ๋‹ค ์ตœ์‹  cnt๋ฅผ ์บก์ฒ˜ํ•œ ์ƒˆ๋กœ์šด interval์ด ๋งŒ๋“ค์–ด์ง„๋‹ค.
    • ๋ Œ๋”๋ง๋งˆ๋‹ค effect ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•จ.
      • cnt ๋Š” useEffect ๋ฐ–์— ์žˆ์œผ๋‹ˆ๊นŒ, useState๋กœ ๋ณ€ํ™”๊ฐ’์„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ์Œ.
    • start / stop ์„ ์—ฌ๋Ÿฌ๋ฒˆ ๋ˆŒ๋Ÿฌ์„œ ๋ณด๋ฉด, Interval ์„ ํ•  ๋•Œ๋Š” cnt ๊ฐ’์ด ์ฆ๊ฐ€ํ•จ. 
    • ๊ทผ๋ฐ, stop ํ›„์— ๋‹ค์‹œ start ํ•ด๋ณด๋ฉด, ์™„์ „ํžˆ ์ดˆ๊ธฐ๋กœ ๋Œ์•„๊ฐ --> cnt = 0 ์œผ๋กœ ์ƒˆ๋กœ ์‹œ์ž‘ํ•จ.

 

๐Ÿ“ ?

  • ใ…‡ใ…‡ 

 

 

 

 

๐Ÿ“ ?

  • ใ…‡ใ…‡ 

 

 


์ถœ์ฒ˜ : 

 

 

 


๊ฐœ๋ฐœ ๊ณต๋ถ€๋ฅผ ์œ„ํ•œ ๋ธ”๋กœ๊ทธ ์ž…๋‹ˆ๋‹ค. 

์˜ค๋ฅ˜๊ฐ€ ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”! 

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

728x90