๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Frontend

React์—์„œ setInterval ์‚ฌ์šฉํ•˜๊ธฐ

์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜ setState๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ตฌํ˜„

import { useEffect, useState } from "react";

import "./App.css";

function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount((prev) => prev + 1);
    }, 1000);

    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <div className="App">
      <h1>{count}</h1>
    </div>
  );
}

export default App;

์œ„ ์†Œ์Šค๋Š” 1์ดˆ๋งˆ๋‹ค ์นด์šดํŠธ๋ฅผ 1 ์”ฉ ์˜ฌ๋ ค์ฃผ๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

  • useEffect ๋‘ ๋ฒˆ์งธ ์ธ์ž์— ๋นˆ ๋ฐฐ์—ด์„ ๋„ฃ์–ด componenetDidMount์™€ ๊ฐ™์ด timer ํ•จ์ˆ˜๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์„ธํŒ…ํ•ฉ๋‹ˆ๋‹ค.
  • setInnerval๋กœ timer๋ฅผ ์„ธํŒ…ํ•˜๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์งˆ ๋•Œ clearInterval๋กœ timer๋ฅผ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • useEffect ๋‘ ๋ฒˆ์งธ ์ธ์ž์— ๋นˆ ๋ฐฐ์—ด์„ ๋„ฃ์„ ๊ฒฝ์šฐ ๋ Œ๋”๋ง ํ›„ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์—
    setState์˜ ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜(setCount(prev => prev + 1))๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. 
    • ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜ setCount(prev => prev + 1) ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ prev๋Š” ํ•ญ์ƒ ์ตœ์‹  ์ƒํƒœ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • setState(count + 1)์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์ดˆ๊ธฐ count ๊ฐ’๋งŒ์„ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์— count๊ฐ€ 1์—์„œ ๋ฉˆ์ถฐ ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.

๋ฌธ์ œ์ 

์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜์ธ setState๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ ๋ณ€๊ฒฝ์—์„œ๋Š” count ์—…๋ฐ์ดํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ props๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์—๋Š”
ํƒ€์ด๋จธ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.  useEffect ๋‘ ๋ฒˆ์งธ ์ธ์ž์— ๋นˆ ๋ฐฐ์—ด์„ ๋„ฃ์–ด timerํ•จ์ˆ˜๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์„ธํŒ…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. 

 

useRef๋ฅผ ํ™œ์šฉํ•œ ํƒ€์ด๋จธ ๊ตฌํ˜„

import { useEffect, useRef, useState } from "react";

import "./App.css";

function App() {
  const timerRef = useRef();

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

  const handleCount = () => {
    setCount(count + 1);
  };

  const handleRestart = () => {
    if (!timerRef.current) {
      timerRef.current = setInterval(handleCount, 1000);
    }
  };

  const handleStop = () => {
    if (timerRef.current) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
  };

  useEffect(() => {
    timerRef.current = setInterval(handleCount, 1000);

    return () => {
      clearInterval(timerRef.current);
    };
  });

  return (
    <div className="App">
      <h1>{count}</h1>
      <button onClick={handleRestart}>restart</button>
      <button onClick={handleStop}>stop</button>
    </div>
  );
}

export default App;

timerRef.current์— timer๋ฅผ ์ €์žฅํ•˜์—ฌ ํƒ€์ด๋จธ๋ฅผ ์ •์ง€ํ•˜๋Š” stop๋ฒ„ํŠผ๊ณผ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š”  restart ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  • useRef๋Š” ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๊ณ  useRef์˜ timerRef ๊ฐ์ฒด๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ „ ์ƒ์• ์ฃผ๊ธฐ ๋™์•ˆ ์œ ์ง€๋˜์–ด 
    useRef๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ’์€ state ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ref์˜ ๊ฐ’์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • count ์ƒํƒœ ๋ณ€๊ฒฝ๋งŒ์˜ ๋ฆฌ๋ Œ๋”๋ง์„ ๋‚˜ํƒ€๋‚ด๊ณ  restart ๋ฒ„ํŠผ or stop ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด๋„ ๋ฆฌ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.