카테고리 없음

React 18이 가진 몇가지 흥미로운 기능에 대하여

ANG DEV 2022. 6. 28. 17:43

오늘은 파트에서 FE 새싹 트렌드 스터디 🌱를 진행하는 날입니다.

React 18이 가진 몇가지 흥미로운 기능에 대한 소개하며, 정리한 내용을 공유합니다 :)

 

How to Update

리액트 18 버전은 기존의 코드를 유지하며, 버전 업데이트를 위해 아래 2가지 작업만 진행해주시면 됩니다.

yarn add react@18 react-dom@18
// 두 줄만 변경하면 The End!
import ReactDOM from 'react-dom/client'; // import by client 
import App from './App';

// 기존 ReactDom.render 함수 교체 → ReactDom.createRoot() 적용
const root = ReactDOM.createRoot(document.getElementById('root')); 
root.render(<App />);

 

  1. 최신 버전의 React & Dom 설치하여 root 엔트리파일에서 react-dom 의 import 경로를 client으로 변경합니다.
  2. 루트 구성요소를 HTML 파일의 특정 엘리먼트로 렝더링하기 위한 ReactDom.render 함수를 교체하여 index.html 파일로 루트 요소를 전달합니다.

 


✔️  리액트 18에서 중요했던 업데이트 사항 3가지

1. Automatic Batching

  • 기능 : 여러 상태 업데이트를 개별 호출하는 대신 그룹화하여 하나의 상태 업데이트 호출로 실행하는 것

  • 장점 : 연속적인 state 업데이트를 모아 한번 만 re-rendering을 실행하기 때문에 효율적인 렌더링이 가능합니다.

  • 동작
    • 이전 : 리액트 이벤트 핸들러에서만 배칭을 지원했고, promise, setTimeout, native 이벤트 핸들러 등에서는 배칭이 되지 않았습니다.

    • v18 : State batching이 state 업데이트 수행 위치에 관계없이 항상 작동
      • 업데이트 시 모든 코드에 자동으로 적용됩니다.

2. useTransition & useDeferredValue

Debounce, Throttle을 리액트에서 hooks로 직접 지원하게 된 것이 특징

💡 Debounce & Throttle 란?

 Debouncing : 이벤트를 그룹화하여 특정시간이 지난 후 하나의 이벤트만 발생하도록 하는 기술

 Throttling : 이벤트를 일정한 주기마다 발생하도록 하는 기술

 

  • 동작 원리 : 중요한 업데이트가 들어오면 리액트는 stale한 렌더링 작업을 버리고 마지막 업데이트만을 렌더링합니다.
    • 이를 통해 state에 변화가 생겼을 때 마다 늦게 처리 될 수 있도록 나중 처리를 진행합니다.

    • 사용자의 입력이 완료되었다고 판단되면 될 때 새로운 값을 리턴

  • 장점 👍
    • 성능 저하로 부정적인 사용자 경험 및 불필요 업데이트 방지

    • 코드 실행 시점을 조금 늦춰 중요한 작업들을 먼저 처리가 가능해져 웹의 성능 향상시킵니다.

| useTransition

React에게 이 상태 업데이트를 지연시켜도 괜찮다고 전달하는 방법

  • 동작 원리 : 중요한 업데이트가 들어오면 useTransition 안의 코드 실행 시점을 조금 늦춰 웹의 성능 향상을 돕습니다.

  • 코드 적용 방식 : 함수로 성능 저하를 일으키는 원인 state 변경을 감싸줍니다.

import { useState, useTransition } from 'react';

function App () {
  const [isPending, startTransition] = useTransition({ timeoutMs: 3000 });
  const [comment, setComment] = useState("");
  
  function handleChange() {
        // 성능에 영향 미치는 함수를 startTransition 함수의 콜백 함수로 감싸줍니다.
	startTransition(() => { 
		(e) => setName(e.target.value);
	});
  }

  return (
    <div>
      {isPending && <Spinner />}
      <button onClick={handleChange}>{count}</button>
    </div>
  );
}​

 

  • Suspense 와의 조합
import {useState, useTransition, Suspense} from 'react';

function handleInput(e) {
  startTransition(() => {
    setName(e.target.value);
  });
}


<Suspense fallback={<Spinner />}>
  {isPending ? <LoadingUI /> : <DisplayInputText />}
</Suspense>;

 

