๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป dev

[โš›๏ธ React Conf 2024] ๋ฆฌ์•กํŠธ 19์—์„œ ์ƒˆ๋กœ์›Œ์ง„ ๊ฒƒ๋“ค (What's new in React 19 | Lydia Hallie)

2024 REACT CONF

What's new in React 19 | Lydia Hallie
์•ฝ 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 ๋“ฑ ์‚ฌ์šฉ

ํ•œ ๋ˆˆ์— ๋ณด๋Š” react 19์—์„œ ์ƒˆ๋กœ์›Œ์ง„ ๊ฒƒ๋“ค

 

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 ๋ฒ„์ „์—์„œ ์ƒˆ๋กœ ์†Œ๊ฐœ๋œ ๊ธฐ๋Šฅ๋“ค์„ ํ•œ๋ฒˆ ์จ๋ณด๊ณ  ๊ฐœ์„ ๋œ ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ์ฒดํ—˜ํ•ด๋ณด๊ณ  ์‹ถ๋‹ค.