╱╱╭╮╱╱╱╱╱╱╭━━━╮╱╱╱╭╮╱╭╮╱╱╱╱╱╱ ╱╱┃┃╱╱╱╱╱╱┃╭━╮┃╱╱╱┃┃╱┃┃╱╱╱╱╱╱ ╱╱┃┣━━┳━━╮┃┃╱┃┣━╮╱┃╰━╯┣━━┳━╮╱ ╭╮┃┃╭╮┃┃━┫┃╰━╯┃╭╮╮┃╭━╮┃╭╮┃╭╮╮ ┃╰╯┃╭╮┃┃━┫┃╭━╮┃┃┃┃┃┃╱┃┃╭╮┃┃┃┃ ╰━━┻╯╰┻━━╯╰╯╱╰┻╯╰╯╰╯╱╰┻╯╰┻╯╰╯

Frontend/React

[React] useTransition, Concurrent Mode 쉽게 이해하기

재안안 2025. 3. 9. 19:18

개요

[1] useTransition

[2] concurrent mode

[3] useTransition Details

[4] reference


 

[1] useTransition

 

useTransitoin이란?

  리액트 18에 추가된 훅으로 nonblocking 방식으로 상태(state)를 업데이트할 수 있게 해준다.

 

nonblocking이란?

  기존 리액트의 동기적 업데이트 방식에서는 상태가 업데이트되면 그에 따른 렌더링 작업이 바로 실행되는데, 해당 작업이 실행될 때, 사용자의 인터랙션이 발생하면 해당 인터렉션 처리가 지연된다. (blocking)

  이때, useTransition의 startTransition을 통해 특정 상태 업데이트를 낮은 우선순위로 예약해 사용자 인터랙션을 우선 순위로 처리하게 된다. (nonblocking)

 

  추가적으로, 이렇게 우선순위가 낮아진 상태 업데이트를 Transition이라고 한다. (조금의 의역이 있다.)

setState함수 내부에서 if 문으로 transition인지 아닌지 분기처리해서 구분된다고 한다.

Call useTransition at the top level of your component to mark some state updates as Transitions.

 


 

[2] Concurrent Mode

 

Concurrent Mode란?

  리액트 18 이상의 버전에서는 기본적으로 Concurrent Mode가 활성화 된다. ('react-dom/client'의 `createRoot`사용시) Concurrent Mode가 활성화 되더라도 기본적으로 상태 업데이트는 동기적 방식으로 진행된다. 사용자가 `useTransition`, `useDeferredValue`, `useOptimistic` 등을 사용할 때만 Concurrent Mode로 상태를 업데이트한다. Concurrent Mode에서는 리액 스케줄러가 렌더링 작업을 작은 청크로 나누어 처리하고, 만약 중간에 높은 우선순위 작업이 발생하면 현재 작업을 일시 중단하고 높은 우선순위 작업을 즉시 처리한다.

 


[3] useTransition Details

const [ isPending, startTransition ] = useTransition();

 

  startTransition에 전달하는 함수 자체를 Action이라고 하고, action 내부에서 실행되는 상태 변경 함수들은 트랜지션이라고 한다. 컨벤션에 따르면, startTransition에 전달되는 함수의 이름은 action으로 지정되거나 Action 접미사를 포함해야한다. 추가적으로, action에서 트랜지션들은 하나의 트랜지션으로 일괄 처리되는데 앞으로도 계속 일괄 처리할 지 말지를 고민중이라고 한다. (2025/03/09)

 

  action은 즉시 실행된다. 함수 내부에서 setTimeout을 통해 상태 업데이트 함수 실행 환경을 분리한다면, 분리된 상태 업데이트 함수는 해당 트랜지션으로 처리되지 않는다. (아마 call stack 때문인듯?) 마찬가지로 action 내부에서 비동기 요청 이후의 상태 업데이트를 진행할 수 없다. 또 다른 startTransition으로 감싸줘야 하는데 이는 아래에서 예제를 통해 다루겠다. (2025/03/09) 이때, startTransition 내부에서 await를 사용하면 상태 업데이트 함수들의 실행 순서는 보장되지 않는다.

 

  추가적으로, Transition으로 표시된 상태 업데이트는 다른 상태 업데이트가 발생한다면 처리 중 중단 될 수 있다. Concurrent Mode에서는 우선 순위가 낮기 때문에, 높은거 먼저 처리하고난 후 돌아 온다. 그래서 텍스트 입력 제어에는, controlled text input에는 사용 할 수 없다.

 

 

useTransition은 아래와 같이 사용할 수 있다.

function SearchComponent() {
  const [input, setInput] = useState('');
  const [suggestions, setSuggestions] = useState([]);
  const [color, setColor] = useState('rgb(0, 0, 0)');
  const [isPending, startTransition] = useTransition();

  const fetchSuggestions = async (query) => {
    const response = await fetch(`/api/autocomplete?query=${encodeURIComponent(query)}`);
    const data = await response.json();
    return data;
  };

  const handleInputChange = async (e) => {
    const value = e.target.value;
    setInput(value);
    
    startTransition(async () => {  
      setColor('rgba(0, 0, 0, 0.5)');
      const results = await fetchSuggestions(value);

      startTransition(() => {
        setColor('rgb(0, 0, 0)');
        setSuggestions(results);
      });
    });
  };

  return (
    <div>
      <input
        type="text"
        value={input}
        style={{ color }}
        onChange={handleInputChange}
        placeholder="검색어를 입력하세요"
      />
      {isPending && <div>관련 키워드 가져오는 중...</div>}
      <ul>
        {suggestions.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

 

 

추가적으로 useTransitio은 Suspense와 함께 사용할 때 매우 유용한데 이는 다음에 자세히 알아보겠다.

 


[4] reference

 

https://react.dev/reference/react/useTransition

 

useTransition – React

The library for web and native user interfaces

react.dev

 

https://ko.react.dev/reference/react/useTransition

 

useTransition – React

The library for web and native user interfaces

ko.react.dev

'Frontend > React' 카테고리의 다른 글

[React] useOptimistic 쉽게 이해하기  (0) 2025.03.09
[React] React Conference 2024 정리  (0) 2024.05.20
[React] Custom Hooks  (0) 2023.09.18
[React] React.memo, useCallback, useMemo, Closure  (0) 2023.09.09