| useDeferredValue

  • 기능 : 느린 컴포넌트 성능 향상 가능

  • 동작 원리 : state에 변화가 생겼을 때 마다 늦게 처리 될 수 있도록 나중 처리를 돕습니다.
    • 중요한 작업들을 먼저 처리 가능할 수 있게 됩니다.
  • 코드 적용 방식 : 성능 저하를 일으키는 원인 state를 함수에 전달합니다. 

import { useState, useDeferredValue } from 'react';

const [slowState, setSlowState] = useState();

// 성능에 영향 미치는 state를 useDeferredValue 함수에 전달
let deferredValue = useDeferredValue(slowState);​

 

  • 기존 라이브러리를 활용한 코드
import { throttle } from 'lodash';

  const throttledScroll = useMemo(
    () =>
      throttle(() => {
        console.log('스크롤 이벤트');
        if (!tabSelectorRef.current) return;
        const nextTabnavOn = window.scrollY > tabSelectorRef.current.offsetTop + 100;
        if (nextTabnavOn !== isTabnavOn) setIsTabnavOn(nextTabnavOn);
      }, 300),
    [isTabnavOn]
  );

  useEffect(() => {
    window.addEventListener('scroll', throttledScroll);
    return () => {
      window.removeEventListener('scroll', throttledScroll);
    };
  }, [throttledScroll]);

 

 


 

✔️ 도입된 중요 신규 기능

 

동시성 지원

 

  • 기능 : 여러 동시 상태를 업데이트하는 것을 의미합니다.

  • 기존 : 트리거된 순서대로 state에 대한 업데이트 처리
    • 이전 상태의 처리를 완료 후에 다음 상태 처리할 수 있었습니다. `비동시성`

  • React 18 :
    • 특정 상태 업데이트의 우선순위를 높여 리액트가 해당 업데이트를 더 높은 우선순위로 처리 가능한 `동시성`

 

NEW Concurrent APIs

  • 기능 : API 중 하나를 사용해 state 업데이트의 우선순위를 낮게 설정할 수 있습니다.
    • ❗️ 모든 state를 hooks로 래핑하진 말고, 도움이 될 수 있는 곳에 적절하게 사용되어야 합니다.
      • ex. 인퍼테이스가 느리고, 복잡한 연산을 포함하는 state나 함수

  • Wrapper된 state는 업데이트의 순위가 낮아지고,
    • 다른 상태 업데이트를 처리하기 전에 프로세스가 완료될 때까지 기다리지 않습니다.

 

💡 useTransition( )useDeferredValue( ) 함수의 차이점

✓ useTransition : 함수 실행의 우선순위를 지정

→  isPending값을 전달해 state의 새로운 업데이트 사항이 적용될 때까지 작업의 지연 여부를 알려줍니다.

✓ useDeferredValue : 값의 업데이트 우선순위를 지정 (useMemo와 유사)

→ 우선순위가 높은 작업을 실행되면 이전 값을 계속 들고 있으면서 업데이트를 지연시킨다.

 

서버 사이드 랜더링

  • SSR 을 지원합니다!

  • 보안 / 성능상 이유로 클라이언트에서 실행되지 않아야하는 서버 로직 작업에 도움

  • 해당 기능이 추가되면서 리액트는 풀스택 프레임워크처럼 클라이언트 사이드로 서버 사이드 페이지 생성이 가능해졌습니다.

 


 

✔️ 기존 기능에 대한 몇 가지 변경 사항

 

  • State batching (상태 일괄 처리)
    • 기능 : 연속적인 state 업데이트를 하나의 리렌더링(re-render)으로 그룹핑 하는 것

    • 장점 👍 : state이 속한 컴포넌트의 불필요 리랜더링 방지합니다.
      • 성능 개선 : state이 속한 컴포넌트의 불필요한 리렌더링을 방지합니다.

      • 효율적 : 여러 리렌더링을 모아 한번만 실행합니다.

    • v18: State batching이 state 업데이트 수행 위치에 관계없이 Automatic 작동

 

  • Improving Suspense (SSR 지원)
    • 지연 로드 컴포넌트 코드가 다운로드될때까지 fallback에 로딩 UI 컴포넌트를 전달해 표시가 가능합니다.

    • 기존 : 서버 사이드 렌더링 사용할 경우 Suspense 사용이 불가능

    • v18 : 클라이언트 & 서버측(SSR)에서 모두 Suspense 사용 가능
      • 업데이트되면서 클라이언트 & 서버측에서 사용할 수 있도록 변경되었습니다. 👍

 

 

 

Posted by Ang