React 18이 가진 몇가지 흥미로운 기능에 대하여
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 />);
- 최신 버전의 React & Dom 설치하여 root 엔트리파일에서 react-dom 의 import 경로를 client으로 변경합니다.
- 루트 구성요소를 HTML 파일의 특정 엘리먼트로 렝더링하기 위한 ReactDom.render 함수를 교체하여 index.html 파일로 루트 요소를 전달합니다.
✔️ 리액트 18에서 중요했던 업데이트 사항 3가지
1. Automatic Batching
- 기능 : 여러 상태 업데이트를 개별 호출하는 대신 그룹화하여 하나의 상태 업데이트 호출로 실행하는 것
- 장점 : 연속적인 state 업데이트를 모아 한번 만 re-rendering을 실행하기 때문에 효율적인 렌더링이 가능합니다.
- 동작
- 이전 : 리액트 이벤트 핸들러에서만 배칭을 지원했고, promise, setTimeout, native 이벤트 핸들러 등에서는 배칭이 되지 않았습니다.
- v18 : State batching이 state 업데이트 수행 위치에 관계없이 항상 작동
- 업데이트 시 모든 코드에 자동으로 적용됩니다.
- 업데이트 시 모든 코드에 자동으로 적용됩니다.
- 이전 : 리액트 이벤트 핸들러에서만 배칭을 지원했고, promise, setTimeout, native 이벤트 핸들러 등에서는 배칭이 되지 않았습니다.
2. useTransition & useDeferredValue
Debounce, Throttle을 리액트에서 hooks로 직접 지원하게 된 것이 특징
💡 Debounce & Throttle 란?
✓ Debouncing : 이벤트를 그룹화하여 특정시간이 지난 후 하나의 이벤트만 발생하도록 하는 기술
✓ Throttling : 이벤트를 일정한 주기마다 발생하도록 하는 기술
- 동작 원리 : 중요한 업데이트가 들어오면 리액트는 stale한 렌더링 작업을 버리고 마지막 업데이트만을 렌더링합니다.
- 이를 통해 state에 변화가 생겼을 때 마다 늦게 처리 될 수 있도록 나중 처리를 진행합니다.
- 사용자의 입력이 완료되었다고 판단되면 될 때 새로운 값을 리턴
- 이를 통해 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나 함수
- ex. 인퍼테이스가 느리고, 복잡한 연산을 포함하는 state나 함수
- ❗️ 모든 state를 hooks로 래핑하진 말고, 도움이 될 수 있는 곳에 적절하게 사용되어야 합니다.
- Wrapper된 state는 업데이트의 순위가 낮아지고,
- 다른 상태 업데이트를 처리하기 전에 프로세스가 완료될 때까지 기다리지 않습니다.
- 다른 상태 업데이트를 처리하기 전에 프로세스가 완료될 때까지 기다리지 않습니다.
💡 useTransition( ) 와 useDeferredValue( ) 함수의 차이점
✓ useTransition : 함수 실행의 우선순위를 지정
→ isPending값을 전달해 state의 새로운 업데이트 사항이 적용될 때까지 작업의 지연 여부를 알려줍니다.
✓ useDeferredValue : 값의 업데이트 우선순위를 지정 (useMemo와 유사)
→ 우선순위가 높은 작업을 실행되면 이전 값을 계속 들고 있으면서 업데이트를 지연시킨다.
서버 사이드 랜더링
- SSR 을 지원합니다!
- 보안 / 성능상 이유로 클라이언트에서 실행되지 않아야하는 서버 로직 작업에 도움
- 해당 기능이 추가되면서 리액트는 풀스택 프레임워크처럼 클라이언트 사이드로 서버 사이드 페이지 생성이 가능해졌습니다.
✔️ 기존 기능에 대한 몇 가지 변경 사항
- State batching (상태 일괄 처리)
- 기능 : 연속적인 state 업데이트를 하나의 리렌더링(re-render)으로 그룹핑 하는 것
- 장점 👍 : state이 속한 컴포넌트의 불필요 리랜더링 방지합니다.
- 성능 개선 : state이 속한 컴포넌트의 불필요한 리렌더링을 방지합니다.
- 효율적 : 여러 리렌더링을 모아 한번만 실행합니다.
- 성능 개선 : state이 속한 컴포넌트의 불필요한 리렌더링을 방지합니다.
- v18: State batching이 state 업데이트 수행 위치에 관계없이 Automatic 작동
- 기능 : 연속적인 state 업데이트를 하나의 리렌더링(re-render)으로 그룹핑 하는 것
- Improving Suspense (SSR 지원)
- 지연 로드 컴포넌트 코드가 다운로드될때까지 fallback에 로딩 UI 컴포넌트를 전달해 표시가 가능합니다.
- 기존 : 서버 사이드 렌더링 사용할 경우 Suspense 사용이 불가능
- v18 : 클라이언트 & 서버측(SSR)에서 모두 Suspense 사용 가능
- 업데이트되면서 클라이언트 & 서버측에서 사용할 수 있도록 변경되었습니다. 👍
- 업데이트되면서 클라이언트 & 서버측에서 사용할 수 있도록 변경되었습니다. 👍
- 지연 로드 컴포넌트 코드가 다운로드될때까지 fallback에 로딩 UI 컴포넌트를 전달해 표시가 가능합니다.
Posted by Ang