https://www.felgus.dev/blog/future-spa



졜근 ν”„λ‘ νŠΈμ—”λ“œ μƒνƒœκ³„μ—μ„œ κ°€μž₯ 뜨거운 주제 쀑 ν•˜λ‚˜λŠ” μ„œλ²„ μ»΄ν¬λ„ŒνŠΈ(Server Components) 와 μ„œλ²„ λ Œλ”λ§μž…λ‹ˆλ‹€. Next.js와 같은 메타 ν”„λ ˆμž„μ›Œν¬κ°€ κ°κ΄‘λ°›μœΌλ©΄μ„œ β€œSPAλŠ” 이제 λ’€μ³μ§€λŠ” 게 μ•„λ‹κΉŒ?β€λΌλŠ” λ…Όμ˜λ„ 자주 λ“±μž₯ν•˜μ£ .


ν•˜μ§€λ§Œ λ‹¨μˆœν•œ SPA(Single Page Application), 즉 정적 HTMLκ³Ό JS 파일 ν•˜λ‚˜λ‘œ μ‹œμž‘ν•˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜λ„ μ—¬μ „νžˆ κ°•λ ₯ν•œ 경쟁λ ₯을 κ°€μ§‘λ‹ˆλ‹€. 였히렀 μƒˆλ‘œμš΄ React κΈ°λŠ₯듀을 적절히 ν™œμš©ν•˜λ©΄ κΈ°μ‘΄ SPA의 ν•œκ³„λ₯Ό κ·Ήλ³΅ν•˜κ³  훨씬 λ§€λ„λŸ¬μš΄ μ‚¬μš©μž κ²½ν—˜(UX)을 μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이 κΈ€μ—μ„œλŠ” SPAμ—μ„œ μ μš©ν•  수 μžˆλŠ” μ΅œμ‹  μ „λž΅λ“€μ„ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

1. Render-on-Fetchμ—μ„œ Render-as-You-Fetch둜


전톡적인 SPAλŠ” 보톡 λ‹€μŒ λ‹¨κ³„λ‘œ λ™μž‘ν•©λ‹ˆλ‹€:

1. HTML μš”μ²­
2. JS λ‹€μš΄λ‘œλ“œ ν›„ React μ΄ˆκΈ°ν™”
3. μ»΄ν¬λ„ŒνŠΈ λ Œλ”λ§ μ‹œμž‘
4. μ»΄ν¬λ„ŒνŠΈ μ•ˆμ—μ„œ fetch 호좜
5. Suspense fallback UI ν‘œμ‹œ
6. 응닡 도착 ν›„ μ‹€μ œ UI λ Œλ”λ§

이 방식은 λ‹¨μˆœν•˜μ§€λ§Œ λ„€νŠΈμ›Œν¬ μ›Œν„°ν΄μ΄ 생기며 UI ν‘œμ‹œκ°€ μ§€μ—°λ©λ‹ˆλ‹€.

반면 Render-as-You-Fetch νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ μ»΄ν¬λ„ŒνŠΈ λ Œλ”λ§ 직전에 라우트 λ‘œλ”(Route Loader) λ₯Ό μ‹€ν–‰ν•˜μ—¬ 데이터λ₯Ό 더 빨리 μš”μ²­ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


즉, ν•„μš”ν•œ 데이터λ₯Ό κ°€μ Έμ˜€λŠ” κ³Όμ •κ³Ό UI λ Œλ”λ§μ„ 맞물렀 λ™μ‹œμ— μ§„ν–‰ν•˜λ―€λ‘œ 초기 λ°˜μ‘ 속도가 κ°œμ„ λ©λ‹ˆλ‹€.

β†’ React Router v7, Tanstack Router 같은 μ΅œμ‹  λΌμš°ν„°κ°€ 이 νŒ¨ν„΄μ„ μ§€μ›ν•©λ‹ˆλ‹€.

2. μ„œλ²„ μ»΄ν¬λ„ŒνŠΈμ˜ 정적 ν™œμš©

μ„œλ²„ μ»΄ν¬λ„ŒνŠΈλŠ” 이름 κ·ΈλŒ€λ‘œ μ„œλ²„μ—μ„œ λ Œλ”λ§ν•΄μ•Ό ν•  κ²ƒμ²˜λŸΌ λ“€λ¦¬μ§€λ§Œ, κΌ­ κ·Έλ ‡μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€.

