์ฝ 2 ๋ฌ ์ ์ REACT CONF 2024๊ฐ ์ด๋ ธ๋ค.
์ฌ๋ฌ ํ ํฌ๋ค์ด ์งํ๋์์๋๋ฐ, ๊ทธ์ค ๋ฐ๋ ๋ฐ๊ทผ(?)ํ React 19์ ์ ์์๋ค์ ์ดํด๋ณด๊ณ ์ ํ๋ค.
canary ๋ฒ์ ์ ๋ฆฌ์กํธ๋ฅผ ์ฐ๊ณ ์์๋ค๋ฉด ์๊ฐํ ๋ด์ฉ๋ค์ด ์ด๋ฏธ ์ต์ํ ๊ฒ๋ค์ผ ์ ์์ง๋ง,
์์ ํ๋ ๋ฒ์ ์ ๊ธฐ๋ค๋ฆฐ ๋์ ๊ฐ์ ์ฌ๋๋ค์ ํด๋น ํ ํฌ์์ ๋ฐ๊ฐ์ด ์์๋ค์ ์ ํด ๋ค์ ์ ์์ ๊ฑฐ ๊ฐ๋ค.
์ด๋ฒ์๋ ๊ฐ๋จํ๊ฒ ์ด๋ค ๊ฒ๋ค์ด ๋ฌ๋ผ์ก๋ ์ดํด๋ณด๊ณ , ์ค์ ๋ก ์๊ฐ๋ 19 ๋ฒ์ ์ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํด ๋ณด๊ณ ์ ํ๋ค.
๐ ๋ค๋ฃฌ ์ฃผ์ ๋ชฉ์ฐจ๋ก ์ดํด๋ณด๊ธฐ
1. Asynchoronous transitions: startTransition์ async ํจ์๋ฅผ ์ ๋ฌํ๊ธฐ
2. Actions: transition์ ํธ๋ฆฌ๊ฑฐํ๋ ํจ์๋ค
3. useActionState: ํ ์ ํตํ action ์์ฑ
4. action and formAction props : form, button, input ๋ฑ๊ณผ action ํจ๊ป ์ฐ๊ธฐ
5. useFormStatus : ๋ ์ฝ๊ฒ action์ form status์ ์ ๊ทผํ๊ธฐ
6. React Server Components : ํด๋ผ์ด์ธํธ ํ๊ฒฝ ์ธ์์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๋๋
7. use: promise์ resolved ๊ฐ์ด๋ context์ ๊ฐ ์ฝ๊ธฐ
8. Server Actions: ์๋ฒ์์ run ํ๋ ํจ์ ํด๋ผ์ด์ธํธ์์ call ํ๊ธฐ
> ๋ฆฌ์กํธ 19๋ถํฐ ๊ฐ์ ๋ ์ฌํญ๋ค
9. ref as prop: ํจ์ํ ์ปดํฌ๋ํธ์์ prop์ผ๋ก ref ์ ๊ทผ
10. Document metadata: ์ปดํฌ๋ํธ ๋ด์์ ์ง์ metadata ์ฌ์ฉํ๊ธฐ
11. Stylesheet support: ์ปดํฌ๋ํธ ๋ด์์ ์ง์ stylesheet ์ฌ์ฉํ๊ธฐ
12. Preloading API: ์ปดํฌ๋ํธ ๋ด์์ preload, preconnect, preinit, prefetchDNS ๋ฑ ์ฌ์ฉ
1. Asynchoronous transitions: startTransition์ async ํจ์๋ฅผ ์ ๋ฌํ๊ธฐ
startTransition์ ๋ฆฌ์กํธ 18์์ ์๊ฐ๋์๋ค.
transition์ ํตํด์ ์๋์ ์ผ๋ก urgent ํ state๋ค์ ๋งํนํ ์ ์๊ฒ ๋์๋ค.
๋ค์๊ณผ ๊ฐ์ด urgentํ ๋ฐ์ดํฐ๋ฅผ setUrgentState์ผ๋ก ๊ฐ์ธ์ฃผ๋ฉด ๋๋ค.
const [isPending, startTransition] = useTransition();
function handleData(){
setUrgentState(urgentData);
startTransition(()=>{
setNonUrgentState(nonUrgentData);
})
}
๋ฆฌ์กํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์๋ก ํ๋ ๋ชจ๋ ์ปดํฌ๋ํธ๋ค์ ํ๋์ ๊ณผ์ ์ผ๋ก ๋๋ ํ๋ค.
ํ์ง๋ง ์ ๋ฐ์ดํธ์ ๋ณต์ก๋์ ๋ฐ๋ผ ๋ฆฌ์กํธ๊ฐ ์ค์ ๋ก ๋๋๋ฅผ ๋ง์น๊ณ ์ด ์ ๋ฐ์ดํธ๋ฅผ DOM์ ์ปค๋ฐํ๊ธฐ๊น์ง์ ์๊ฐ์ด ๋ฌ๋ผ์ง ์ ์๋ค.
๋ฌธ์ ๋ ์ด ๋๋์ ์ปค๋ฐ์ ๊ณผ์ ์ด ๋ฉ์ธ thread์์ ์งํ๋๊ธฐ ๋๋ฌธ์, ์ฐ๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ ํ ๋ค๋ฅธ ํ์คํฌ๋ค์ ์ฒ๋ฆฌํ ์ ์๋ ์ํ๊ฐ ๋๋ค. ์ฌ์ฉ์๋ค์ ์ด๋ ๋ฌด๋ฐ์ํ UI๋ฅผ ๋ง์ฃผํ๊ฒ ๋๋ ์ ์ข์ ๊ฒฝํ์ ํ ์ ์๋ค.
์ฆ, ๋ฆฌ์กํธ๊ฐ ๋๋๋ฅผ ํ๊ณ DOM์ ๋ณํ๋ฅผ ์ปค๋ฐํ๋ ค๋ ๋์ค์ ์ฌ์ฉ์๊ฐ ์น์ฌ์ดํธ์์ ์ด๋ค ์ํธ์์ฉ์ ํ๊ณ ์ ํ๋ค๋ฉด,
ํผ๋๋ฐฑ์ด ์ง์ฐ๋๋ ํ์์ด ๋ฐ์ํ๊ฒ ๋๋ค.
์ด ๋ transition ํ ์ ์ฌ์ฉํ๋ฉด ์ฉ์ดํ๋ค.
transition์ ์ฌ์ฉํ๋ฉด ํ๋์ ๋ฐฉํด๋ฐ์ง ์์ ์ ๋ฐ์ดํธ ๋์ ,
๋ฆฌ์กํธ๋ ๋งค 5ms ๋ง๋ค ๋ฉ์ธ thread์๊ฒ ์ ์ด๊ถ์ ๋๊ฒจ์ค์ ์ฒ๋ฆฌ๋์ด์ผ ํ๋ ํ์คํฌ๋ค์ด ์๋์ง ํ์ธํ๋ค.
์๋ฅผ ๋ค๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ๋ฉ์ธ thread์ ํ์คํฌ๋ค์ด ์๋ค๊ณ ํ ๋,
๋ฆฌ์กํธ๋ ํ์ฌ ๋ ๋๋ฅผ ์ค์งํ๊ณ , ๋ธ๋ผ์ฐ์ ๊ฐ ๋จผ์ ํ์คํฌ๋ฅผ ์ฒ๋ฆฌํ๋๋ก ์์๋ฅผ ์๋ณดํ ๋ค, ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ๋ ๋ ์์
์ ๋ง์ ํ๋ค.
์ปค๋ฐ ์์ ์ ์ดํ, ๊ฐ์ฅ ํจ์จ์ ์ผ ๋ ์งํํ๋ค.
์๋์ฒ๋ผ input ๊ฐ์ form์ ์ ๋ ฅํ์ฌ ์ ์ถํ๋ ๊ฒฝ์ฐ๊ฐ ์ข ์ข ์๋ค.
// ...์ค๋ต...
const [name, setName] = useState('');
const [data, setData] = useState(null);
const [isPending, setIsPending] = useState(false);
async function handleSubmit(){
setIsPending(true); // isPending์ true๋ก ์ค์ ์ ๋ฆฌ์กํธ๊ฐ ๋ฆฌ๋๋๋ฅผ ์ํจ๋ค
const data = await updateData(name);
setIsPending(false);
setData(data);
}
return (
<div>
<input onChange={e => setName(e.target.value)}/>
<button onClick={handleSubmit}>
{isPending? "Updating..." : "Update"}
</button>
<span>{data?.success && "Changes saved!"}</span>
</div>
)
// ...์ค๋ต...
์ด ๋ฐฉ์์ด ํ๋ฆฐ ๊ฑด ์๋์ง๋ง, ํด๋น ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค.
์ฌ์ฉ์๊ฐ "Lydia"๋ผ๊ณ ์ ๋ ฅํ๊ณ updateDate ์ ์ถ์ด ๋ฐ์ํ๊ณ ์๋ ๋์, ๋ค์ ์ฌ์ฉ์๊ฐ "Evan"์ด๋ผ๊ณ ์ ๋ ฅํ๊ณ updateDate ์ ์ถ์ ํ ์ ์๋ค.
๋คํธ์ํฌ ์์ฒญ์ด ๋๋๊ณ data ๊ฐ ๋ฆฌํด๋์์ ๋, setData๋ก UI์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ฃผ๊ฒ ๋ ๊ฒฝ์ฐ,
์ฌ์ฉ์ ์ ์ฅ์์๋ ๊ฐ์ฅ ์ต์ ์ ์ ๋ ฅํ๋ ์ด๋ฆ์ด Evan์ด์๊ธฐ ๋๋ฌธ์ Evan์ผ๋ก ๋ฐ ๊ฑฐ๋ผ๊ณ ๊ธฐ๋ํ์ ์๋ ์๋ค.
ํ์ง๋ง ์ค์ ๋ก๋ Lydia์ ๋ํ ๋ฐ์ดํฐ ์์ฒญ์ด ๋๋ ๋ค, ํด๋น ๋ฐ์ดํฐ๋ก ์ ๋ฐ์ดํธ๊ฐ ๋ฐ์ํ๊ณ ,
Evan์ ๋ํ ์์ฒญ์ด ๋๋์ผ์ง๋ง ํด๋น ์ ๋ณด๋ก UI๊ฐ ์ ๋ฐ์ดํธ๋๋ค.
๋ฟ๋ง ์๋๋ผ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํ boilerplate ์ฝ๋(์๋ฌ์ฒ๋ฆฌ ๋ฑ๋ฑ๊น์ง ํฌํจ ๋ฑ๋ฑ)๊ฐ ์ฅํฉํ๊ฒ ๋๊ปด์ง ์ ์๋ค.
transition์ ์ฌ์ฉํด ๋ค์๊ณผ ๊ฐ์ด ์์ ํด ๋ณด์.
// ...์ค๋ต...
const [name, setName] = useState('');
const [data, setData] = useState(null);
// const [isPending, setIsPending] = useState(false);
// ์์
const [isPending, startTransition] = useTransition();
async function handleSubmit(){
// setIsPending(true);
// const data = await updateData(name);
// setIsPending(false);
// setData(data);
startTransition(async () => {
const data = await updateData(name);
startTransition(async () => {
setData(data);
})
})
}
return (
<div>
<input onChange={e => setName(e.target.value)}/>
<button onClick={handleSubmit}>
{isPending? "Updating..." : "Update"}
</button>
<span>{data?.success && "Changes saved!"}</span>
</div>
)
// ...์ค๋ต...
๋ค๋ง ํ์ฌ์ limitation์ผ๋ก๋ startTransition ์์ await ํค์๋ ์ดํ์ state ์ ๋ฐ์ดํธ๋ ์์ง ๋ํดํธ๋ก transition์ผ๋ก ๋งํน๋์ด ์์ง ์๊ธฐ ๋๋ฌธ์ ๋ค์ startTransition๋ฅผ ๊ฐ์ธ์ค์ผ ํ๋ค. (async context๊ฐ ์ฌ์ฉ๊ฐ๋ฅํด์ง๊ธฐ ์ ๊น์ง๋!)
transition์ผ๋ก ์ฝ๋๋ฅผ ๋ณ๊ฒฝ ํ, ๋ค์ Lydia๋ฅผ ์ ๋ ฅํ๊ณ ์ ์ถํ๊ณ ์๋ ๋์ค์ Evan์ ์ ๋ ฅํ๊ณ ์ ์ถํ๋ ์ํฉ์ ์ดํด๋ณด์.
์ด๋ฒ์๋ ์์ ์ํฉ๊ณผ๋ ๋ฌ๋ฆฌ Evan์ ๊ดํ ๋ฐ์ดํฐ๋ง ํ๋๋ง ํ๋ฉด์ ๋ ๋ ๋๋ค.
์ด๋ ์ฌ๋ฌ ๊ฐ์ transition์ด ์งํ ์ค์ด๋ผ๋ฉด, ๋ฆฌ์กํธ๋ ์ด transition๋ค์ batch ํ๊ณ ,
๋ชจ๋ transition์ด ์ข ๋ฃ๋ ์ดํ์์ผ๋ง commit์ ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ผ์ ํ๋์ ํ์ธํธ์ธ 'Evan'๋ง ๋ฐ์ํ๋ค.
2. Actions: transition์ ํธ๋ฆฌ๊ฑฐํ๋ ํจ์๋ค
3. useActionState: ํ ์ ํตํ action ์์ฑ
useActionState์ ๋ฆฌ์กํธ 19์์ ์๋กญ๊ฒ ๋ฑ์ฅํ ํ ์ด๋ค.
action์ ์ฌ์ฉํ๊ณ , transition ์ค status ์ ๋ฐ์ดํธ๋ค์ ์ ๊ทผํ๊ณ , ์ ๊ทผํ state๋ค๋ก state์ ์ค์ ํ๊ธฐ์ ์ฉ์ดํ ํ ์ด๋ค.
useActionState ํ ์ด ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด ์๋์ง ์ดํด๋ณด์.
- useActionState๋ ์ธ ๊ฐ์ ๊ฐ์ ๋ฐฐ์ด๋ก ๋ฆฌํดํ๋ค. ๊ฐ๊ฐ์ ๊ฐ์ ์ดํด๋ณด์.
- state: useActionState์ ๋ ๋ฒ์งธ ์ธ์๋ก ๋๊ฒจ์ค initialState(์์ ๊ฒฝ์ฐ null), ๋๋ action ํ ๋ฆฌํด๋๋ ๋ฐ์ดํฐ ๊ฐ
- action : useActionState์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ๋๊ฒจ์ค action ํจ์ ๋ฆฌํด. transition์ trigger ํ๋๋ก ๊ฐ์ ์ฌ์ฉํ ์ ์๋ค.
- isPending: transition์ด ์์ํ์๋ง์ true๊ฐ์ ์ง๋๋ค. transition์ด dom์ commit ๋๋ฉด ์๋์ ์ผ๋ก false๊ฐ์ด ๋๋ค.
์ด๋ฒ์๋ ์ด์ ์ useTransition์ผ๋ก ๋ฆฌํํ ๋ง ํ๋ ์ฝ๋๋ฅผ useActionState์ ํ์ฉํด ๋ฆฌํํ ๋ง ํด๋ณด์.
์ด์ ์๋ transition state๋ฅผ ์ง์ ์ ๋ฐ์ดํธํด ์ค ํ์๋ ์์ด์ก์ง๋ง, ์ฌ์ ํ ์ง์ state ์ ๋ฐ์ดํธ๋ฅผ ํด์คฌ์ด์ผ ํ๋ค.
// ...์ค๋ต...
// const [name, setName] = useState('');
// const [data, setData] = useState(null);
// const [isPending, startTransition] = useTransition();
// ์์
const [isPending, startTransition] = useActionState(
async(currentState, formData)=>{
const name = await formData.get('name');
const data = await updateDate(name);
return data;
},
null
);
// async function handleSubmit(){
// setIsPending(true);
// const data = await updateData(name);
// setIsPending(false);
// setData(data);
// startTransition(async () => {
// const data = await updateData(name);
// startTransition(async () => {
// setData(data);
// })
// })
// }
return (
{/**<div>
<input onChange={e => setName(e.target.value)}/>
<button onClick={handleSubmit}>
{isPending? "Updating..." : "Update"}
</button>
<span>{data?.success && "Changes saved!"}</span>
</div> */}
<form action={action}>
<input name='name'/>
<button onClick={handleSubmit}>
{isPending? "Updating..." : "Update"}
</button>
<span>{data?.success && "Changes saved!"}</span>
</form>
)
// ...์ค๋ต...
useActionState์ผ๋ก ๋ ์ด์ ์ฌ๋ฌ ๊ฐ์ ๋ฐ์ดํฐ state๊ฐ ๋ถํ์ํด์ก๊ณ ,
formData์ name์ผ๋ก ์ ๊ทผํ ์ ์์ด์ ธ์ ์ฝ๋๊ฐ ๋ ๊น๋ํด์ก๋ค.
4. action and formAction props : form, button, input ๋ฑ๊ณผ action ํจ๊ป ์ฐ๊ธฐ
๋ฆฌ์กํธ dom์ action๊ณผ formAction ํ๋กญ์ค๋ก ์ง์ action์ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ค.
action ๋๋ formAction์ผ๋ก ํ๋กญ์ค๋ก ์ ๋ฌํ ํจ์๋ async์ผ ์๋ ์๊ณ ์๋ ์๋ ์๋ค.
๋ค๋ง ์ ๋ฌํ ํจ์๋ ๋ชจ๋ action์ด๋ค. (transition์ trigger ํ๋ค)
5. useFormStatus : ๋ ์ฝ๊ฒ action์ form status์ ์ ๊ทผํ๊ธฐ
์ง์ ์ ์ ์ถํ form์ status์ ๋ ์ฝ๊ฒ ์ ๊ทผํ ์ ์๋ค.
useFormStatus ํ ์ ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๋ค.
- data: ํ์ฌ ์ ์ถํ form ๋ฐ์ดํฐ
- pending: transition์ pending state
๋ค์์ ์์๋ฅผ ์ดํด๋ณด์.
useFormStatus ํ ์ useContext์ฒ๋ผ action ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ค.
์ฆ, useActionState๋ฅผ ์ฌ์ฉํ๊ณ ์๋ ์์(๋ถ๋ชจ) ์ปดํฌ๋ํธ๋ก ๊ฐ์ธ์ค ํ์์ ์ปดํฌ๋ํธ๋ค์
action ๋ฐ์ดํฐ์ ์ฝํ ์คํธ๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
function Form(){
const [data, action] = useActionState();
return (<form>
<input name="name"/>
<StyledButton/>
<span>{data.success && "Changes saved!"}</span>
</form>)
}
function StyledButton(){
const {pending} = useFormStatus();
return (<button style={...}>
{pending? "Updating...": "Updaate"}
</button>)
}
context์ ์ ์ฌํ๊ฒ, ์ค์ ๋ก form์ ๋๋ ํ๋ ์ปดํฌ๋ํธ(๋ถ๋ชจ ์ปดํฌ๋ํธ)๊ฐ ์๋ ์์ ์ปดํฌ๋ํธ์์ ํธ์ถํด์ผ ํ๋ค.
6. useOptimistic : action์ด ์๋ฃ๋๊ธฐ ์ ์ UI๋ฅผ optimistic ํ๊ฒ ์ ๋ฐ์ดํธํ๊ธฐ
action ์์ async ํ์คํฌ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฆฌํด์ ํ๊ธฐ๊น์ง ์๊ฐ๋ณด๋ค ๋ง์ ์๊ฐ์ด ์์๋ ์๋ ์๊ณ ์ ์ ๋ค์ด ๋๋ฆฐ ์ธํฐ๋ท ์ปค๋ฅ์ ์ ์ฌ์ฉ ์ค์ผ ์๋ ์๋ค. ์ด๋ด ๊ฒฝ์ฐ isPending์ ์ํ๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ๋ณด๋ค๋ ์ด๋ฏธ action์ด ์๋ฃ๋ ๊ฒ ๊ฐ์ ์ํ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ ์๋ ์๋ค.
์ด๋ฏธ action์ด ์๋ฃ๋ ์ํ๋ฅผ ๋ณด์ฌ์ฃผ๋ ค๋ฉด ์ด๋ค ๋ฐ์ดํฐ๊ฐ ๋ฆฌํด๋ ๊ฑด์ง ์์์ผ ํ๋๋ฐ ์ด๋ป๊ฒ ํ๋ฉด ๋ ๊น?
์ด๋ useOptimistic ํ ์ผ๋ก ๋ฆฌํด๋ ํจ์๋ฅผ ํตํด transition์ด ์๋ฃ๋๊ธฐ ์ ์ UI๋ฅผ ์ ๋ฐ์ดํธํ ์ ์๋ค.
useOptimistic ํ ์ ๋ค์์ ๊ฐ๋ค์ ๋ฐฐ์ด๋ก ๋ฆฌํดํ๋ค.
- allValues: ๋ฆฌํดํ ๋ฐฐ์ด์ ์ฒซ ์ธ๋ฑ์ค์๋ ํ์ฌ state์ด๋ค. action ์ด pending ์ค์ด ์๋๋ผ๋ฉด initial state๋ฅผ, pending ์ค์ด๋ผ๋ฉด update ํจ์๋ก ๋ฆฌํดํ ๊ฐ ([... currentState, optimisticValue])์ ์ง๋๋ค.
- update ํจ์: (currentState, optimisticValue) =>{return [...currentState, optimisticValue]} ์ ํด๋นํ๋ ์ค์ ์ ๋ฐ์ดํธ ํจ์.
๋์ ์์๋ฅผ ์ดํด๋ณด์.
๋ค์๊ณผ ๊ฐ์ด messagesFromServer ํ๋กญ์ผ๋ก ๋ฒ๋ก๋ถํฐ ๋ฉ์์ง๋ฅผ ๋ฐ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค๊ณ ํ์.
๋จผ์ useOptimistic ํ ์์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก messageFromSever ํ๋กญ์ผ๋ก๋ถํฐ ๋ฐ์ ๊ฐ์ initial state๋ก ์ง์ ํ๊ณ , ์๋ฒ์์ ๋ฐ์ ์ด ๊ฐ์ด ๋๋ ๋๋ค.
๋ง์ฝ ๋ค์๊ณผ ๊ฐ์ด ์ ์ ๊ฐ ๋ฉ์์ง๋ฅผ ์ ์ถํ๋ฉด addMessage action์ด trigger ๋๋ค.
addMessage action ์์ ์ฐ์ ๋ฐฉ๊ธ ์ ๋ ฅํ๋ ๊ฐ์ผ๋ก addOptimisticMessage ํจ์๊ฐ ํธ์ถ๋๊ณ ,
useOptimistic ํ ์ update ํจ์๊ฐ trigger ๋๋ค.
trigger ๋ updateํจ์๋ ์๋ฒ์์ ๋ฐ์ currentMessages์ ์๋ก์ด optimisticMessage์ ๋ด์ ๋ฐฐ์ด์ ๋ฆฌํดํ๋ค.
์ด์ pending ์ค์ด๋ฏ๋ก allMessages๋ ์
๋ฐ์ดํธ๋๋ค.
์์ง ๋ณด๋ด์ง๊ณ ์๋ค๋ ๊ฑธ ๋ช ์ํ๊ธฐ ์ํด 'Sending...'๋ฑ์ ๋ฌธ๊ตฌ๋ฅผ ์ถ๊ฐํด ์ค ์ ์๋ค.
์ดํ์ ์๋์ ๊ฐ์ด ์ค์ ๋ก ์์ฒญ์ ๋ณด๋ด๊ณ ,
์์ฒญ์ด ์ฑ๊ณตํ๋ฉด messagesFromServer ํ๋กญ์ด ์ ๋ฐ์ดํธ๋๊ณ ,
์ด ๊ฐ์ initial state๋ก ์ผ๊ธฐ ๋๋ฌธ์ ์ด์ allMessages๋ ์ด ์ ๋ฐ์ดํธ๋ ๊ฐ์ ๊ฐ๊ฒ ๋๋ค.
๋ฐ๋ผ์ re-render๊ฐ ๋ฐ์ํ๊ณ allMessages๊ฐ์ ๋ณด์ฌ์ฃผ๊ฒ ๋๋ค. (๋ฆฌ๋๋๋ง ์ ๊น์ง๋ optimistic ์ ๋ฐ์ดํธ์ ๋ฐ์ดํฐ๋ฅผ ๋ณธ ๊ฒ)
์ด์ ๊น์ง ๋ํดํธ๋ก async ํ action์ transition์ trigger ํ๋ค๋ ๊ฒ์ ์ดํด๋ดค์๋ค.
ํ์ง๋ง useOptimistic์ UI์ ๊ณง๋ฐ๋ก ๋ฐ์์ด ๋๋๋ก ํ๋ค.
์ง๊ธ๊น์ง๋ Client API์ ๋ํด ์ดํด๋ดค์๋ค.
์ด๋ฒ์๋ Server API์ ๋ํด ์ดํด๋ณด์.
6. React Server Components : ํด๋ผ์ด์ธํธ ํ๊ฒฝ ์ธ์์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๋๋
์ ํต์ ์ผ๋ก ๋ ๋๋ง ๋ฐฉ์์๋ client-side์ server-side๊ฐ ์๋ค.
1. Client-side Rendering
- ์๋ฒ ์ฌ์ด๋์ ๋ฆฌ์กํธ ํธ๋ฆฌ๊ฐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค๋ก ๋๋ ๋๊ณ ,
- minimal html์ด ํด๋ผ์ด์ธํธ ์ฌ์ด๋์ ์ ๋ฌ
- ํด๋ผ์ด์ธํธ ์ฌ์ด๋์ ๋ฆฌ์กํธ ํธ๋ฆฌ๊ฐ ๋ฒ๋ค๋ ์๋ฒ ์ฌ์ด๋ ๋ฆฌ์กํธ ํธ๋ฆฌ๋ก ๋ฆฌ์กํธ ํธ๋ฆฌ๋ฅผ rebuild
2. Server-side Rendering
- ๋ฆฌ์กํธ ํธ๋ฆฌ๊ฐ html๊ณผ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค๋ก ๋๋๋๊ณ ,
- ์ด ๋ฒ๋ค์ด ํด๋ผ์ด์ธํธ ์ฌ์ด๋์ ์ ๋ฌ
- static html์ด ๋ฒ๋ค ์์์ ์ํธ์์ฉ๊ฐ๋ฅํ๊ฒ๋ rebuild
๋ ๋ ๋๋ง ๋ฐฉ์ ๋ชจ๋ ๋ฆฌ์กํธ ํธ๋ฆฌ๋ฅผ ์ด๋ฏธ ์๋ฒ์ ๊ฐ๊ณ ์์์๋ ๋ฆฌ์กํธ ๋ ๋๋ฌ๊ฐ client-side์์ rebuild ํด์ผ ํ๋ค๋ ์
(react18) Concurrent renderer ๋ฑ์ฅ์ผ๋ก React Server Component ๋ฑ์ฅ
- RSC๋ ์ค์ serialized ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ฅผ ํน์ํ json ํ์์ผ๋ก ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ ์ ์๊ฒ๋ ํ๋ค.
- ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋๋๋ฌ๋ ์ด json ํฌ๋งท์ ์ฝ์ด์ html์ด๋ js ์์ด๋ ๋ฆฌ์กํธ ํธ๋ฆฌ๋ฅผ rebuild ํ ์ ์๊ฒ ๋์๋ค.
RSC๋ ํด๋ผ์ด์ธํธ์ ์ง์ ์ ๋ฌ๋์ง ์๊ณ , ๋ค์๊ณผ ๊ฐ์ json ํ์์ผ๋ก ๋ฆฌํด ๊ฐ๋ง ์ ๋ฌ๋๋ค.
๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ด ์๋ฒ ์ฌ์ด๋์ ๊ธฐ๋ฅ(DB์ ๊ทผ, ํ์ผ ์์คํ ์ด์ฉ ๋ฑ๋ฑ)๋ค์ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ง์ ์ธ ์ ์๊ฒ ๋์๋ค.
๋ฆฌ์กํธ 19๋ถํฐ๋ aysnc/await๋ก ์๋ฒ ์ปดํฌ๋ํธ๋ฅผ ๋๋ ํ ์ ์๊ฒ ๋์ด ๋์ฑ ์ฝ๊ฒ ์๋ฒ ์ฌ์ด๋์ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ ์ ์๋ค.
์๊ฐ๋ณด๋ค db์์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ธฐ ์ํ ์๊ฐ์ด ๋ง์ด ์์๋๋ ์ํฉ์ด ์์ ์ ์๋ค.
์ด ๊ฒฝ์ฐ ๋ฆฌ์กํธ ํธ๋ฆฌ ์ ์ฒด๊ฐ ๋ฐ์ดํฐ๊ฐ fetch ์๋ฃ๋ ๋๊น์ง, ๊ทธ๋ฆฌ๊ณ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌ๋ ๋๊น์ง ๋๊ธฐํด์ผ ํ๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ suspense boundary๋ก ๊ฐ์ธ์ค์ ์๋์ ์ผ๋ก ๋น ๋ฅธ ๋ถ๋ธ๋ค์ ํด๋ผ์ด์ธํธํํ stream ํด์ ๋๋ ํ๊ณ ,
๊ธฐ๋ค๋ คํ๋ ๋ถ๋ถ๋ค์ suspense fallback์ ๋ ๋ ํ ์ ์๋ค.
๋ฐ์ดํฐ fetch๊ฐ ์๋ฃ๋๊ณ rc payload๊ฐ ์์ฑ์๋ฃ๋ ์์ ์ ํด๋น ์ปดํฌ๋ํธ๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌ๋๊ณ ๋ ๋ ๋๋ค.
๋ฆฌ์กํธ ์ปดํฌ๋ํธ๊ฐ ์๋ฌด๋ฐ js ์ฝ๋ ์์ด ์๋ฒ์์๋ง ๋ ๋ ๋ ํ json์ผ๋ก ๋ ๋ ๋๊ธฐ ๋๋ฌธ์ ๋ํดํธ๋ก ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ ์ ์๋ค. ์ฆ, hook์ด๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ฑ์ ์ฌ์ฉํ๊ฑฐ๋ window๊ฐ์ฒด์ ์ ๊ทผํ ์ ์๋ค.
ํด๋ผ์ด์ธํธ ์ฌ์ด๋๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ ๋ ํ๊ธฐ ์ํด์๋ ๋ช ์์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ ์ถ๊ฐํด์ผ ํ๋ค.
๋ฒ๋ค๋ฌ์๊ฒ ๋ช ์ํ๊ธฐ ์ํด์ "use client" ๋ฒ๋ค๋ฌ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
"use client" ๋ช ๋ น์ด๋ฅผ ์ถ๊ฐ ์, ๋ฆฌ์กํธ๋ ์๋ฒ์์ ์ด ์ปดํฌ๋ํธ๋ฅผ ๋ ๋ ํ์ง ์๊ณ CSR๋ก ๋ ๋ ํ๋ ๋ฐฉ์์ ํํ๋ค.
๋ฆฌํด ๊ฐ๋ฟ๋ง ์๋๋ผ ์ปดํฌ๋ํธ ์์ฒด๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ๋ณด๋ด๊ธฐ ๋๋ฌธ์ ์๋ฒ ์ปดํฌ๋ํธ์์ ๊ทธ๋ฌ๋ฏ์ด ๋ฐ์ดํฐ๋ฅผ fetch ํด์ฌ ์ ์๊ฒ ๋์๋ค.
๋์ ๋ค์๊ณผ ๊ฐ์ด ์๋ฒ ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ๋ฅผ fetch ํด์ค๊ณ props๋ก ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ ์ ๋ฌํ๋ ๋ฐฉ์์ ํํ๊ฑฐ๋
๋ค์์ ์ค๋ช ํ ํด๋ผ์ด์ธํธ API์ธ use๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
use API๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ฌ์ฉํ์ฌ ์ค์ ๋ฐ์ดํฐ ๋์ promise๋ฅผ props๋ก ์ ๋ฌํ๋ ๋ฐฉ์์ ํํ ์ ์๋ค.
7. use : promise์ resolved ๊ฐ์ด๋ context์ ๊ฐ ์ฝ๊ธฐ
โ ๏ธ ์ฃผ์! use๋ ํ ์ด ์๋ api๋ค.
์ง์ ์ ์ดํด๋ดค๋ ์์์์ reactionsPromise๋ ์๋ฒ ์ปดํฌ๋ํธ์์ ์์ฑ๋์๋ค.
๊ฐ์ await ํ๋ ๋์ ์ด promise๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ๊ณ , ํด๋ผ์ด์ธํธ์์ use API๋ก ์ ๋ฌํ๊ฒ ๋๋ค.
use API๋ ์๋์ ์ผ๋ก Suspense์ ErrorBoundary์ ํตํฉ๋๋๋ฐ,
๋ค์๊ณผ ๊ฐ์ด ํด๋ผ์ด์ธํธ์์ promise๊ฐ resolve ๋๊ธฐ ์ ๊น์ง๋ suspense fallback์ ๋ณด์ฌ์ฃผ๊ณ ,
promise๊ฐ resolve ๋ ์ดํ ๋ค์๊ณผ ๊ฐ์ด ํด๋น ์ปดํฌ๋ํธ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ฃผ๊ฑฐ๋ promise๊ฐ rejected ๋๋ฉด errorBoundary๋ฅผ ๋ณด์ฌ์ค๋ค.
use API๋ฅผ ํด๋ผ์ด์ธํธ์ ์ง์ ์ฌ์ฉํ๋ ๊ฒ์ ์ฅ์ ์ ๋๋จธ์ง ์๋ฒ ์ปดํฌ๋ํธ๋ค์ ๋ฐ์ดํฐ๋ฅผ await ํ ํ์ ์์ด ํด๋ผ์ด์ธํธ์ ๋ฏธ๋ฆฌ stream ๋๋ค๋ ์ ์ด๋ค.
use API๋ฅผ ํตํด async ๋ฐ์ดํฐ๋ฅผ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ์์ํ๊ฒ ๋ค๋ฃฐ ์ ์๊ฒ ๋๋ค.
์ด์ ์๋ ์๋์ ์ฝ๋(์ผ์ชฝ)์ฒ๋ผ api endpoint๋ฅผ ์ค์ ํ๊ณ , ๋ก๋ฉ/์๋ฌ state ์ค์ ์ ํด์ผ ํ์ง๋ง,
useAPI๋ฅผ ํตํด (์ค๋ฅธ์ชฝ) ๋ฆฌ์กํธ ๋ด๋ถ์ ์ผ๋ก ์ด ๋ถ๋ถ์ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๋ฅผ ๋จ์ํํ ์ ์๊ฒ ๋์๋ค.
use API๋ async ํจ์๋ฟ๋ง ์๋๋ผ context์ ์ฐ์ผ ์ ์๋ค.
useContext ํ ๊ณผ ๋์ผํ์ง๋ง ์กฐ๊ฑด๋ถ์ ์ผ๋ก ํธ์ถํ ์ ์๋ค๋ ์ ์์ ์ฐจ์ด๊ฐ ์๋ค.
์ฆ, early return์ด๋ ์กฐ๊ฑด๋ฌธ ๋ด์์ ํธ์ถ ๊ฐ๋ฅํ๋ค๋ ์ ์์ useContext๋ณด๋ค ๋ ์ ์ฐํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
8. Server Actions : ์๋ฒ์์ run ํ๋ ํจ์ ํด๋ผ์ด์ธํธ์์ call ํ๊ธฐ
์๋ฒ ํ๊ฒฝ์์ server action์ ์์ฑํ ์ ์๊ฒ ๋์๋ค.
server action์ด๋ ์๋ฒ ์ฌ์ด๋์์ ์คํ(run)ํ์ง๋ง ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ํธ์ถ(call)๋ ์ ์๋ ํจ์๋ค.
server action์ ๋ฆฌ์กํธ ๋ด๋ถ์ ์ธ ํน์ฑ์ด๋ผ๊ธฐ๋ณด๋ค๋ framework์ ํจ๊ป ์ฐ์ด๊ธฐ ์ํ ํน์ฑ์ด๋ผ๊ณ ํ๋ค.
"use server" ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฒ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ์ ์๋ค.
ํจ์์ body ์์ ๋ช ์ํ๊ณ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ props๋ก ์ ๋ฌํ๊ฑฐ๋
ํ์ผ์ ์ต์๋จ์ ๋ช ์ํ์ฌ serverAction๋ฅผ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ import ํ๋ ๋ฐฉ์์ ์ทจํ ์ ์๋ค.
endpoint ๊ตฌํ์ ์ฌ์ฉํ๋ framework์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๊ฒ ์ง๋ง,
server action์ด trigger ๋๋ฉด ์ด ํจ์๋ฅผ ์คํํ๊ธฐ ์ํด ๋ฆฌ์กํธ๋ ์ด ์์ฒญ์ ์๋ฒ์๊ฒ ์ ๋ฌํ๊ฒ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ์์ฒญ์ state๋ฅผ useActionState, useTransition, useFormStatus ๋ฑ์ ํ ์ผ๋ก ์ถ์ ํ ์ ์๋ค.
์ง๊ธ๊น์ง๋ ๋ฆฌ์กํธ 19์์ ์๋ก ์๊ฐ๋ ๊ธฐ๋ฅ๋ค์ ๋ํด ์ดํด๋ดค์๋ค.
๋ค์์ ๊ฐ์ ๋ ์ฌํญ๋ค์ ๋ํด ์ดํด๋ณด๊ณ ๋ง๋ฌด๋ฆฌํ ์์ ์ด๋ค.
9. ref as prop : ํจ์ํ ์ปดํฌ๋ํธ์์ prop์ผ๋ก ref ์ ๊ทผ
๋ฆฌ์กํธ 19๋ถํฐ๋ ์๋ฒ ์ปดํฌ๋ํธ์์ ref๋ฅผ prop์ผ๋ก ์ ๊ทผํ ์ ์๊ฒ ๋์๋ค.
์ด์ ์๋ ref๋ฅผ ์๋ฒ ์ปดํฌ๋ํธ์ ์ง์ ์ ๋ฌํ๊ธฐ ์ํด์๋ forwardRef๋ฅผ ์ฌ์ฉํด์ผ ํ์๋ค (์ผ์ชฝ ์ฌ์ง).
ํ์ง๋ง ๋ฆฌ์กํธ 19๋ถํฐ๋ forwardRef ์์ด ์ผ๋ฐ prop์ฒ๋ผ ์ ๊ทผ ๊ฐ๋ฅํด์ก๋ค (์ค๋ฅธ์ชฝ ์ฌ์ง).
๋ํ ref ์ฝ๋ฐฑํจ์ ๋ด์ cleanup ํจ์๊ฐ ์ ๊ณต๋๋๋ฐ, ๋ค์๊ณผ ๊ฐ์ด ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ ๊ฑฐํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์๋ฐฉํ ์ ์๋ค.
10. Document metadata : ์ปดํฌ๋ํธ ๋ด์์ ์ง์ metadata ์ฌ์ฉํ๊ธฐ
์ด์ ์ ์ปดํฌ๋ํธ ๋ด์์ ์ง์ metatag๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ react helmet๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
๋ฆฌ์กํธ 19๋ถํฐ๋ ๋ฆฌ์กํธ ์์ฒด์ ์ผ๋ก ์ปดํฌ๋ํธ ๋ด๋ถ์์ metatag๋ฅผ ์ฌ์ฉํ๋ฉด head๋ก hoisting์ ํด์ค๋ค.
ํ์ง๋ง ์์ง ์ปค์คํ metatag๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ๋ค๋ฉด react helmet ํด์ ์ฌ์ฉํด์ผ ํ๋ค.
11. Stylesheet support : ์ปดํฌ๋ํธ ๋ด์์ ์ง์ stylesheet ์ฌ์ฉํ๊ธฐ
๋ฆฌ์กํธ 19๋ถํฐ๋ ์คํ์ผ์ํธ๋ฅผ ์ฌ์ฉํ๊ณ ์๋ ์ปดํฌ๋ํธ ๋ด์์ ์ง์ ์ฌ์ฉํ ์ ์๊ฒ ๋์๋ค.
metatag๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฆฌ์กํธ๋ ์ด ํ๊ทธ๋ค์ head๋ก hoist ํ์ฌ css๊ฐ ๋ก๋๋๊ธฐ ์ ๊น์ง ๋ธ๋ผ์ฐ์ ๊ฐ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋ ํ์ง ์๋๋ก ํ๋ค.
๋ฟ๋ง ์๋๋ผ suspense ์์์๋ ์ฌ์ฉ๊ฐ๋ฅํ๋ฐ,
๋ฆฌ์กํธ๋ ๋ค์๊ณผ ๊ฐ์ด ์ค์๋(precedence)์ ๋ฐ๋ผ ์คํ์ผ์ํธ๊ฐ ๋จผ์ ๋ก๋๋๋๋ก ๋ณด์ฅํ๋ค.
suspense boundary ์์ ์คํ์ผ์ํธ๊ฐ ๋ก๋(์คํ์ผ์ํธ๊ฐ head์ ์ถ๊ฐ๋๊ณ ๋ก๋๋ฅผ ์๋ฃ๋ ๋๊น์ง)๋๋ ๋์ ๋ฆฌ์กํธ๋ suspense fallback์ ๋ณด์ฌ์ค๋ค. css๊ฐ ์์ ํ ๋ก๋๋ ๋๊น์ง ์ด suspense fallback์ ๋ณด์ฌ์ฃผ๊ธฐ ๋๋ฌธ์ ์คํ์ผ์ด ์ ํ์ง์ง ์์ flash๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ค.
12. Preloading API: ์ปดํฌ๋ํธ ๋ด์์ preload, preconnect, preinit, prefetchDNS ๋ฑ ์ฌ์ฉ
browser hint์ ํด๋นํ๋ preload, preconnect, preinit, prefetchDNS ๋ฑ์ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ฌ์ฉํ์ฌ ๋ก๋ฉ ์๋๋ฅผ ํฅ์ํ ์ ์๊ฒ ๋์๋ค.
๋ฆฌ์กํธ๋ ์๋์ ์ผ๋ก ์ค์๋์ ๋ฐ๋ผ ์ด ๋งํฌ๋ค์ ์์๋ฅผ ์ ๋ ฌํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์๊ฐ ๋ก๋ฉ ์์๋ก ์ธํ ์ฑ๋ฅ์ ํ๋ฅผ ๊ฑฑ์ ํ ํ์๊ฐ ์์ด์ง๋ค.
๐ ๋ง์น๋ฉด์
์ค๋์ What's new in React 19์ ์๊ฐ๋ ๋ฆฌ์กํธ 19์ ์๋กญ๊ฑฐ๋ ๊ฐ์ ๋ ๊ธฐ๋ฅ๋ค์ ๋ํด ์ดํด๋ดค๋ค.
1. Asynchoronous transitions: startTransition์ async ํจ์๋ฅผ ์ ๋ฌํ๊ธฐ
2. Actions: transition์ ํธ๋ฆฌ๊ฑฐํ๋ ํจ์๋ค
3. useActionState: ํ ์ ํตํ action ์์ฑ
4. action and formAction props : form, button, input ๋ฑ๊ณผ action ํจ๊ป ์ฐ๊ธฐ
5. useFormStatus : ๋ ์ฝ๊ฒ action์ form status์ ์ ๊ทผํ๊ธฐ
6. React Server Components : ํด๋ผ์ด์ธํธ ํ๊ฒฝ ์ธ์์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๋๋
7. use: promise์ resolved ๊ฐ์ด๋ context์ ๊ฐ ์ฝ๊ธฐ
8. Server Actions: ์๋ฒ์์ run ํ๋ ํจ์ ํด๋ผ์ด์ธํธ์์ call ํ๊ธฐ
> ๋ฆฌ์กํธ 19๋ถํฐ ๊ฐ์ ๋ ์ฌํญ๋ค
9. ref as prop: ํจ์ํ ์ปดํฌ๋ํธ์์ prop์ผ๋ก ref ์ ๊ทผ
10. Document metadata: ์ปดํฌ๋ํธ ๋ด์์ ์ง์ metadata ์ฌ์ฉํ๊ธฐ
11. Stylesheet support: ์ปดํฌ๋ํธ ๋ด์์ ์ง์ stylesheet ์ฌ์ฉํ๊ธฐ
12. Preloading API: ์ปดํฌ๋ํธ ๋ด์์ preload, preconnect, preinit, prefetchDNS ๋ฑ ์ฌ์ฉ
์ ๋ฐ์ ์ผ๋ก '๋ฆฌ์กํธ ์๋ฒ ์ปดํฌ๋ํธ'๊ฐ ๋ถ๋ฌ์จ ๋ณํ๋ค๋ก ์ธํด state๋ค์ ์ด๋ป๊ฒ ์ ๊ทผ/๊ด๋ฆฌํ๊ณ , ์ปดํฌ๋ํธ๋ฅผ ์ธ์ ์ด๋ป๊ฒ ๋๋๋ง ํ ์ง์ ๊ดํ ๊ธฐ๋ฅ๋ค์ ๋ํด ๋ค๋ฃฌ ๊ฒ ๊ฐ๋ค. ์์ง ์๊ฐํ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉ์ ํด๋ณด์ง๋ ๋ชปํ์ง๋ง, transition๊ด๋ จ ํ ๋ค์ด transition ์ํ๋ฅผ ๋ํ๋ด๋๋ฐ ํ ์ ํด์ผ ํ๋ ์ฝ๋๋ค์ ๋ํญ ์ค์ผ ์ ์์ ๊ฑฐ ๊ฐ์์ ํฅ๋ฏธ๋กญ๊ฒ ๋๊ปด์ก๋ค.
๋ค์์๋ ๋ฆฌ์กํธ 19 ๋ฒ์ ์์ ์๋ก ์๊ฐ๋ ๊ธฐ๋ฅ๋ค์ ํ๋ฒ ์จ๋ณด๊ณ ๊ฐ์ ๋ ๊ฐ๋ฐ ๊ฒฝํ์ ์ฒดํํด๋ณด๊ณ ์ถ๋ค.