useEffect로 타이머 구현하기
useEffect는 리액트의 훅(hook) 중 하나로, 컴포넌트가 렌더링된 후에 부수적인 작업(side effect)을 처리할 때 사용됩니다.
useEffect는 컴포넌트가 렌더링될 때마다 실행될 수 있고, 특정 상태나 props의 변화에 따라 다르게 동작하도록 설정할 수 있습니다.
useEffect는 두 가지 주요 매개변수를 받습니다:
- 콜백 함수: 이 함수는 컴포넌트가 렌더링된 이후에 실행되는 코드입니다.
- 의존성 배열(Dependency Array): 이 배열은 useEffect가 언제 실행될지를 결정합니다. 배열 안에 있는 값이 변경될 때마다 useEffect가 다시 실행됩니다. 이 배열을 비워두면, useEffect는 컴포넌트가 처음 마운트될 때만 실행됩니다.
이러한 특징으로 useEffect를 사용해 타이머를 구현해 봅시다.
const App = () => {
const [toggle, setToggle] = useState(false);
const [count, setCount] = useState(0);
const toggleTimer = () => {
setToggle(!toggle);
};
useEffect(() => {
let timer;
if (toggle) {
timer = setInterval(() => {
setCount((prev) => prev + 1);
}, 1000);
} else {
clearInterval(timer);
}
return () => {
clearInterval(timer);
};
}, [toggle]);
return (
<div>
<div>{count}</div>
<button onClick={toggleTimer}>{toggle ? '타이머 중단' : '타이머 시작'}</button>
</div>
);
};
- 타이머 시작과 중지: 이 코드에서 toggle 상태에 따라 타이머를 시작하거나 중지합니다. toggle이 true일 때 setInterval로 1초마다 count 값을 증가시키는 타이머를 설정하고, false일 때 clearInterval로 타이머를 중지합니다.
- useEffect로 타이머 관리:
- useEffect는 컴포넌트의 상태(toggle)가 변경될 때마다 실행됩니다. 즉, toggle 상태가 true로 변경되면 타이머가 시작되고, false로 변경되면 타이머가 중지됩니다.
- cleanup:
- useEffect는 반환값으로 cleanup 함수를 가질 수 있습니다. 이 함수는 컴포넌트가 언마운트되거나 의존성 배열의 값이 변경될 때 실행됩니다. 여기서 clearInterval(timer)를 사용하여 타이머가 계속 실행되는 것을 방지합니다. 이렇게 하면 리소스 낭비를 줄이고, 의도하지 않은 동작을 방지할 수 있습니다.
- 의존성 배열: 의존성 배열 [toggle]을 설정함으로써 toggle 값이 변경될 때마다 useEffect가 다시 실행되도록 했습니다. 이 배열을 사용하지 않으면 useEffect는 컴포넌트가 처음 렌더링될 때만 실행되고, toggle 값이 변경되어도 타이머는 다시 시작되지 않습니다.
setCount(count + 1)이 아닌 setCount((prev) => prev + 1)로 작성한 이유?
비동기적인 상태 업데이트
리액트는 상태를 변경할 때 바로 변경된 값을 반영하는 것이 아니라, 배치(batch) 처리를 통해 업데이트합니다. 즉, setCount(count + 1)을 여러 번 호출하더라도, 각 호출에서 사용된 count 값은 마지막으로 렌더링된 상태 값을 반영하게 되며, 이는 비동기적으로 처리되므로, 여러 번의 상태 업데이트가 동시에 일어날 때 올바른 결과를 보장하지 않습니다.
prev를 사용한 이유
setCount((prev) => prev + 1)처럼 함수를 사용한 업데이트 방식은 prev라는 파라미터로 이전 상태 값을 자동으로 전달받아 처리합니다. 이렇게 하면 상태 업데이트가 여러 번 중첩되어도 항상 최신 상태 값을 기준으로 업데이트가 이루어집니다. 리액트가 상태를 업데이트할 때 최적화된 방식으로, 여러 상태 변경이 겹치더라도 예상한 대로 순차적으로 값이 변경됩니다.
useEffect – React
The library for web and native user interfaces
ko.react.dev