λΉŒλ“œ λ‹¨κ³„μ—μ„œ 미리 μƒμ„±ν•œ 정적 Server Component Payloadλ₯Ό ν™œμš©ν•΄ SPA μ•ˆμ— ν¬ν•¨μ‹œν‚¬ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
예λ₯Ό λ“€μ–΄, μ„Έμ…˜ μƒνƒœλ‚˜ μ‚¬μš©μž μž…λ ₯κ³Ό λ¬΄κ΄€ν•œ μ»΄ν¬λ„ŒνŠΈλŠ” λΉŒλ“œ μ‹œμ μ— 미리 λ§Œλ“€μ–΄ 두고, SPA μ‹€ν–‰ μ‹œ ν•„μš”ν•œ μˆœκ°„ λΆˆλŸ¬μ˜€λŠ” λ°©μ‹μž…λ‹ˆλ‹€.
β†’ μ΄λ ‡κ²Œ ν•˜λ©΄ μ„œλ²„ ν™˜κ²½μ΄ 없어도 SPA μ„±λŠ₯κ³Ό 초기 λ‘œλ”© κ²½ν—˜μ„ κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

3. Concurrent Features: 더 λ§€λ„λŸ¬μš΄ μΈν„°λž™μ…˜


React 18μ—μ„œ λ„μž…λœ useTransition, useDeferredValue 같은 λ™μ‹œμ„± κΈ°λŠ₯은 λ‹¨μˆœνžˆ β€œλŒ€ν˜• μ„œλΉ„μŠ€ μ „μš©β€μ΄ μ•„λ‹™λ‹ˆλ‹€.
ν”„λ‘ νŠΈμ—”λ“œμ—μ„œμ˜ 규λͺ¨(scale) λŠ” μ‚¬μš©μž μˆ˜κ°€ μ•„λ‹ˆλΌ β€œνŽ˜μ΄μ§€, μƒν˜Έμž‘μš©, 정보 νλ¦„μ˜ λ³΅μž‘λ„β€λ‘œ μ •μ˜λ©λ‹ˆλ‹€.
SPAμ—μ„œλ„ μ‚¬μš©μžλŠ” 아무 λ•Œλ‚˜ λ‹€μ–‘ν•œ μΈν„°λž™μ…˜μ„ μˆ˜ν–‰ν•  수 있기 λ•Œλ¬Έμ—, μ—…λ°μ΄νŠΈμ˜ μš°μ„ μˆœμœ„λ₯Ό λͺ…ν™•νžˆ μ§€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ UXκ°€ μ‰½κ²Œ 끊기게 λ©λ‹ˆλ‹€.

λ™μ‹œμ„± κΈ°λŠ₯을 ν™œμš©ν•˜λ©΄ Reactκ°€ 높은 μš°μ„ μˆœμœ„ μž‘μ—…λΆ€ν„° μ²˜λ¦¬ν•˜λ„λ‘ μ§€μ‹œν•  수 있고, κ·Έ κ²°κ³Ό 더 λΆ€λ“œλŸ¬μš΄ ν™”λ©΄ μ „ν™˜κ³Ό λ°˜μ‘μ„±μ„ 확보할 수 μžˆμŠ΅λ‹ˆλ‹€.

4. Preloadλ₯Ό ν†΅ν•œ μ„ μ œμ  μ‚¬μš©μž κ²½ν—˜

μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…κ³Ό μ§€μ—° λ‘œλ”©μ€ 이미 ν”ν•œ κΈ°λ²•μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ—¬κΈ°μ„œ 더 λ‚˜μ•„κ°€ SPA λΌμš°ν„°μ˜ Link μ»΄ν¬λ„ŒνŠΈλ₯Ό ν™œμš©ν•˜λ©΄ μ„±λŠ₯을 또 ν•œ 단계 κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, μ‚¬μš©μžκ°€ νŠΉμ • 링크 μœ„μ— 마우슀λ₯Ό μ˜¬λ €λ†“μ€ μˆœκ°„, λΌμš°ν„°κ°€ ν•΄λ‹Ή νŽ˜μ΄μ§€μ˜ 데이터와 μ½”λ“œ μŠ€ν”Œλ¦Ώλœ JSλ₯Ό 미리 μš”μ²­ν•˜λ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

