프로그래머가 되는 꿈
count증가/handleClick함수/useEffect/strict (3-2) 본문
<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 |