Written by
Parkdev
on
on
[React]성능을 개선해보자3 (automatic batch, useTransition, useDeferredValue)
세번째 로딩성능 개선
Automatic Batch
- 리엑트는 기본적으로 automatic batch를 지원한다.
- state변경이 근처에서 발생하면
- 마지막에 발생한 state 변경함수에서만 재랜더링이 발생한다.
- 그러나 예외가 있다.
- 18버전 부터 특정 조건아래 automatic batching기능이 작동안하도록 바뀌었다.
- ajax요청
- settimeout과 같은 지연 발생시
- 18버전 부터 특정 조건아래 automatic batching기능이 작동안하도록 바뀌었다.
- 이는 자동 지원이므로 반대의 경우가 아니라면 크게 신경쓰지 않아도된다.
useTransition
- 18버전부터는 느린 컴포넌트 성능 개선을 위한 hook인 useTransitiion기능을 제공한다.
// 예시
import { useState } from "react";
function App() {
let [name, setName] = useState('');
return (
<div className="App">
<input onChange={(e)=> { setName(e.target.value)}}/>
</div>
)
}
- 위 코드에서 성능 저하가 발생했다고 가정해보자
// 예시
import { useState } from "react";
let a = new Array(10000).fill(0)
function App() {
let [name, setName] = useState('');
return (
<div className="App">
<input onChange={(e)=> { setName(e.target.value)}}/>
</div>
// 성능 저하를 일으키기 위해 값이 변경할때마다 10000개의 출력이 발생하면 매우 느려진다.
{
a.map(()=>{
return <div>{name}</div>
})
}
)
}
- 이럴때 useTransition을 사용하면 성능을 개선할 수 있다.
// 예시
import { useState, useTransition } from "react"; //import하고
let a = new Array(10000).fill(0)
function App() {
let [name, setName] = useState('');
let [isPending, startTransition] = useTransition(); //사용을 위한 변수설정을 한 후
return (
<div className="App">
// 성능 저하를 일으키는 부분을 감싸면된다.
<input onChange={(e)=> {
startTransition(() =>{
setName(e.target.value)
}
}}/>
</div>
{
a.map(()=>{
return <div>{name}</div>
})
}
)
}
- startTransition 동작원리
- 브라우저는 기본적으로 병렬작업을 하지 못한다.
- 그런데 위의 예시처럼 여러개의 작업을 동시에 실행시키면 필연적으로 속도가 느려진다.
- state 변경하기
- div 10000 개보여주기 등등
- 이때 startTransition은 감싼 함수를 다른것을 처리한 이후 실행시켜준다.
- 참고로 isPending은 startTransition이 상호작용 중 일때 (지연되고 처리하기 전까지) true를 변환한다.
- 이를 활용하면 다음과 같이 코드를 작성할 수 있다.
// 예시
import { useState, useTransition } from "react"; //import하고
let a = new Array(10000).fill(0)
function App() {
let [name, setName] = useState('');
let [isPending, startTransition] = useTransition(); //사용을 위한 변수설정을 한 후
return (
<div className="App">
// 성능 저하를 일으키는 부분을 감싸면된다.
<input onChange={(e)=> {
startTransition(() =>{
setName(e.target.value)
}
}}/>
</div>
{
isPending ? '로딩중' : // 실행중일때 로딩중을 표시
a.map(()=>{
return <div>{name}</div>
})
}
)
}
useDefferedValue
- useDefferedValue도 비슷한 기능을 제공한다.
// 예시
import { useState, useTransition, useDeferredValue } from "react";
let a = new Array(10000).fill(0)
function App() {
let [name, setName] = useState('');
let [isPending, startTransition] = useTransition();
let state = useDeferredValue(name); // useDefferedValue에 입력된 함수는 변동이 생길때 느리게 처리해준다.
return (
<div className="App">
// 성능 저하를 일으키는 부분을 감싸면된다.
<input onChange={(e)=> {
startTransition(() =>{
setName(e.target.value)
}
}}/>
</div>
{
isPending ? '로딩중' :
a.map(()=>{
return <div>{state}</div>
})
}
)
}