프로그래머가 되는 꿈

count증가/handleClick함수/useEffect/strict (3-2) 본문

프론트엔드 (Front-end)/React

count증가/handleClick함수/useEffect/strict (3-2)

AI박사 2026. 1. 16. 14:08

<App.jsx>

import logo from "./logo.svg";
import "./App.css";
import { useState } from "react";

function App() { //App이라는 프로젝트를 만든다.
    const [count, setCount] = useState(0); // count하면서 어떤 state가 만들어져 있다.
    const handleClick = () => {
        setCount((prev) => prev + 1); // setCount를 1씩 증가시켜준다.
    };
    return (
        <div className="App">
            <h1>{count}</h1> // 화면에 count를 보여준다.
            <button onClick={handleClick}>증가</button> // 증가 버튼이 있고 클릭할때 마다 handleClick함수를 실행시켜준다.(위 코드로 이동)
        </div>
    )
}

export default App;

증가버튼을 호출해줄 때 handleClick 함수 호출

setCount를 1씩 증가시켜준다.

 

 

{

      숫자(ex.0,1,2... 1씩 증가!)

증가(버튼)

}

 

import logo from "./logo.svg";
import "./App.css";
import { useEffect, useState } from "react";

function App() {
    const [count, setCount] = useState(0);
    const handleClick = () => {
        setCount((prev) => prev + 1);
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    // UI render하는 부분
    return (
        <div className="App">
            {console.log("렌더!!")}
            <h1>{count}</h1>
            <button onClick={handleClick}>증가</button>
        </div>
    )
    //
}

export default App;

 


use~~ : hook(훅)=유용한 함수 - ():함수표

매개변수 2개: 콜백함수/배열(array)

useEffect()가 언제 호출이 되냐? - UI render하는 부분에 console.log를 추가한다. 

 

 

<검은 창>

console창
렌더!!
렌더!!
앱시작!!
앱시작!!

 

앱시작!!이 표시되는 이유 = render를 해주고 나서 그 다음에 useEffect를 호출해준다. - render끝나면 자동으로 호출해준다!

두개씩 나타나는 이유 = 

제거한다.

 

console창
렌더!!
앱시작!!

 

< strict 모드 >

좀 더 엄격하게, 그러니까 한번의 시도로 안그려질 수도 있잖아. 인간이 내가 이거 해야하는데 안되어 있을 수도 있잖아

( 그러니까)확실하게 있기 위해서 최소 2번 씩은 내가 호출을 해버리겠다.  - 2번씩 호출 된다.

 

근데..

나 그렇게 엄격하게 안해도 되. 내 UI 그렇게 복잡하지 않아... 

지워주면 된다.!

 

import logo from "./logo.svg";
import "./App.css";
import { useEffect, useState } from "react";

function App() {
    const [count, setCount] = useState(0);
    const handleClick = () => {
        setCount((prev) => prev + 1);
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()->{
       console.log("업데이트!!")
       },[count]
       
    // UI render하는 부분
    return (
        <div className="App">
            {console.log("렌더!!")}
            <h1>{count}</h1>
            <button onClick={handleClick}>증가</button>
        </div>
    )
    //
}

export default App;

 

console창
렌더!!
앱시작!!
업데이트!!

 

(여기서 알 수 있는 것)

useEffect는 무조건 처음에 실행이 된다.(배열(에 어떤게 있던 없던) 상관없음)

--

증가 버튼을 누르면...

0->1

console창
렌더!!
앱시작!!
업데이트!!

 

1->2

console창
렌더!!
앱시작!!
업데이트!!
렌더!!
업데이트!!

 

2->3

console창
렌더!!
앱시작!!
업데이트!!
렌더!!
업데이트!!
렌더!!
업데이트!!

 

배열 안에 넣어놓은 state가 업데이트 되면 [count]

어떤 업데이트가 일어날때마다 useEffect()가 자동으로 호출이 된다 -> -- 업데이트!!

항상 호출 X

배열 안에 있는 state가 업데이트 되면 호출된다. - count가 업데이트 되었다.

 

import logo from "./logo.svg";
import "./App.css";
import { useEffect , useState } from "react";

function App() {
    const [count, setCount] = useState(0);
    const [value, setValue] = useState(1);
    const handleClick = () => {
        setCount((prev) => prev + 1); //setCount를 업데이트
        setValue((prev) => prev + 1); //setValue를 업데이트
        // = setValue(value+1)
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()->{
       console.log("업데이트!!")
       },[count]
       
    // UI render하는 부분
    return (
        <div className="App">
            {console.log("렌더!!")}
            <h1>{count}</h1>
            <h2>value:{value}</h2>
            <button onClick={handleClick}>증가</button>
        </div>
    )
    //
}

export default App;

 

● setValue((prev) => prev + 1); -- 애가 조금더 안전하다(권장,추천) = 이전 상태를 기반으로 여러 번 변경할 때

=

●setValue(value+1); = 한 번만 업데이트 할 때

 

둘은 같다! 결론적으로 하는 일은 같고 (단지) 값을 하나 추가하는 것!

그럼 얘 setValue(value+1); 를 쓰지 왜 setValue((prev) => prev + 1);를 쓰나?

 

import logo from "./logo.svg";
import "./App.css";
import { useEffect, useState } from "react";

function App() {
    const [count, setCount] = useState(0);
    const [value, setValue] = useState(1);
    const handleClick = () => {
        setCount((prev) => prev + 1); //setCount를 업데이트
        setValue((prev) => prev + 1); //setValue를 업데이트
        // = setValue(value+1)
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()->{
       console.log("업데이트!!")
       },[count,value] // 내가 지켜보고 있는 값이 2개
       
    // UI render하는 부분
    return (
        <div className="App">
            {console.log("렌더!!")}
            <h1>{count}</h1>
            <h2>value:{value}</h2>
            <button onClick={handleClick}>증가</button>
        </div>
    )
    //
}

export default App;

내가 지켜보고 있는 값 = count, value 

 

증가 버튼을 누르면...

0->1

value: 1 -> 2

console창
렌더!!
앱시작!!
업데이트!!

 

1->2

value: 2-> 3

console창
렌더!!
앱시작!!
업데이트!!
렌더!!
업데이트!!

 

2->3

value: 3-> 4

console창
렌더!!
앱시작!!
업데이트!!
렌더!!
업데이트!!
렌더!!
업데이트!!

 

<알수있는것>

배열 안에 값이 여러개가 있어도 (업데이트는) 한번만 호출된다!

count,value 이렇게 2개가 있다고 두번 호출되는 것 X.

 

function App() {
    const [count, setCount] = useState(0);
    const [value, setValue] = useState(1);
    const handleClick = () => {
        //삭제 setCount((prev) => prev + 1); //setCount를 업데이트
        setValue((prev) => prev + 1); //setValue를 업데이트
        // = setValue(value+1)
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()->{
       console.log("업데이트!!")
       },[count,value] // 내가 지켜보고 있는 값이 2개

 

증가 버튼을 누르면...

0

value: 1 -> 2

console창
렌더!!
앱시작!!
업데이트!!

 

0

value: 2-> 3

console창
렌더!!
앱시작!!
업데이트!!
렌더!!
업데이트!!

 

0

value: 3-> 4

console창
렌더!!
앱시작!!
업데이트!!
렌더!!
업데이트!!
렌더!!
업데이트!!

 

value가 바뀌기 때문에 업데이트!!가 출력(실행)된다 (count때문 X)

 

function App() {
    const [count, setCount] = useState(0);
    const [value, setValue] = useState(1);
    const handleClick = () => {
        //삭제 setCount((prev) => prev + 1); //setCount를 업데이트
        //삭제 setValue((prev) => prev + 1); //setValue를 업데이트
        // = setValue(value+1)
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()->{
       console.log("업데이트!!")
       },[count,value] // 내가 지켜보고 있는 값이 2개

 

증가 버튼을 누르면...

0

value: 1

console창
렌더!!
앱시작!!
업데이트!!

-아무것도 반응 X-

 

function App() {
    const [count, setCount] = useState(0);
    const [value, setValue] = useState(1);
    const handleClick = () => {
          setCount((prev) => prev + 1); //setCount를 업데이트
          setValue((prev) => prev + 1); //setValue를 업데이트
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()->{
       console.log("업데이트!!")
       },[count,value] // 내가 지켜보고 있는 값이 2개
       
    useEffect(()=>{
       console.log("다른일!!")
       },[value])

 

증가 버튼을 누르면...

0

value: 1

console창
렌더!!
앱시작!!
업데이트!!
다른일!!

 

증가 버튼을 누르면...

1

value: 2

console창
렌더!!
앱시작!!
업데이트!!
다른일!!
렌더!!
업데이트!!
다른일!!

 

증가 버튼을 누르면...

2

value: 3

console창
렌더!!
앱시작!!
업데이트!!
다른일!!
렌더!!
업데이트!!
다른일!!
렌더!!
업데이트!!
다른일!!

 

 

function App() {
    const [count, setCount] = useState(0);
    const [value, setValue] = useState(1);
    const handleClick = () => {
         //삭제 setCount((prev) => prev + 1); //setCount를 업데이트
          setValue((prev) => prev + 1); //setValue를 업데이트
    };
    useEffect(() =>{
       console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()->{
       console.log("업데이트!!")
       },[count,value] // 내가 지켜보고 있는 값이 2개
       
    useEffect(()=>{
       console.log("다른일!!")
       },[value])

 

증가 버튼을 누르면...

0

value: 1

console창
렌더!!
앱시작!!
업데이트!!
다른일!!

 

증가 버튼을 누르면...

0

value: 2

console창
렌더!!
앱시작!!
업데이트!!
다른일!!
렌더!!
다른일!!
렌더!!
다른일!!

 

--왜냐하면 value만 업데이트하고 있기 때문!!

 

* useEffect : 자동으로 호출되는데 언제 호출되느냐? 앱 시작시의 render 후에  한번 호출이되고, /무조건 이때는 다 호출이 된다.(모든 useEffect)/

업데이트 하고 있을 때에 render후에 useEffect가 호출이 되는데 이때는 매번 호출되는 것이 아니라 내가 이 배열 안에서 보고 있는 state값이 업데이트 될때에만  그 useEffect가 호출이 된다. -- 여러분이 아실 수가 있습니다.

앱 종료후에 useEffect with return(하는 방법)

 

<타이머(Timer)만들기>

1000ms = 1s

 

계속 살아있기 때문에 앱이 끝날 때 살려두면 안돼고 없애야 한다.자원낭비!

-> return / cleareInterval(intereval닫기)

 

<Unmounting 앱 종료>useEffect with return

 

 

<App.jsx>

import logo from "./logo.svg";
import "./App.css";
import { useEffect,  useState } from "react";

function App() {
    const [count, setCount] = useState(0);
    const [value, setValue] = useState(1);
    const [showTimer,setShowTimer] = useState(true) //처음에는 타이머가 보이도록 true
    const handleClick = () => {
    setCount((prev) => prev + 1); //setCount를 업데이트
    setValue((prev) => prev + 1); //setValue를 업데이트
        // = setValue(value+1)
    };
    useEffect(() =>{
    console.log("앱 시작!!");
       //앱 초기작업들 , api호출
    },[])
    
    useEffect(()=>{
    console.log("업데이트!!");
    },[count]) // 내가 지켜보고 있는 값이 2개
    // UI render하는 부분

    useEffect(()=>{
    console.log("다른일!!");
    },[value]);


    useEffect(()=>{
        const interval = setInterval(() => {
            console.log("count 실행");
        }, 1000);

        return() => {
            console.log("타이머 정리됨");
            clearInterval(interval);
        };
    }, []);

    return (
        <div className="App">
            {console.log("렌더!!")}
            <h1>{count}</h1>
            <h2>value:{value}</h2>
            <button onClick={handleClick}>증가</button>
            <button onClick={() => setShowTimer((prev) => !prev)}> // setShowTimer함수에 prev(ious)의 반대되는 값을 넣어준다. 
            타이머 보이기
            </button>
            {showTimer && <Timer />} // (showTimer가) true이면 Timer(이 컴포넌트)를 보여주겠다.
        </div>
    );
}

export default App;

 

<타이머 생성>

1초마다

App이 끝나면 interval은 살아있다. 앱이 끝날때 이걸 없애줘야한다. 사라지게 해야한다. 자원 낭비 ㅜ

여기서 return! clearInterval - interval을 닫아주는 역할! 깔끔하게 클리어 하겠다.

 

앱을 종료하기 위해서 전체 화면을 끄면... (앱=useEffect가 속한 컴포넌트의 lifecycle을 의미한다. - 전체 앱 뿐만 아니라 컴포넌트가 시작되고 종료될때 에도 useEffect가 쓰인다.)

'타이머가 종료됨' 결과를 못 보게된다.

이것을 실습하기 위해서 새로운 컴포넌트를 만들겠다.

 

 

 

<Timer.jsx>

import React, { useEffect } from 'react'

const Timer = () => {
    useEffect(()=> {
        const interval = setInterval(()=> {
            console.log("count 실행")
        },1000);

        return () => {
            console.log("타이머 정리됨")
            clearInterval(interval);
        };
    },[]);

  return <div> Timer </div>;
};

export default Timer;

1.

                                        0

                                   value:1

                증가            타이머 보이기

                                       Timer

①count 실행

②count 실행

..... 1초마다 변함

 

2.

타이머 보이기 버튼 클릭!

                                        0

                                   value:1

                증가            타이머 보이기
ex.(8) count 실행
렌더!!
타이머 정리됨

 

3. 

정리?(중지)하면 아무것도 안나옴 (타이머가 정리되었기 때문에)

 

4. 

다시 타이머 보이기 버튼 클릭!
                                        0

                                   value:1

                증가            타이머 보이기

                                       Timer

①count 실행

②count 실행

..... 1초마다 변함

 

5.

타이머 보이기 버튼 클릭!

                                        0

                                   value:1

                증가            타이머 보이기
ex.(8) count 실행
렌더!!
타이머 정리됨

 

반복~~~~~~~~~~~~~~~~~~~~

 

<정리?>

전체앱도 맞지만,,컴포넌트 개개인의 lifecycle도 useEffect가 관리한다.

컴포넌트의 lifecycle

타이머가 return을 통해 정리된다.

return이 있으면 Unmounting으로 실행이 된다.

매일 x , 타이머 같은 메모리 양 많을때...

'프론트엔드 (Front-end) > React' 카테고리의 다른 글

5-2(Link,Navigate - 페이지 사이를 이동하는 방법)  (0) 2026.01.16
5-1  (0) 2026.01.16
리액트의 Life Cycle  (0) 2026.01.15
rafce 단축키  (0) 2026.01.15
버튼 만들기 (2)  (0) 2026.01.15