본문 바로가기
개발/React

react18 : flushSync

by 안뇽! 2023. 4. 10.
반응형

react18 : flushSync

React 18에서는 새로 도입된 Concurrent Mode를 통해 여러 상태 업데이트를 동시에 처리하고 렌더링 작업을 인터럽트하여 중요한 작업(ex : 사용자 입력)을 먼저 처리할 수 있다. 이를 통해 웹 어플리케이션의 반응성을 크게 향상시킬 수 있다. 하지만 이 방식은 모든 경우에 적합한 것은 아니다. 예를 들어, 상태 변경 후 즉시 DOM업데이트를 반영해야 하는 경우 이 방식이 문제가 될 수 있다. 

useEffect를 이용하는 방식도 있지만, useEffect는 핸들러 안에 사용할 수 없는 hook이기 때문에 결국 관심사가 분리되게 된다.

react 18에서 신기능으로 나온 flushSync 메소드는 비동기작업을 동기화 하고 강제 리렌더링 시킨다. 이 메서드는 지정된 작업이 가능한 빨리 완료되도록 React의 스케쥴러에 지시한다. flushSync를 이용하면 핸들러 안에서 관심사를 분리하지 않고 상태변경후 즉시 DOM 업데이트를 구현할 수 있다.

 

아래 코드를 통해 간단한 예시를 들어보았다.

// useEffect를 이용할때는 코드가 handler밖으로 나오면서 관심사가 분리된다.
const handler = () => {
	setState(changeState)
}

useEffect(()=>{ 
	asyncHandler()
},[state])

//flushSync 사용할땐 핸들러 안에서 처리할 수 있다.
const handler = () => {
	flushSync(()=>asyncHandler())
}

 

flushSync 사용 후기

이 기능을 사용하게 된 이유는 회사에서 카드를 하나 만들면 스크롤을을 최하단으로 내리는 작업이 의도대로 작동하지 않았기 때문이다.

const onAdd = () => {
  setCards(newCards)
  scrollToBottom()
};

다음과 같이 작성하니, 비동기로 실행되는 setCards가 완료되기 전에 scrollToBottom이 실행되었다.

스크롤 이동 후, 카드가 하나 더생겨서 스크롤이 최하단으로 내려가지 않음.

카드 생성후 스크롤 최하단이동이 아닌, 스크롤 최하단 이동 후 카드생성이 되어버렸다.

setCards이 끝난 후 동기적으로 scrollToBottom을 실행시키기 위해 useEffect를 사용하거나 syncSetState라는 함수를 만들었었다.

// syncSetState.ts
import { Dispatch, SetStateAction } from 'react';

export const syncSetState = <T>(state: T, setState: Dispatch<SetStateAction<T | undefined>>) => {
  return new Promise((resolve) => {
    setState(state);
    resolve('done');
  });
};

그런데 이러한 수작업이 필요 없이, 리액트18의 신기능 중에 비동기를 동기화 시키고 강제로 리렌더링시키는 flushSync라는 함수가 있었다.

 

flushSync안에 콜백을 넣으면 리액트 18에서 추가된 AutoBatching에서 콜백을 제외시킨다. 즉시 실행시키는 것이다.

const onAdd = () => {
  // setCards(newCards);
  flushSync(() => setCards(newCards));
  scrollToBottom();
};

위와 같이 적으면 setCards의 실행이 완료 된 후, 강제 리렌더링을 시킨다. 그 후에 scrollToBottom이 실행된다.

 

그 결과 의도대로 새 카드 생성 후 스크롤 최하단 이동 이 구현된다.

setCards를 동기화 한 후 강제 리렌더링 시키기 때문에 스크롤이 최하단으로 이동한다.
좌 ) flushSync 사용 전, 우) flushSync 사용 후

flushSync 사용 시 주의할 점

flushSync는 강력한 도구지만, 애플리케이션의 전체적인 성능에 영향을 줄 수 있으므로 신중하게 사용해야 한다. 일반적으로 React가 스스로 작업의 우선순위를 관리하도록 하는 것이 좋다. 원하는 동작을 보장해야 하는 상황에서만 flushSync를 사용하자.

반응형