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๋ ํด๋น ๋ฆฌ๋ ๋๋ง์ ์ค๋จํ๊ณ ํค ์
๋ ฅ์ ์ฒ๋ฆฌํ ๋ค์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ฆฌ๋ ๋๋ง์ ์์ํฉ๋๋ค. ๋ฐ๋ฉด ๋๋ฐ์ด์ฑ๊ณผ ์ค๋กํ๋ง์ ๋ ๋๋ง์ด ํค ์
๋ ฅ์ ์ฐจ๋จํ๋ ์๊ฐ์ ์ง์ฐํ ๋ฟ์ด๋ฏ๋ก ์ฌ์ ํ ๋ถ์์ ํ ๊ฒฝํ์ ๋ง๋ค์ด ๋
๋๋ค.
์ต์ ํํ๋ ค๋ ์์ ์ด ๋ ๋๋ง ์ค์ ๋ฐ์ํ์ง ์๋ ๊ฒฝ์ฐ์๋ ๋๋ฐ์ด์ฑ๊ณผ ์ค๋กํ๋ง์ ์ฌ์ ํ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋๋ฐ์ด์ฑ๊ณผ ์ค๋กํ๋ง์ ์ฌ์ฉํ๋ฉด ๋คํธ์ํฌ ์์ฒญ์ ๋ ์ ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ธฐ์ ์ ํจ๊ป ์ฌ์ฉํ ์๋ ์์ต๋๋ค.