Early Riser
생각정리
Early Riser
전체 방문자
오늘
어제
  • 분류 전체보기 (128)
    • JS (19)
    • React (33)
    • React Native (2)
    • Library, Tool (13)
    • CSS (2)
    • Algorithm (40)
    • Computer Science (3)
    • 회고 (3)
    • AI (13)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • LGBM
  • boosting
  • 파이썬
  • 완전탐색
  • local minima
  • useState
  • js
  • javascript
  • BFS
  • 알고리즘
  • 딥러닝
  • 백트래킹
  • 부스트캠프 합격
  • 오늘의불경
  • 프로그래머스
  • react
  • 비동기
  • 구현
  • 백준
  • useEffect
  • global minima
  • 밑바닥
  • lightgbm
  • 논문리뷰
  • 손실함수
  • 부스트캠프 합격 후기
  • RNN
  • 부스트캠프 9기
  • dfs
  • 자바스크립트

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Early Riser

생각정리

React

transition과 concurrent render

2025. 12. 20. 20:23

서론

 React의 useTransition hook은 React 18에서 도입된 concurrent rendering의 핵심 기능 중 하나로, 상태 업데이트를 우선순위가 낮은 업데이트로 처리할 수 있게 해준다. 이를 통해 UI의 응답성을 유지하면서 백그라운드에서 느린 렌더링 작업을 처리할 수 있다. transition은 lane 시스템을 활용해 time slicing을 가능하게 하며, 사용자 입력 같은 우선순위가 높은 업데이트를 먼저 처리하고 오래된 transition 결과를 폐기함으로써 deferred UI를 가능하게 한다.

Concurrent Rendering과 Transition의 동작 원리

 React 18에서 도입된 concurrent rendering은 time slicing을 통해 장시간의 렌더링 작업을 여러 프레임으로 분할할 수 있게 한다. 이를 위해 내부적으로 5가지 우선순위 lane을 활용한다: Discrete, InputContinuous, Default, Transition, Retry. 이 중 Transition과 Retry lane은 실행을 다음 tick으로 지연시켜 메인 스레드를 비워둔다. 그 사이에 우선순위가 높은 업데이트(예: 사용자 입력)가 발생하면 먼저 처리되고, 이 과정에서 transition 상태가 변경되었다면 이전 transition의 결과는 폐기된다. 최신 상태만 렌더링되어 deferred UI를 실현한다. 이는 UI가 블로킹되지 않고 응답성을 유지하는 핵심 메커니즘이다.

Transition되는 action

 그러나 transition은 이벤트 루프의 한 tick에만 Transition lane을 할당한다. 따라서 비동기 작업에서 await를 만나 다음 tick으로 넘어간 이후의 상태 업데이트는 다시 startTransition으로 감싸지 않으면 urgent 업데이트로 처리된다.  따라서 isPending 상태가 예상과 다르게 종료되어 UI 전환이 찢겨보일 수 있게 된다.

Action prop과 await 패턴

 재사용 가능한 컴포넌트에서 action prop을 노출할 때 transition 내부에 await action()을 두는 이유도 이 맥락에서 이해할 수 있다. startTransition(async () => { await action(); }) 형태로 작성하면 action이 동기 함수이든 async 함수이든 transition 처리가 유지된다. 이는 action 구현이 나중에 변경되더라도 기존 코드를 수정할 필요가 없는 디커플링을 위함이다.
 컴포넌트 내부에서 setState를 호출할 수 없는 상황이라면 startTransition 혹은 useDeferredValue를 사용해야한다. 

Suspense와의 결합

 Suspense도 concurrent render의 기능 중 하나이다. Suspense는 초기 페이지 로딩 시 선언적으로 컴포넌트들을 lazy하게 로딩하거나 마운트할 때 data fetch시 로딩상태를 보여주는데 유용하다. 컴포넌트가 suspend 상태가 될 때(주로 use 훅으로 Promise를 읽거나 Promise를 throw할 때) fallback을 표시하기 때문이다. Suspense의 문제는 이미 로드된 페이지에서 새로운 데이터를 로드할때 fallback을 보여준다면 로딩동안 사용자는 기존 데이터들을 볼 수 없게 된다는 점이다.

이때 useTransition과 함께 사용하면 추가적인 data fetching 등으로 suspend가 발생하더라도 이미 드러난 콘텐츠는 숨기지 않고 유지된다. isPending 플래그를 활용해 추가 로딩 인디케이터를 구현할 수 있으며, 전체 사용자 경험을 크게 개선한다.

참고자료

https://react.dev/reference/react/useTransition
https://react.dev/reference/react/Suspense#preventing-already-revealed-content-from-hiding

'React' 카테고리의 다른 글

React 톺아보기 4. reconciler (2)  (0) 2025.07.14
React 톺아보기 3. scheduler (1)  (0) 2025.06.29
React 톺아보기 2. reconciler (1)  (0) 2025.06.09
React 톺아보기 - 1. ReactDom  (0) 2025.06.05
React에서 batch 처리와 렌더링 주기: 무한 재렌더링  (1) 2025.01.15
    'React' 카테고리의 다른 글
    • React 톺아보기 4. reconciler (2)
    • React 톺아보기 3. scheduler (1)
    • React 톺아보기 2. reconciler (1)
    • React 톺아보기 - 1. ReactDom
    Early Riser
    Early Riser
    2년차 프론트엔드 개발자입니다. https://github.com/EarlyRiser42

    티스토리툴바