React 16. React 버전 18

@t189216·2024년 3월 14일

😎 프론트엔드

목록 보기
28/31

React 버전 18 업데이트 내용


React의 전체 배포 기록

Automatic Batching

리액트는 함수 컴포넌트에서 각각의 state가 업데이트될 때마다 재렌더링이 발생합니다. useState 훅을 사용해서 선언한 각 state들의 set 함수를 동시에 호출하더라도 호출된 횟수만큼 재렌더링이 발생합니다.

Automatic Batching 을 사용하면 여러 상태의 업데이트가 동시에 발생한 경우, 자동으로 이 작업들을 묶어서 한번에 처리할 수 있습니다.

// 기존 버전
setTimeout(( => {
    setCount((count) => count + 1);
    setIsFull((isFull) => !isFull);
	//  각 state의 업데이트마다 재렌더링 발생
}, 1000)

// 현재 버전
setTimeout(( => {
    setCount((count) => count + 1);
    setIsFull((isFull) => !isFull);
	//  재렌더링이 마지막에 한번만 발생 (Automatic Batching)
}, 1000)

Transitions

Transitions 은 긴급한 업데이트와 긴급하지 않은 업데이트를 구분해서 처리하기 위한 개념입니다. 업데이트의 형태를 나누면 사용자에게 더 빠르고 좋은 경험을 제공할 수 있습니다.

긴급한 업데이트

  • 사용자와 직접적인 인터랙션이 일어나는 경우
  • ex) 글자 입력, 버튼 클릭 등

긴급하지않은 업데이트

  • 사용자와 직접적인 인터랙션이 일어나지 않는 경우
  • ex) 서버로부터 결과를 받아와서 보여주는 경우
import { startTransitions } from 'react';

// 긴급 업데이트
setInputValue(input);

// 함수 내에 있는 모든 업데이트는 Transitions 업데이트가 됨
startTransitions(() => {
    // Transitions 업데이트: 검색 결과를 보여줘야 함
    setSearchQuery(input);
});

Transitions 업데이트는 긴급하지 않은 것으로 처리되기 때문에 그 사이에 더 긴급한 업데이트가 추가되면 중단될 수도 있습니다.

Suspense

웹사이트의 규모가 커지면 컴포넌트의 사이즈도 커지게 됩니다. 웹브라우저에서 이런 큰 컴포넌트를 한 번에 로딩하려고 하면 시간이 오래 걸리게 됩니다.

이러한 문제를 해결하게 위해 Code Splitting 기법을 사용합니다. 분리된 조각을 흔히 레이지 로딩 또는 다이나믹 로딩이라고 부르는 동적 로딩 기법을 적용하여 웹사이트의 반응 속도를 높일 수 있습니다.

Suspense 는 하위 컴포넌트(children)가 준비되기 전까지 렌더링을 중단합니다.

import { lazy, Suspense } from 'react';
import LoadingSpinner from './LoadingSpinner';
const OtherComponent = lazy(() => import('/OtherComponent'));

function MyComponent(props) {
    return (
    	<Suspense fallback={<LoadingSpinner />}>
        	<OtherComponent />
    	</Suspense>
  	);
}

export default MyComponent;

Other 컴포넌트가 준비되기 전까지 fallback 속성에 들어가 있는 LoadingSpinner 컴포넌트를 화면에 보여주고, Other 컴포넌트가 준비되면 그 때 Other 컴포넌트를 보여줍니다.

클라이언트와 서버 렌더링 API 업데이트

리액트 DOM 클라이언트의 변경 사항입니다.

// 기존 방식
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
    <React.StrictMode>
    	<App />
  	</React.StrictMode>
  	document.getElementById('root')
);
// React 버전 18
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  	<React.StrictMode>
    	<App />
  	</React.StrictMode>
);

리액트 DOM 서버 변경사항입니다.

  • renderToPipeableStream
    NodeJs 환경에서 스트리밍을 위한 함수
  • renderToReadableStream
    Edge 런타임 환경(ex: Deno, Cloudflare workers)을 위한 함수

새로운 Strict 모드 작동 방식

StrictMode 는 개발 모드일 때 잠재적인 버그를 찾을 수 있게 해주는 모드입니다. 개발 모드에서 사용하게 되면 컴포넌트를 언마운트 시켰다가 다시 한 번 마운트 시키게 됩니다. 그래서 컴포넌트 생명 주기 함수들이 예상과 다르게 여러번 호출 될 수 있습니다.

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  	<React.StrictMode>
    	<App />
  	</React.StrictMode>
);

그래서 컴포넌트가 여러 번 마운트 되어도 문제가 생기지 않도록 개발해야 합니다.

새로운 훅

useId()

서버와 클라이언트에서 고유한 id 값을 생성하기 위한 훅입니다. 다만 리스트를 렌더링할 때 맵 함수 내에서 반환하는 element의 key로 사용하는 용도는 아닙니다.

useTransitions()

긴급하지 않은 업데이트를 위한 훅입니다. 기본적으로 일반적인 상태 업데이트는 긴급한 업데이트로 처리되며, useTransition 훅이나 startTransitions 함수를 사용하여 긴급하지 않은 업데이트를 모아서 처리할 수 있습니다.

useDeferredValue()

긴급하지 않은 업데이트를 재렌더링을 하는 것을 연기할 수 있습니다. 짧은 시간에 한 가지 상태의 업데이트가 여러 번 발생하게 되면 최종 상태값만을 업데이트하면 됩니다. 이런 것을 값이 튀는 것을 막는다는 의미로 디바운싱이라고 하는데 useDeferredValue 훅도 비슷한 역할을 합니다. 참고로 지연된 렌더링은 중단 가능하며 사용자의 입력을 차단하지 않습니다.

useSuncExternalStore()

외부 저장소를 React 컴포넌트의 State와 연동해서 사용하고 싶을 때 사용하게 됩니다. 참고로 useSuncExternalStore 훅은 애플리케이션 코드가 아닌 라이브러리에서 사용하기 위한 것이기 때문에 입문자가 사용할 일은 거의 없습니다.

useInsertionEffect()

CSS인 JS 라이브러리를 위한 훅으로, 렌더링 과정에서 스타일 삽입의 성능 문제를 해결할 수 있게 해줍니다. 마찬가지로 애플리케이션 코드가 아닌 라이브러리에서 사용하기 위한 것이기 때문에 입문자가 사용할 일은 거의 없습니다.

profile
Today I Learned

0개의 댓글