μ΄λ ‡κ²Œ ν•˜λ©΄ μ‹€μ œ νŽ˜μ΄μ§€ μ „ν™˜ μ‹œ 이미 μ€€λΉ„λœ μ½˜ν…μΈ κ°€ μ¦‰μ‹œ ν‘œμ‹œλ˜μ–΄, 마치 λ„€μ΄ν‹°λΈŒ μ•±μ²˜λŸΌ λ°˜μ‘ν•˜λŠ” UXλ₯Ό μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

5. React Labs의 μ‹ κΈ°λŠ₯: ViewTransition & Activity

React νŒ€μ΄ λ°œν‘œν•œ μ‹€ν—˜μ  κΈ°λŠ₯ 쀑 두 κ°€μ§€κ°€ SPA UX에 특히 μ£Όλͺ©ν•  λ§Œν•©λ‹ˆλ‹€:
β€’ ViewTransitionβ€¨μƒˆλ‘œμš΄ μ›Ή ν‘œμ€€μœΌλ‘œ, νŽ˜μ΄μ§€ μ „ν™˜ μ‹œ μ• λ‹ˆλ©”μ΄μ…˜μ„ 더 λΆ€λ“œλŸ½κ²Œ μ μš©ν•  수 μžˆλ„λ‘ React와 λΈŒλΌμš°μ € API κ°„μ˜ 간극을 λ©”μ›Œμ€λ‹ˆλ‹€.
→ 결과적으둜 ν™”λ©΄ μ „ν™˜ κ²½ν—˜μ΄ 훨씬 μžμ—°μŠ€λŸ¬μ›Œμ§‘λ‹ˆλ‹€.
β€’ Activity (ꡬ Offscreen)β€¨λ Œλ”λ§κ³Ό 컀밋 κ³Όμ • 사이에 β€œλ―Έλ¦¬ UI μŠ€λƒ…μƒ·μ„ μ€€λΉ„ν•΄λ‘λŠ”β€ κΈ°λŠ₯μž…λ‹ˆλ‹€.

즉, μ»΄ν¬λ„ŒνŠΈλ₯Ό 보이지 μ•ŠλŠ” μƒνƒœλ‘œ λ Œλ”λ§ν•΄λ‘” λ’€, ν•„μš”ν•  λ•Œ μ¦‰μ‹œ 화면에 μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
→ μ „ν™˜ μ‹œμ μ—μ„œ κΈ°λ‹€λ¦Ό 없이 κ³§λ°”λ‘œ μƒˆλ‘œμš΄ 화면을 보여쀄 수 μžˆμŠ΅λ‹ˆλ‹€.

이 κΈ°λŠ₯을 Preload μ „λž΅κ³Ό ν•¨κ»˜ μ‚¬μš©ν•˜λ©΄, νŽ˜μ΄μ§€ μ „ν™˜ 속도 및 연속성이 λŒ€ν­ κ°œμ„ λ©λ‹ˆλ‹€.

κ²°λ‘ : SPAλŠ” 더 λΆ€λ“œλŸ½κ²Œ, 더 λΉ λ₯΄κ²Œ
SPAκ°€ μ„œλ²„ λ Œλ”λ§ ν”„λ ˆμž„μ›Œν¬μ— λ°€λ € μ‚¬λΌμ§ˆ 거라고 μƒκ°ν•˜κΈ° μ‰½μ§€λ§Œ, 였히렀 λ°˜λŒ€μž…λ‹ˆλ‹€.
β€’ Render-as-you-fetch νŒ¨ν„΄
β€’ Server Component의 정적 ν™œμš©
β€’ Concurrent Features둜 λΆ€λ“œλŸ¬μš΄ μΈν„°λž™μ…˜
β€’ Preload & Activity & ViewTransition으둜 λ„€μ΄ν‹°λΈŒ 같은 μ „ν™˜ κ²½ν—˜

이 μ „λž΅λ“€μ„ κ²°ν•©ν•˜λ©΄ SPAλŠ” μ§€κΈˆλ³΄λ‹€ 훨씬 κ°•λ ₯ν•˜κ³  μ„Έλ ¨λœ UXλ₯Ό μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ 즉, SPA의 λ―Έλž˜λŠ” μ„±λŠ₯κ³Ό UXλ₯Ό λͺ¨λ‘ κ°–μΆ˜ β€œλ” λ˜‘λ˜‘ν•œ ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œ λ Œλ”λ§β€μž…λ‹ˆλ‹€.

+ Recent posts