useDeferredValue
useDeferredValue๋ UI ์ผ๋ถ ์
๋ฐ์ดํธ๋ฅผ ์ง์ฐ์ํฌ ์ ์๋ React Hook์
๋๋ค.
const deferredValue = useDeferredValue(value)๋ ํผ๋ฐ์ค
useDeferredValue(value)
์ปดํฌ๋ํธ์ ์ต์์ ๋ ๋ฒจ์์ useDeferredValue๋ฅผ ํธ์ถํ์ฌ ์ง์ฐ๋ ๋ฒ์ ์ ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค.
import { useState, useDeferredValue } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
// ...
}์๋์์ ๋ ๋ง์ ์๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
value: ์ง์ฐ์ํค๋ ค๋ ๊ฐ์ ๋๋ค. ๋ชจ๋ ํ์ ์ ๊ฐ์ง ์ ์์ต๋๋ค.
๋ฐํ๊ฐ
์ด๊ธฐ ๋ ๋๋ง ์ค์๋ ๋ฐํ๋ โ์ง์ฐ๋ ๊ฐโ์ ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ๊ฐ๊ณผ ๊ฐ์ต๋๋ค. ์ ๋ฐ์ดํธ๊ฐ ๋ฐ์ํ๋ฉด React๋ ๋จผ์ ์ด์ ๊ฐ์ผ๋ก ๋ฆฌ๋ ๋๋ง์ ์๋(๋ฐํ๊ฐ์ด ์ด์ ๊ฐ๊ณผ ์ผ์นํ๋๋ก)ํ๊ณ , ๊ทธ๋ค์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ค์ ์ ๊ฐ์ผ๋ก ๋ฆฌ๋ ๋๋ง์ ์๋(๋ฐํ๊ฐ์ด ์ ๋ฐ์ดํธ๋ ์ ๊ฐ๊ณผ ์ผ์นํ๋๋ก)ํฉ๋๋ค.
์ฃผ์์ฌํญ
-
useDeferredValue์ ์ ๋ฌํ๋ ๊ฐ์ ๋ฌธ์์ด ๋ฐ ์ซ์์ ๊ฐ์ ์์๊ฐ์ด๊ฑฐ๋, ์ปดํฌ๋ํธ์ ์ธ๋ถ์์ ์์ฑ๋ ๊ฐ์ฒด์ฌ์ผ ํฉ๋๋ค. ๋ ๋๋ง ์ค์ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฆ์useDeferredValue์ ์ ๋ฌํ๋ฉด ๋ ๋๋งํ ๋๋ง๋ค ๊ฐ์ด ๋ฌ๋ผ์ ธ ๋ถํ์ํ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ ์ ์์ต๋๋ค. -
useDeferredValue๊ฐ ํ์ฌ ๋ ๋๋ง(์ฌ์ ํ ์ด์ ๊ฐ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ) ์ธ์ ๋ค๋ฅธ ๊ฐ(Object.is๋ก ๋น๊ต)์ ๋ฐ์ผ๋ฉด ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ ๊ฐ์ผ๋ก ๋ฆฌ๋ ๋๋งํ๋๋ก ์์ฝํฉ๋๋ค.๊ฐ์ ๋ํ ๋ ๋ค๋ฅธ ์ ๋ฐ์ดํธ๊ฐ ์์ผ๋ฉด ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฆฌ๋ ๋๋ง์ ์ค๋จ๋ ์ ์์ต๋๋ค. React๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฆฌ๋ ๋๋ง์ ์ฒ์๋ถํฐ ๋ค์ ์์ํ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด ์ฐจํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๊ฐ๋ฅํ ์ง์ฐ๋ ๊ฐ์ ๋ฐ๋ ์๋๋ณด๋ค ์ฌ์ฉ์๊ฐ input์ ๊ฐ์ ์ ๋ ฅํ๋ ์๋๊ฐ ๋ ๋น ๋ฅธ ๊ฒฝ์ฐ, ์ฐจํธ๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅ์ ๋ฉ์ถ ํ์๋ง ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค. -
useDeferredValue๋<Suspense>์ ํตํฉ๋ฉ๋๋ค. ์๋ก์ด ๊ฐ์ผ๋ก ์ธํ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ๋ฐ์ดํธ๋ก ์ธํด UI๊ฐ ์ผ์ ์ค๋จ๋๋ฉด ์ฌ์ฉ์๋ ํด๋ฐฑ์ ๋ณผ ์ ์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ ๋ก๋ฉ๋ ๋๊น์ง ์ด์ ์ง์ฐ๋ ๊ฐ์ด ํ์๋ฉ๋๋ค. -
useDeferredValue๋ ๊ทธ ์์ฒด๋ก ์ถ๊ฐ ๋คํธ์ํฌ ์์ฒญ์ ๋ฐฉ์งํ์ง ์์ต๋๋ค. -
useDeferredValue์์ฒด๋ก ์ธํ ๊ณ ์ ๋ ์ง์ฐ์ ์์ต๋๋ค. React๋ ์๋์ ๋ฆฌ๋ ๋๋ง์ ์๋ฃํ์๋ง์ ์ฆ์ ์๋ก์ด ์ง์ฐ๋ ๊ฐ์ผ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฆฌ๋ ๋๋ง ์์ ์ ์์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฒคํธ๋ก ์ธํ ์ ๋ฐ์ดํธ(์: ํ์ดํ)๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฆฌ๋ ๋๋ง์ ์ค๋จํ๊ณ ์ฐ์ ์์๋ฅผ ๊ฐ์ต๋๋ค. -
useDeferredValue๋ก ์ธํ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฆฌ๋ ๋๋ง์ ํ๋ฉด์ ์ปค๋ฐ๋ ๋๊น์ง Effects๋ฅผ ์คํํ์ง ์์ต๋๋ค. ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฆฌ๋ ๋๋ง์ด ์ผ์ ์ค๋จ๋๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ก๋ฉ๋๊ณ UI๊ฐ ์ ๋ฐ์ดํธ๋ ํ์ ํด๋น Effects๊ฐ ์คํ๋ฉ๋๋ค.
์ฌ์ฉ๋ฒ
์ ์ฝํ ์ธ ๊ฐ ๋ก๋ฉ๋๋ ๋์ ์ค๋๋ ์ฝํ ์ธ ํ์ํ๊ธฐ
์ปดํฌ๋ํธ์ ์ต์์ ๋ ๋ฒจ์์ useDeferredValue๋ฅผ ํธ์ถํ์ฌ UI ์ผ๋ถ ์
๋ฐ์ดํธ๋ฅผ ์ง์ฐํ ์ ์์ต๋๋ค.
import { useState, useDeferredValue } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
// ...
}์ด๊ธฐ ๋ ๋๋ง ์ค์ ์ง์ฐ๋ ๊ฐ์ ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ๊ฐ๊ณผ ์ผ์นํฉ๋๋ค.
์ ๋ฐ์ดํธ๊ฐ ๋ฐ์ํ๋ฉด ์ง์ฐ๋ ๊ฐ์ ์ต์ ๊ฐ๋ณด๋ค โ๋ค์ณ์ง๊ฒโ ๋ฉ๋๋ค. React๋ ๋จผ์ ์ง์ฐ๋ ๊ฐ์ ์ ๋ฐ์ดํธํ์ง ์์ ์ฑ๋ก ๋ ๋๋งํ ๋ค์, ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์๋ก ๋ฐ์ ๊ฐ์ผ๋ก ๋ฆฌ๋ ๋๋ง์ ์๋ํฉ๋๋ค.
์ด๊ฒ์ด ์ธ์ ์ ์ฉํ์ง ์์๋ฅผ ํตํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ด ์์์์๋ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ถ๋ฌ์ค๋ ๋์ SearchResults ์ปดํฌ๋ํธ๊ฐ ์ผ์ ์ค์ง๋ฉ๋๋ค. "a"๋ฅผ ์
๋ ฅํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฐ ๋ค์ "ab"๋ก ์์ ํด ๋ณด์ธ์. "a"์ ๋ํ ๊ฒฐ๊ณผ๊ฐ ๋ก๋ฉ ํด๋ฐฑ์ผ๋ก ๋์ฒด๋ ๊ฒ์
๋๋ค.
import { Suspense, useState } from 'react'; import SearchResults from './SearchResults.js'; export default function App() { const [query, setQuery] = useState(''); return ( <> <label> Search albums: <input value={query} onChange={e => setQuery(e.target.value)} /> </label> <Suspense fallback={<h2>Loading...</h2>}> <SearchResults query={query} /> </Suspense> </> ); }
์ผ๋ฐ์ ์ธ ๋์ฒด UI ํจํด์ ๊ฒฐ๊ณผ ๋ชฉ๋ก ์
๋ฐ์ดํธ๋ฅผ ์ง์ฐํ๊ณ ์ ๊ฒฐ๊ณผ๊ฐ ์ค๋น๋ ๋๊น์ง ์ด์ ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ ํ์ํฉ๋๋ค. useDeferredValue๋ฅผ ํธ์ถํ์ฌ ์ฟผ๋ฆฌ์ ์ง์ฐ๋ ๋ฒ์ ์ ์ ๋ฌํ์ธ์.
export default function App() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
return (
<>
<label>
Search albums:
<input value={query} onChange={e => setQuery(e.target.value)} />
</label>
<Suspense fallback={<h2>Loading...</h2>}>
<SearchResults query={deferredQuery} />
</Suspense>
</>
);
}query๋ ์ฆ์ ์
๋ฐ์ดํธ๋๋ฏ๋ก input์ ์ ๊ฐ์ด ํ์๋ฉ๋๋ค. ๊ทธ๋ฌ๋ deferredQuery๋ ๋ฐ์ดํฐ๊ฐ ๋ก๋ฉ๋ ๋๊น์ง ์ด์ ๊ฐ์ ์ ์งํ๋ฏ๋ก SearchResults๋ ์ ์ ๋์ ์ค๋๋ ๊ฒฐ๊ณผ๋ฅผ ํ์ํฉ๋๋ค.
์๋ ์์์์ "a"๋ฅผ ์
๋ ฅํ๊ณ ๊ฒฐ๊ณผ๊ฐ ๋ก๋ฉ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ๋ค์, ์
๋ ฅ๊ฐ์ "ab"๋ก ์์ ํด๋ณด์ธ์. ์ด์ ์ ๊ฒฐ๊ณผ๊ฐ ๋ก๋ฉ๋ ๋๊น์ง Suspense ํด๋ฐฑ ๋์ ์ค๋๋ ๊ฒฐ๊ณผ ๋ชฉ๋ก์ด ํ์๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค:
import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; export default function App() { const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); return ( <> <label> Search albums: <input value={query} onChange={e => setQuery(e.target.value)} /> </label> <Suspense fallback={<h2>Loading...</h2>}> <SearchResults query={deferredQuery} /> </Suspense> </> ); }
Deep Dive
๋ ๋จ๊ณ๋ก ์งํ๋๋ค๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค
-
๋จผ์ , React๋ ์๋ก์ด
query("ab")๋ก ๋ฆฌ๋ ๋๋งํ์ง๋ง ์ด์ deferredQuery(์ฌ์ ํ"a")๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ฒฐ๊ณผ ๋ชฉ๋ก์ ์ ๋ฌํ๋deferredQuery๊ฐ์ โ์ง์ฐโ๋query๊ฐ์ ๋๋ค. -
๋ฐฑ๊ทธ๋ผ์ด๋์์ React๋
query์deferredQuery๋ฅผ ๋ชจ๋"ab"๋ก ์ ๋ฐ์ดํธํ ์ํ๋ก ๋ฆฌ๋ ๋๋ง์ ์๋ํฉ๋๋ค. ์ด ๋ฆฌ๋ ๋๋ง์ด ์๋ฃ๋๋ฉด React๋ ์ด๋ฅผ ํ๋ฉด์ ํ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ผ์ ์ค๋จ๋๋ ๊ฒฝ์ฐ("ab"์ ๋ํ ๊ฒฐ๊ณผ๊ฐ ์์ง ๋ก๋ฉ๋์ง ์์ ๊ฒฝ์ฐ) React๋ ์ด ๋ ๋๋ง ์๋๋ฅผ ํฌ๊ธฐํ๋ฉฐ, ๋ฐ์ดํฐ๊ฐ ๋ก๋ฉ๋ ํ ์ด ๋ฆฌ๋ ๋๋ง์ ๋ค์ ์๋ํฉ๋๋ค. ์ฌ์ฉ์๋ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋ ๋๊น์ง ์ค๋๋ ์ง์ฐ๋ ๊ฐ์ ๊ณ์ ๋ณด๊ฒ ๋ฉ๋๋ค.
์ง์ฐ๋ โbackgroundโ ๋ ๋๋ง์ ์ค๋จํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด input์ ๋ค์ ์ ๋ ฅํ๋ฉด React๋ ์ง์ฐ๋ ๊ฐ์ ๋ฒ๋ฆฌ๊ณ ์ ๊ฐ์ผ๋ก ๋ค์ ์์ํฉ๋๋ค. React๋ ํญ์ ๊ฐ์ฅ ์ต๊ทผ์ ์ ๊ณต๋ฐ์ ๊ฐ์ ์ฌ์ฉํฉ๋๋ค.
์ฌ์ ํ ๊ฐ ํค ์ ๋ ฅ๋ง๋ค ๋คํธ์ํฌ ์์ฒญ์ด ์๋ค๋ ์ ์ ์ฃผ์ํ์ธ์. ์ฌ๊ธฐ์ ์ง์ฐ๋๋ ๊ฒ์ ๋คํธ์ํฌ ์์ฒญ ์์ฒด๊ฐ ์๋๋ผ ๊ฒฐ๊ณผ๊ฐ ์ค๋น๋ ๋๊น์ง ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ๊ฒ์ ๋๋ค. ์ฌ์ฉ์๊ฐ ๊ณ์ ์ ๋ ฅํ๋๋ผ๋ ๊ฐ ํค ์ ๋ ฅ์ ๋ํ ์๋ต์ ์บ์ ๋๋ฏ๋ก ๋ฐฑ์คํ์ด์ค๋ฅผ ๋๋ฅด๋ฉด ์ฆ์ ๋ค์ ๊ฐ์ ธ์ค์ง ์์ต๋๋ค.
์ฝํ ์ธ ๊ฐ ์ค๋๋์์์ ํ์ํ๊ธฐ
์์ ์์์๋ ์ต์ ์ฟผ๋ฆฌ์ ๋ํ ๊ฒฐ๊ณผ ๋ชฉ๋ก์ด ์์ง ๋ก๋ฉ ์ค์ด๋ผ๋ ํ์๊ฐ ์์ต๋๋ค. ์ ๊ฒฐ๊ณผ๋ฅผ ๋ก๋ฉํ๋ ๋ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ฒฝ์ฐ ์ฌ์ฉ์์๊ฒ ํผ๋์ ์ค ์ ์์ต๋๋ค. ๊ฒฐ๊ณผ ๋ชฉ๋ก์ด ์ต์ ์ฟผ๋ฆฌ์ ์ผ์นํ์ง ์๋๋ค๋ ๊ฒ์ ์ฌ์ฉ์์๊ฒ ๋ ๋ช ํํ๊ฒ ์๋ฆฌ๊ธฐ ์ํด, ์ค๋๋ ๊ฒฐ๊ณผ ๋ชฉ๋ก์ด ํ์๋ ๋ ์๊ฐ์ ํ์๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
<div style={{
opacity: query !== deferredQuery ? 0.5 : 1,
}}>
<SearchResults query={deferredQuery} />
</div>์ด๋ ๊ฒ ๋ณ๊ฒฝํ๋ฉด ์ ๋ ฅ์ ์์ํ์๋ง์ ์ ๊ฒฐ๊ณผ ๋ชฉ๋ก์ด ๋ก๋ฉ๋ ๋๊น์ง ์ค๋๋ ๊ฒฐ๊ณผ ๋ชฉ๋ก์ด ์ฝ๊ฐ ์ด๋์์ง๋๋ค. ์๋ ์์์์์ ๊ฐ์ด ์ ์ง์ ์ผ๋ก ์ด๋์์ง๋ค๊ณ ๋๊ปด์ง๋๋ก CSS transition์ ์ถ๊ฐํ์ฌ ํ๋ฆฌ๊ฒ ํ์๋๋ ๊ฒ์ ์ง์ฐ์ํฌ ์๋ ์์ต๋๋ค.
import { Suspense, useState, useDeferredValue } from 'react'; import SearchResults from './SearchResults.js'; export default function App() { const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); const isStale = query !== deferredQuery; return ( <> <label> Search albums: <input value={query} onChange={e => setQuery(e.target.value)} /> </label> <Suspense fallback={<h2>Loading...</h2>}> <div style={{ opacity: isStale ? 0.5 : 1, transition: isStale ? 'opacity 0.2s 0.2s linear' : 'opacity 0s 0s linear' }}> <SearchResults query={deferredQuery} /> </div> </Suspense> </> ); }
UI ์ผ๋ถ์ ๋ํด ๋ฆฌ๋ ๋๋ง ์ง์ฐํ๊ธฐ
useDeferredValue๋ฅผ ์ฑ๋ฅ ์ต์ ํ๋ก ์ ์ฉํ ์๋ ์์ต๋๋ค. UI ์ผ๋ถ๊ฐ ๋ฆฌ๋ ๋๋ง ์๋๊ฐ ๋๋ฆฌ๊ณ , ์ด๋ฅผ ์ต์ ํํ ์ฌ์ด ๋ฐฉ๋ฒ์ด ์์ผ๋ฉฐ, ๋๋จธ์ง UI๋ฅผ ์ฐจ๋จํ์ง ์๋๋ก ํ๋ ค๋ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค.
ํค ์ ๋ ฅ ์๋ง๋ค ๋ฆฌ๋ ๋๋ง๋๋ ํ ์คํธ ํ๋์ ์ปดํฌ๋ํธ(์: ์ฐจํธ ๋๋ ๊ธด ๋ชฉ๋ก)๊ฐ ์๋ค๊ณ ์์ํด ๋ณด์ธ์
function App() {
const [text, setText] = useState('');
return (
<>
<input value={text} onChange={e => setText(e.target.value)} />
<SlowList text={text} />
</>
);
}๋จผ์ , props๊ฐ ๊ฐ์ ๊ฒฝ์ฐ ๋ฆฌ๋ ๋๋ง์ ๊ฑด๋๋ฐ๋๋ก SlowList๋ฅผ ์ต์ ํํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด, memo๋ก ๊ฐ์ธ์ฃผ์ธ์.
const SlowList = memo(function SlowList({ text }) {
// ...
});๊ทธ๋ฌ๋ ์ด๋ SlowList props๊ฐ ์ด์ ๋ ๋๋ง ๋์ ๋์ผํ ๊ฒฝ์ฐ์๋ง ๋์์ด ๋ฉ๋๋ค. ์ง๊ธ ์ง๋ฉดํ๊ณ ์๋ ๋ฌธ์ ๋ props๊ฐ ๋ค๋ฅด๊ณ ์ค์ ๋ก ๋ค๋ฅธ ์๊ฐ์ ์ถ๋ ฅ์ ๋ณด์ฌ์ค์ผ ํ ๋ ์๋๊ฐ ๋๋ฆฌ๋ค๋ ๊ฒ์
๋๋ค.
๊ตฌ์ฒด์ ์ผ๋ก, ์ฃผ์ ์ฑ๋ฅ ๋ฌธ์ ๋ input์ ํ์ดํํ ๋๋ง๋ค SlowList๊ฐ ์๋ก์ด props๋ฅผ ์์ ํ๊ณ ์ ์ฒด ํธ๋ฆฌ๋ฅผ ๋ฆฌ๋ ๋๋งํ๋ฉด ํ์ดํ์ด ๋๊ธฐ๋ ๋๋์ด ๋ ๋ค๋ ๊ฒ์
๋๋ค. ์ด ๊ฒฝ์ฐ useDeferredValue๋ฅผ ์ฌ์ฉํ๋ฉด ์
๋ ฅ ์
๋ฐ์ดํธ(๋นจ๋ผ์ผ ํ๋)๋ฅผ ๊ฒฐ๊ณผ ๋ชฉ๋ก ์
๋ฐ์ดํธ(๋๋ ค๋ ๋๋)๋ณด๋ค ๋์ ์ฐ์ ์์์ ๋ ์ ์์ต๋๋ค.
function App() {
const [text, setText] = useState('');
const deferredText = useDeferredValue(text);
return (
<>
<input value={text} onChange={e => setText(e.target.value)} />
<SlowList text={deferredText} />
</>
);
}์ด๋ ๊ฒ ํ๋ค๊ณ ํด์ SlowList์ ๋ฆฌ๋ ๋๋ง ์๋๊ฐ ๋นจ๋ผ์ง์ง๋ ์์ต๋๋ค. ํ์ง๋ง ํค ์
๋ ฅ์ ์ฐจ๋จํ์ง ์๋๋ก ๋ชฉ๋ก ๋ฆฌ๋ ๋๋ง์ ์ฐ์ ์์๋ฅผ ๋ฎ์ถ ์ ์๋ค๋ ๊ฒ์ React์ ์๋ ค์ค๋๋ค. ๋ชฉ๋ก์ ์
๋ ฅ๋ณด๋ค โ์ง์ฐโ๋์๋ค๊ฐ โ๋ฐ๋ผ์ก์โ ๊ฒ์
๋๋ค. ์ด์ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก React๋ ๊ฐ๋ฅํ ํ ๋นจ๋ฆฌ ๋ชฉ๋ก์ ์
๋ฐ์ดํธํ๋ ค๊ณ ์๋ํ์ง๋ง, ์ฌ์ฉ์๊ฐ ์
๋ ฅํ๋ ๊ฒ์ ์ฐจ๋จํ์ง๋ ์์ต๋๋ค.
์์ 1 of 2: ๋ชฉ๋ก ๋ฆฌ๋ ๋๋ง ์ง์ฐ
์ด ์์์์๋ SlowList ์ปดํฌ๋ํธ์ ๊ฐ ํญ๋ชฉ์ ์ธ์์ ์ผ๋ก ๋๋ ค์ง๋๋ก ํ์ฌ useDeferredValue๋ฅผ ํตํด input์ ๋ฐ์์ฑ์ ์ ์งํ๋ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค. input์ ํ์ดํํ๋ฉด ์
๋ ฅ์ ๋น ๋ฅด๊ฒ ๋๊ปด์ง๋ ๋ฐ๋ฉด ๋ชฉ๋ก์ โ์ง์ฐโ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
import { useState, useDeferredValue } from 'react'; import SlowList from './SlowList.js'; export default function App() { const [text, setText] = useState(''); const deferredText = useDeferredValue(text); return ( <> <input value={text} onChange={e => setText(e.target.value)} /> <SlowList text={deferredText} /> </> ); }
Deep Dive
์ด ์๋๋ฆฌ์ค์์ ์ด์ ์ ์ฌ์ฉํ์ ์ ์๋ ๋ ๊ฐ์ง ์ผ๋ฐ์ ์ธ ์ต์ ํ ๊ธฐ์ ์ด ์์ต๋๋ค
- ๋๋ฐ์ด์ฑ์ ํ์ดํ์ ๋ฉ์ถ ๋๊น์ง(์: 1์ด ๋์) ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ชฉ๋ก์ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
- ์ค๋กํ๋ง์ ๊ฐ๋์ฉ(์: ์ต๋ 1์ด์ ํ ๋ฒ) ๋ชฉ๋ก์ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์ด๋ฌํ ๊ธฐ๋ฒ๋ค์ ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ ์ฉํ์ง๋ง, useDeferredValue๋ React ์์ฒด์ ๊น๊ฒ ํตํฉ๋์ด ์๊ณ ์ฌ์ฉ์์ ๊ธฐ๊ธฐ์ ๋ง๊ฒ ์กฐ์ ๋๊ธฐ ๋๋ฌธ์ ๋ ๋๋ง์ ์ต์ ํํ๋ ๋ฐ ๋ ์ ํฉํฉ๋๋ค.
๋๋ฐ์ด์ฑ์ด๋ ์ค๋กํ๋ง๊ณผ ๋ฌ๋ฆฌ ๊ณ ์ ๋ ์ง์ฐ์ ์ ํํ ํ์๊ฐ ์์ต๋๋ค. ์ฌ์ฉ์์ ๋๋ฐ์ด์ค๊ฐ ๋น ๋ฅธ ๊ฒฝ์ฐ(์: ๊ณ ์ฑ๋ฅ ๋ ธํธ๋ถ) ์ง์ฐ๋ ๋ฆฌ๋ ๋๋ง์ ๊ฑฐ์ ์ฆ์ ๋ฐ์ํ๋ฉฐ ๋์ ๋์ง ์์ต๋๋ค. ์ฌ์ฉ์์ ๋๋ฐ์ด์ค๊ฐ ๋๋ฆฐ ๊ฒฝ์ฐ, ๊ธฐ๊ธฐ ์๋์ ๋น๋กํ์ฌ ๋ชฉ๋ก์ด input์ โ์ง์ฐโ๋ฉ๋๋ค.
๋ํ ๋๋ฐ์ด์ฑ์ด๋ ์ค๋กํ๋ง๊ณผ ๋ฌ๋ฆฌ, useDeferredValue์ ์ํด ์ํ๋๋ ์ง์ฐ๋ ๋ฆฌ๋ ๋๋ง์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋จํ ์ ์์ต๋๋ค. ์ฆ, React๊ฐ ํฐ ๋ชฉ๋ก์ ๋ฆฌ๋ ๋๋งํ๋ ๋์ค์ ์ฌ์ฉ์๊ฐ ๋ค๋ฅธ ํค ์
๋ ฅ์ ํ๋ฉด React๋ ํด๋น ๋ฆฌ๋ ๋๋ง์ ์ค๋จํ๊ณ ํค ์
๋ ฅ์ ์ฒ๋ฆฌํ ๋ค์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ฆฌ๋ ๋๋ง์ ์์ํฉ๋๋ค. ๋ฐ๋ฉด ๋๋ฐ์ด์ฑ๊ณผ ์ค๋กํ๋ง์ ๋ ๋๋ง์ด ํค ์
๋ ฅ์ ์ฐจ๋จํ๋ ์๊ฐ์ ์ง์ฐํ ๋ฟ์ด๋ฏ๋ก ์ฌ์ ํ ๋ถ์์ ํ ๊ฒฝํ์ ๋ง๋ค์ด ๋
๋๋ค.
์ต์ ํํ๋ ค๋ ์์ ์ด ๋ ๋๋ง ์ค์ ๋ฐ์ํ์ง ์๋ ๊ฒฝ์ฐ์๋ ๋๋ฐ์ด์ฑ๊ณผ ์ค๋กํ๋ง์ ์ฌ์ ํ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋๋ฐ์ด์ฑ๊ณผ ์ค๋กํ๋ง์ ์ฌ์ฉํ๋ฉด ๋คํธ์ํฌ ์์ฒญ์ ๋ ์ ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ธฐ์ ์ ํจ๊ป ์ฌ์ฉํ ์๋ ์์ต๋๋ค.