ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] Concurrency(동시성) - #3. Concurrent Rendering
    Front-End(Web)/React - 프레임워크(React, Next) 2022. 10. 27. 20:19
    반응형

    🧐 서론

    지난 포스팅에선, <Suspense>, <SuspenseList> 를 통한 Loading UI, <ErrorBoundary>를 통한 Error UI 등에 대해 알아보았다.

    하지만, 이런 로딩화면도 사용자에게 답답함을 줄 수 있기에, React는 좀 더 UX 친화적인 렌더링 방식을 제공하려고 한다.

     

    Concurrent Rendering(동시성 렌더링)는 React 18버전이 릴리즈되면서 가장 강조하고 있는 컨셉이다.

    정확히는, Parellel(병렬)이 불가능한 Javascript의 싱글 스레드 환경에서, 최대한 이와 비슷한 Concurrency(동시성)을 구현하는 것이다.

     

    React 18에 출시된 Transition API들을 통해 동시성 렌더링을 구현할 수 있으며, 이러한 환경을 앞으로 더욱 보장할 계획이라고 한다.

    * React 18 변경점(포스팅) : https://abangpa1ace.tistory.com/252

     

    [React] React 18 의 달라진 점들

    올해 3월, React v18.0 이 정식 릴리즈가 되었다. (2020년 10월, v17.0 이 릴리즈된지 약 1년반) 업데이트 소식과 베타버전은 작년부터 리포트 되어왔으며, 최근 정식 릴리즈됨에 따라 이 포스팅을 한 번

    abangpa1ace.tistory.com

     

    동시성 렌더링을 직접 구현하기에 앞서, 그 개념과 원리를 알아보고 앞으로 React가 어떻게 이 컨셉을 반영할지를 먼저 훑어보고 가는게 좋다고 판단하여 이를 먼저 정리한다!

     


     

    💙 Concurrent Rendering(동시성 렌더링)

     

    - 배경

    기존의 React의 렌더링single, uninterrupted, synchronous 라고 설명한다. (React 18 공식문서)

    즉, 상태 업데이트를 통해 리렌더링이 일어나면 이를 블로킹할 수 없고 렌더링 결과가 다시 노출되기까지 우리는 대기해야한다.

     

    하지만, 동시성 렌더링을 통해선 이 렌더링을 지연시키거나 병렬적으로 처리하여 더 나은 사용자 경험을 제공할 수 있게 된다.

    또한, 새로운 DOM 트리가 완성되기 전까지 이전의 상태값을 유지하여 임시적인 UI를 최소화하거나 문제가 발생하면 이전 상태로 돌아가게끔 하는 것이다.(<Offscreen> 이라는 준비중인 신규기능)

     

     

     

    - 업데이트 : 긴급(Urgent) vs 전환(Transition)

    이전 React 18에 관한 글을 적으며, 동시성을 설명하기 전에 React의 2가지 상태 업데이트 분류를 설명했다.

    • 긴급 업데이트(Urgent) : 직접적인 상호작용 반영(타이핑, 호버, 스크롤 등). 업데이트가 즉각적으로 일어나는 대상 - Input 박스
    • 전환 업데이트(Transition) : 뷰에서 다른 뷰로 UI 전환. 상태값에 따른 모든 업데이트가 즉시 반영되지 않아도 됨 - 자동완성 박스

     

    여기서 중요한 점은, 전환 업데이트는 긴급 업데이트를 방해하면 안된다는 것이다.

    Concurrent Features의 일부 기능들은 이렇게 중요도가 낮은 전환 업데이트를 Hooks들을 통해 가능하게끔 하는 것이다.

     

     

     

    - Concurrency(동시성)?

    아시다시피 Javascript는 싱글 스레드 언어다. 각 작업들이 실행되면 스레드가 블록되고, 이러한 작업들이 동기적으로 실행된다.

    React 역시 Reconciliation(재조정)이 발생하여 DOM트리를 제작하고 컴포넌트 코드를 실행하면 jank(스레드 블로킹)이 일어날 뿐 아니라 이를 중단할 수도 없었다.

     

    이 작업을 여러 개의 작은 작업단위로 나눈 뒤, 그들간의 우선순위를 정하고 이를 바꿔가며 번갈아 수행하는 방법이 동시성이다!

    실제로 작업이 동시에 수행되는 것이 아니지만, 작업 간의 전환이 매우 빠르게 이루어지며 동시에 수행되는 것처럼 보인다.

     

     

    * 기존의 동시성

     

    기존에는 통상 setTimeout이나 debounce(디바운스) throttle(쓰로틀) 기법들을 통해 동시성을 그럴듯하게 구현하곤 했다.

    하지만, 이는 단순히 우선순위가 낮은 작업을 지연시키는 것일 뿐, 근본적으로 나아진 성능으로 UX가 개선되는 형태는 아니다.

    • 디바운스 : 일정시간이 지나고 작업을 수행하므로, 컴퓨터 성능에 상관없이 같은 시간이 지연되며 무거운 로직은 지연시간 이상의 스레드 블로킹을 유발할 수 있다.
    • 쓰로틀 : 특정시간동안 동일한 작업들을 1번만 실행하나, 시간이 짧아질수록 성능이 나쁜 기기에서는 불리하다.

     

    또한, React는 <Suspense>를 통해 로딩 UI를 노출하지만,

    이는 사용자에게 답답함을 주거나 기존 컨텐츠가 로더로 대체된다는 단점들이 있으며, 결국 이러한 작업도 메인 스레드에 영향을 미친다.

     

    그렇기에, Concurrent Rendering을 통해 전환 업데이트를 완벽히 분리하며 지연시간은 사용자 기기 성능으로 좌우하는 것이다.

    또한, 기존의 화면과 기능을 그대로 노출하며 다음 화면의 렌더링을 준비하고, 특정 조건에 부합하면 이를 실행하는 것이다.

     

     

     

    - 원리

    원리의 기본적인 틀은, 특정 state가 변경되었을 때 현재 UI를 유지하면서 해당 변경에 따른 UI 업데이트를 동시에 준비한다.

    준비중인 UI의 렌더링 단계특정 조건에 부합하면 실제 DOM에 반영되는 것이다. 렌더링 단계와 특정 조건에 대해 자세히 설명하겠다!

     

    1) 렌더링 단계

    useState의 setter 함수를 통해 상태변경이 일어나면, Transition, Loading, Done 3가지 랜더링 단계를 거치게 된다.

    1. Transition : state 변경 직후 일어날 수 있는 UI 렌더링 단계이다.
      • Pending : state 변경 직후에도 UI를 업데이트하지 않고 기존 UI를 잠시 유지. (React Transition API 사용시)
      • Receded : Transition API를 쓰지 않는 기본상태. state 변경 시 UI도 변경되며, 전체 페이지를 로드하는 단계에 해당.
        (Pending 상태도 useTransition의 timeout 시간을 지나면, 강제로 Receded 상태로 전환됨)
    2. Loading : Skeleton으로 페이지 일부만을 로딩하는 단계.
    3. Done : 로딩 UI 없이 모든 정보가 사용자에게 보이는 상태이자, 렌더링의 최종 단계이다.

     

    2) 특정 조건

     

    이제, DOM을 업데이트하게 되는 특정조건에 대해 알아보겠다. 이 내용은 공식문서에도 상당히 모호하게 표현된다.

    공식문서에서 언급하듯, 2가지 상태의 렌더링은 마치 각각의 유니버스에 존재하며, 다음 렌더링이 준비되었다는 일종의 신호를 통해 이를 화면에 새로이 반영한다고 설명한다.

     

    상태값 업데이트에 따라 렌더링이 일어날 때 본래는 기본적인 리렌더링 단계(Receded - Skeleton - Done)를 준수했다면,

    Transition API를 통한 지연 업데이트새로운 리렌더링 단계(isPending - Skeleton - Done)가 끝날때까지 기존 화면을 노출하다 Complete 됬다는 신호를 받으면 화면에 반영시켜주는 것으로 이해된다.

     

     

    - 마무리

    이전엔, Concurrent Mode(모드), Concurrent Features(기능들) 등으로 명명했지만,

    미래에는 개발자가 Concurrency를 하나의 설정으로 특정하고 개발하는 것이 아니라 React의 백그라운드 매커니즘으로 동작하며 새로운 렌더링 모델을 React APP에서 제공하게끔 하는 것이 목적이라고 공식문서는 언급한다.

     

    Concurrent Rendering은 호버나 텍스트 입력과 같은 작업은 즉각적으로 처리하면서, 클릭이나 페이지 전환은 조금 더 지연시키며 사람과컴퓨터 간 상호작용에 대한 연구결과가 실제 UI와 통합되도록 해준다.

     


     

    📎 출처

    - [React 18] React 공식문서 : https://reactjs.org/blog/2022/03/29/react-v18.html

    - [React 17: Concurrent Mode(outdated)] React 공식문서 : https://17.reactjs.org/docs/concurrent-mode-reference.html#suspenselist

     

    - [Concurrent Mode란?(번역)] kelly woo 님의 블로그 : https://kelly-kh-woo.medium.com/%EB%B2%88%EC%97%AD-what-is-react-concurrent-mode-45e4cdc3de17 

    - [Concurrent Mode] Tecoble 기술 블로그 : https://tecoble.techcourse.co.kr/post/2021-07-24-concurrent-mode/

    - [Concurrent Mode] programming119 블로그 :   https://programming119.tistory.com/242

     

     

    반응형
Designed by Tistory.