본문 바로가기
React

React에서 setState 비동기 처리 이해하기

by 굿센스굿 2024. 12. 12.
반응형

 

React를 사용하다 보면 setState 메서드의 비동기적 특성과 관련된 질문이 자주 나옵니다. 이 글에서는 setState의 동작 원리와 비동기 처리 특성을 깊이 있게 이해할 수 있도록 설명합니다. 또한 setState의 비동기성을 올바르게 다루는 방법과 흔히 발생하는 문제를 해결하는 팁을 제공합니다.

1. setState는 왜 비동기적일까?

React에서 setState는 비동기로 동작합니다. 이는 React의 성능 최적화 전략과 관련이 있습니다. 여러 개의 상태 변경이 있을 때, React는 이 변경 사항을 하나의 업데이트로 묶어 처리(batch processing)하여 렌더링 과정을 최소화합니다.

주요 이유

  • 성능 최적화: 상태 업데이트마다 렌더링을 트리거하면 성능 저하가 발생할 수 있습니다. setState는 이를 방지하기 위해 여러 상태 변경을 하나의 렌더링 사이클에서 처리합니다.
  • 동기 실행의 문제 방지: 컴포넌트 계층 구조에서 연속적으로 상태를 변경하면, 동기적으로 처리할 경우 예기치 못한 버그가 발생할 수 있습니다.

예시 코드

import React, { useState } from 'react';

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

  const handleClick = () => {
    setCount(count + 1);
    setCount(count + 1);
    console.log(count); // 여전히 이전 값 출력
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increase</button>
    </div>
  );
}

export default Counter;

위 코드를 실행하면 버튼을 클릭해도 console.log(count)는 예상과 달리 업데이트된 값을 출력하지 않습니다. 이는 setState가 비동기로 처리되기 때문입니다.


2. setState 비동기성을 다루는 방법

setState의 비동기성을 이해하고 이를 올바르게 다루기 위해 몇 가지 방법을 활용할 수 있습니다.

2.1. 함수형 업데이트 사용하기

React에서 setState는 이전 상태값에 의존할 경우 함수형 업데이트를 사용하는 것을 권장합니다. 함수형 업데이트는 최신 상태값을 안전하게 가져옵니다.

함수형 업데이트 예제

import React, { useState } from 'react';

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

  const handleClick = () => {
    setCount(prevCount => prevCount + 1);
    setCount(prevCount => prevCount + 1);
    console.log(count); // 여전히 이전 값 출력
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increase</button>
    </div>
  );
}

export default Counter;

위 코드에서는 prevCount를 사용하여 최신 상태값을 기반으로 상태를 안전하게 업데이트합니다.

2.2. 상태 변경 후 동작을 실행하기

상태 업데이트가 완료된 후 특정 작업을 수행하고 싶을 때는 **useEffect**를 활용할 수 있습니다.

useEffect를 이용한 예제

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

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

  useEffect(() => {
    console.log("Count updated:", count);
  }, [count]);

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increase</button>
    </div>
  );
}

export default Counter;

위 코드는 상태가 변경될 때마다 useEffect가 호출되어 최신 값을 출력합니다.


3. 흔한 문제와 해결 방법

3.1. 상태값을 즉시 사용하는 경우

상태값이 즉시 변경되지 않는다는 점을 간과하면 예기치 않은 버그가 발생할 수 있습니다.

문제 상황

const handleClick = () => {
  setCount(count + 1);
  console.log(count); // 이전 값 출력
};

해결 방법

const handleClick = () => {
  setCount(prevCount => {
    const updatedCount = prevCount + 1;
    console.log(updatedCount); // 최신 값 출력
    return updatedCount;
  });
};

3.2. 여러 상태를 동시에 업데이트

여러 상태를 업데이트할 때 setState의 비동기성을 고려하지 않으면 의도한 결과를 얻기 어렵습니다.

문제 상황

const handleClick = () => {
  setX(x + 1);
  setY(y + 1);
};

해결 방법

상태를 하나의 객체로 관리하거나, useEffect를 활용해 처리 순서를 제어합니다.

const handleClick = () => {
  setState(prevState => ({
    ...prevState,
    x: prevState.x + 1,
    y: prevState.y + 1,
  }));
};

4. 결론

React의 setState는 비동기적으로 동작하며, 이는 성능 최적화와 관련이 있습니다. 이 비동기성을 올바르게 다루기 위해 함수형 업데이트와 useEffect를 적절히 활용해야 합니다. 또한, 상태 업데이트 순서와 로직을 명확히 작성함으로써 예기치 않은 문제를 방지할 수 있습니다.

React의 상태 관리와 비동기적 특성을 잘 이해하면 더 안정적이고 예측 가능한 애플리케이션을 개발할 수 있습니다. 이 글을 통해 setState의 비동기 처리에 대한 이해를 높이는 데 도움이 되었기를 바랍니다.

반응형