λͺ©μ°¨
[React] SPA νμ΄μ§ μ΄λ μ μ€ν¬λ‘€ 맨 μ μ μ§ νλ λ°©λ²
μ΅κ·Ό μΉ κ°λ° νΈλ λμμ μ±κΈ νμ΄μ§ μ ν리μΌμ΄μ (SPA)μ μ¬μ©μ κ²½ν(UX)μ κ·ΉλννκΈ° μν΄ λ§μ΄ νμ©λκ³ μμ΅λλ€. νΉν Reactμ κ°μ νλ‘ νΈμλ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ SPAλ₯Ό ꡬμΆν λ, νμ΄μ§ κ° μ νμ΄ λΉ λ₯΄κ³ λΆλλ¬μ΄ μ ν ν¨κ³Όλ₯Ό μ 곡ν μ μλ€λ μ μ΄ ν° μ₯μ μ λλ€. κ·Έλ¬λ μ΄λ¬ν SPAμ νΉμ±μ νμ΄μ§ μ΄λ μ μ€ν¬λ‘€ μμΉκ° μ΄μ νμ΄μ§μ μμΉλ₯Ό κ·Έλλ‘ μ μ§νλ λ¬Έμ κ° λ°μν μ μμ΅λλ€. λ³Έ ν¬μ€ν μμλ React νκ²½μμ SPA νμ΄μ§ μ΄λ μ μ€ν¬λ‘€μ νμ 맨 μλ‘ μ μ§νλ λ€μν λ°©λ²κ³Ό κ·Έ ꡬν μ¬λ‘μ λν΄ μ¬λ μκ² λ€λ£¨μ΄ λ³΄κ² μ΅λλ€.
SPAμ μ€ν¬λ‘€ λ¬Έμ μ μ΄ν΄
SPAλ ν λ²μ λ‘λ©μΌλ‘ μ ν리μΌμ΄μ μ 체λ₯Ό λΆλ¬μ¨ ν, λ΄λΆμμ λΌμ°ν μ ν΅ν΄ μ¬μ©μκ° νμλ‘ νλ μ½ν μΈ λ§ λμ μΌλ‘ λ³κ²½νμ¬ λ³΄μ¬μ£Όλ ꡬ쑰μ λλ€. μ΄μ κ°μ ꡬ쑰 λλΆμ μλ²μμ λΆνμν ν΅μ μ μ€μΌ μ μμ§λ§, μ ν΅μ μΈ λ©ν° νμ΄μ§ μ ν리μΌμ΄μ (MPA)κ³Ό λ¬λ¦¬ νμ΄μ§κ° μ νλ λ λΈλΌμ°μ κ° μ€ν¬λ‘€ μμΉλ₯Ό μλμΌλ‘ μ΄κΈ°νν΄μ£Όμ§ μμ΅λλ€. μ΄λ‘ μΈν΄ μ¬μ©μλ μλ‘μ΄ μ½ν μΈ λ₯Ό νμΈν λλ μ΄μ νμ΄μ§μ μ€ν¬λ‘€ μμΉμ λ¨Έλ¬Όκ² λμ΄, κ°λ μ±κ³Ό UX μΈ‘λ©΄μμ λΆνΈν¨μ κ²ͺμ μ μμ΅λλ€.
μλ₯Ό λ€μ΄, μ¬μ©μκ° κΈ΄ μ€ν¬λ‘€μ΄ νμν νμ΄μ§μμ νλ¨κΉμ§ μ€ν¬λ‘€ν ν λ€λ₯Έ νμ΄μ§λ‘ μ΄λνλ©΄, μλ‘ λ‘λλ νμ΄μ§μμλ μ€ν¬λ‘€ μμΉκ° νλ¨μ 머무λ₯΄κ² λ©λλ€. μ΄λ μ¬μ©μκ° νμ΄μ§μ μμ λΆλΆλΆν° μ½ν μΈ λ₯Ό νμΈν΄μΌ νλ μν©μμλ λ§€μ° νΌλμ€λ¬μ΄ κ²½νμ΄ λ μ μμ΅λλ€.
μ€ν¬λ‘€ μ΄κΈ°νμ νμμ±κ³Ό ν΄κ²° λ°©λ²
μΉ κ°λ°μμλ μ¬μ©μ νΈμμ±μ λμ΄κΈ° μν΄ νμ΄μ§ μ ν μ μ€ν¬λ‘€ μμΉλ₯Ό μλμΌλ‘ μ΅μλ¨μΌλ‘ μ΄λμν€λ κ²μ΄ μΌλ°μ μΈ UX ν¨ν΄μ λλ€. Reactλ₯Ό λΉλ‘―ν SPA νλ μμν¬μμλ μ΄μ κ°μ κΈ°λ₯μ΄ νμνλ©°, λ€μν λ°©λ²μΌλ‘ μ΄λ₯Ό ꡬνν μ μμ΅λλ€. λνμ μΈ ν΄κ²° λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
- window.scrollTo() λ©μλ μ¬μ©
νμ΄μ§ μ΄λμ΄ λ°μν λλ§λ€ window.scrollTo(0, 0)μ νΈμΆνμ¬ μ€ν¬λ‘€ μμΉλ₯Ό μ΄κΈ°ννλ λ°©λ²μ λλ€. μ΄ λ°©λ²μ κ°λ¨νλ©΄μλ ν¨κ³Όμ μ΄μ§λ§, μ¬λ¬ μ»΄ν¬λνΈμμ λ°λ³΅μ μΌλ‘ νΈμΆν΄μΌ νκ±°λ λΌμ°ν λ³νμ λν μ΄λ²€νΈ μ²λ¦¬κ° 볡μ‘ν΄μ§ μ μλ€λ λ¨μ μ΄ μμ΅λλ€. - React Routerμ Scroll Restoration κΈ°λ₯ νμ©
μ΅μ λ²μ μ React Routerλ κΈ°λ³Έμ μΌλ‘ μ€ν¬λ‘€ μμΉ κ΄λ¦¬ κΈ°λ₯μ μ 곡νκΈ°λ ν©λλ€. νμ§λ§ λͺ¨λ νλ‘μ νΈμμ μ΄ κΈ°λ₯μ μ¬μ©ν μ μλ κ²μ μλλ©°, 컀μ€ν°λ§μ΄μ§μ΄ νμν κ²½μ° μ§μ ꡬννλ κ²μ΄ μ 리ν μ μμ΅λλ€. - ScrollToTop μ»΄ν¬λνΈ μ μ
컀μ€ν μ»΄ν¬λνΈλ₯Ό λ§λ€μ΄ λΌμ°νΈκ° λ³κ²½λ λλ§λ€ μλμΌλ‘ μ€ν¬λ‘€μ μ΄κΈ°ννλ λ°©λ²μ λλ€. μ΄ λ°©μμ μ½λμ μ¬μ¬μ©μ±κ³Ό μ μ§λ³΄μ μΈ‘λ©΄μμ λ§€μ° ν¨μ¨μ μ λλ€. λ³΄ν΅ useEffect ν μ νμ©νμ¬ λΌμ°νΈ λ³κ²½ μμ μ window.scrollTo(0, 0)μ νΈμΆνλ ννλ‘ κ΅¬νν©λλ€.
μλμμλ κ°μ₯ λ§μ΄ μ¬μ©λλ ScrollToTop μ»΄ν¬λνΈ κ΅¬ν μμ λ₯Ό ν΅ν΄ ꡬ체μ μΈ λ°©λ²μ μ΄ν΄λ³΄κ² μ΅λλ€.
Reactμμ ScrollToTop μ»΄ν¬λνΈ κ΅¬ν μμ
λ€μμ React Routerλ₯Ό μ¬μ©νλ νλ‘μ νΈμμ ScrollToTop μ»΄ν¬λνΈλ₯Ό ꡬννλ λ°©λ²μ λλ€. μ΄ μ»΄ν¬λνΈλ λΌμ°νΈκ° λ³κ²½λ λλ§λ€ μ€ν¬λ‘€μ μ΅μλ¨μΌλ‘ μ΄λμμΌ μ¬μ©μμκ² νμ μλ‘μ΄ νμ΄μ§μ μμ λΆλΆμ 보μ¬μ€ μ μλλ‘ λμμ€λλ€.
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
const ScrollToTop = () => {
const { pathname } = useLocation();
useEffect(() => {
// νμ΄μ§κ° λ³κ²½λ λλ§λ€ μ€ν¬λ‘€μ 맨 μλ‘ μ΄λ
window.scrollTo({
top: 0,
behavior: 'smooth' // λΆλλ¬μ΄ μ€ν¬λ‘€ ν¨κ³Ό (μνλ κ²½μ° 'auto'λ‘ λ³κ²½ κ°λ₯)
});
}, [pathname]);
return null;
};
export default ScrollToTop;
μ μ½λμμ useLocation ν μ μ¬μ©νμ¬ νμ¬ λΌμ°νΈ κ²½λ‘λ₯Ό λ°μμ€λ©°, κ²½λ‘κ° λ³κ²½λ λλ§λ€ useEffect λ΄μ μ½λ°± ν¨μκ° μ€νλ©λλ€. μ΄λ window.scrollToλ₯Ό νΈμΆνμ¬ μ€ν¬λ‘€ μμΉλ₯Ό 맨 μλ‘ μ΄λμν΅λλ€. behavior μ΅μ μ 'smooth'λ‘ μ€μ νλ©΄ λΆλλ¬μ΄ μ€ν¬λ‘€ μ λλ©μ΄μ ν¨κ³Όλ₯Ό μ€ μ μμ΄ μ¬μ©μ κ²½νμ΄ νμΈ΅ ν₯μλ©λλ€.
μ΄ μ»΄ν¬λνΈλ₯Ό μ ν리μΌμ΄μ μ λ£¨νΈ μ»΄ν¬λνΈλ λΌμ°ν°λ₯Ό κ°μΈλ μμμ μ½μ νλ©΄, λΌμ°νΈ λ³κ²½ μ μλμΌλ‘ μ€ν¬λ‘€ μμΉκ° μ΄κΈ°νλλ ν¨κ³Όλ₯Ό λ릴 μ μμ΅λλ€. μλ₯Ό λ€μ΄, App.js νμΌμμ λ€μκ³Ό κ°μ΄ μ μ©ν μ μμ΅λλ€.
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import ScrollToTop from './ScrollToTop';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import ContactPage from './pages/ContactPage';
const App = () => {
return (
<Router>
<ScrollToTop />
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
</Routes>
</Router>
);
};
export default App;
μ΄μ κ°μ΄ ꡬμ±νλ©΄ μ¬μ©μκ° νμ΄μ§λ₯Ό μ νν λλ§λ€ μ€ν¬λ‘€μ΄ μλμΌλ‘ μ΅μλ¨μΌλ‘ μ΄λνμ¬, κ° νμ΄μ§μ μμ λΆλΆλΆν° μ½ν μΈ λ₯Ό νμΈν μ μμ΅λλ€.
λ€μν μν©μ λ§μΆ μ€ν¬λ‘€ κ΄λ¦¬ μ λ΅
μ€μ νλ‘μ νΈμμλ λ¨μν νμ΄μ§ μ΄λ μ μ€ν¬λ‘€μ μ΅μλ¨μΌλ‘ μ΄κΈ°ννλ κ² μΈμλ μ¬λ¬ μν©μ κ³ λ €ν΄μΌ ν λκ° μμ΅λλ€. μλ₯Ό λ€μ΄, λ€μκ³Ό κ°μ μν©λ€μ΄ μμ μ μμ΅λλ€.
- λͺ¨λ¬ μ°½ λλ νμ
μ€ν μ
νμ΄μ§ μ μ²΄κ° μλ νΉμ μμλ§ μ λ°μ΄νΈλλ κ²½μ°, μ 체 νμ΄μ§μ μ€ν¬λ‘€ μμΉλ₯Ό λ³κ²½νλ©΄ μ€νλ € μ¬μ©μμ νΌλμ μ΄λν μ μμ΅λλ€. μ΄λλ λͺ¨λ¬ λ΄λΆμ λ³λμ μ€ν¬λ‘€ 컨ν μ΄λλ₯Ό λκ³ κ΄λ¦¬νλ λ°©λ²μ΄ νμν©λλ€. - νΉμ νμ΄μ§μμλ μ΄μ μ€ν¬λ‘€ μμΉ μ μ§
μλ₯Ό λ€μ΄, 리μ€νΈ νμ΄μ§μμ μμΈ νμ΄μ§λ‘ μ΄λν ν λ€μ 리μ€νΈλ‘ λμμ¬ λ μ΄μ μ€ν¬λ‘€ μμΉλ₯Ό μ μ§νκ³ μΆμ κ²½μ°κ° μμ΅λλ€. μ΄λ¬ν κ²½μ°μλ μ€ν¬λ‘€ μμΉλ₯Ό μν(state)λ λ‘컬 μ€ν 리μ§μ μ μ₯ν ν, λ³΅κ· μ ν΄λΉ μμΉλ‘ μ€ν¬λ‘€μ μ΄λμν€λ λ‘μ§μ μΆκ°ν μ μμ΅λλ€. - λΌμ°νΈ λ³κ²½μ λ°λ₯Έ μ λλ©μ΄μ
ν¨κ³Ό μ μ©
νμ΄μ§ μ΄λ μ λ¨μν μ€ν¬λ‘€μ μ΄κΈ°ννλ κ² μΈμλ, μ ν μ λλ©μ΄μ μ ν¨κ» μ μ©νμ¬ λ³΄λ€ λΆλλ¬μ΄ UXλ₯Ό μ 곡ν μ μμ΅λλ€. μ΄λ μ λλ©μ΄μ κ³Ό μ€ν¬λ‘€ μ΄κΈ°ν νμ΄λ°μ μ‘°μ¨ν΄μΌ νλ―λ‘, μΆκ°μ μΈ λ‘μ§κ³Ό λΌμ΄λΈλ¬λ¦¬ νμ©μ΄ νμν μ μμ΅λλ€.
μ΄μ κ°μ΄ λ€μν μ¬μ©μ μλ리μ€λ₯Ό κ³ λ €νμ¬ μ€ν¬λ‘€ κ΄λ¦¬ λ‘μ§μ 컀μ€ν°λ§μ΄μ§νλ©΄, λμ± ν₯μλ μ¬μ©μ κ²½νμ μ 곡ν μ μμ΅λλ€.
μ€λ¬΄μμμ μ μ©κ³Ό μ£Όμμ¬ν
μ€λ¬΄ νκ²½μμλ νλ‘μ νΈμ κ·λͺ¨μ 볡μ‘λμ λ°λΌ μ€ν¬λ‘€ μ΄κΈ°ν κΈ°λ₯μ λ¨μν νλμ μ»΄ν¬λνΈλ‘ ν΄κ²°νκΈ° μ΄λ €μ΄ κ²½μ°λ λ§μ΅λλ€. λ€μκ³Ό κ°μ μ¬νλ€μ κ³ λ €ν΄λ³΄μκΈ° λ°λλλ€.
- λΌμ°ν° λ²μ λ° λΌμ΄λΈλ¬λ¦¬ νΈνμ±
React Routerμ λ²μ μ΄ μ λ°μ΄νΈλλ©΄μ κΈ°λ³Έ μ 곡λλ μ€ν¬λ‘€ 볡μ κΈ°λ₯μ΄ λ¬λΌμ§ μ μμ΅λλ€. νλ‘μ νΈμ μ μ©νκΈ° μ μ νμ¬ μ¬μ© μ€μΈ λΌμ°ν° λΌμ΄λΈλ¬λ¦¬μ λ¬Έμλ₯Ό κΌΌκΌΌνκ² νμΈνλ κ²μ΄ μ’μ΅λλ€. - μ±λ₯ μ΅μ ν
μ€ν¬λ‘€ μ΄κΈ°ν λ‘μ§μ΄ νμ΄μ§ μ ν μλ§λ€ μ€νλλ―λ‘, λΆνμν λ λλ§μ΄λ κ³Όλν μ λλ©μ΄μ ν¨κ³Όλ‘ μΈν΄ μ±λ₯ μ νκ° λ°μν μ μμ΅λλ€. νΉν λͺ¨λ°μΌ νκ²½μμλ μ±λ₯μ λ―Όκ°νλ―λ‘, λΆλλ¬μ΄ μ€ν¬λ‘€ μ λλ©μ΄μ ν¨κ³Όμ μ±λ₯ κ°μ κ· νμ λ§μΆλ κ²μ΄ μ€μν©λλ€. - μ¬μ©μ κ²½ν(UX) κ³ λ €
λͺ¨λ νμ΄μ§μμ 무쑰건 μ€ν¬λ‘€μ μ΅μλ¨μΌλ‘ μ΄λμν€λ κ²μ΄ νμ μ΅μ μ μ νμ μλλλ€. μ¬μ©μκ° νΉμ 컨ν μΈ λ₯Ό μ½λ€κ° λ€λ₯Έ νμ΄μ§λ‘ μ΄λν ν λ€μ λμμ¬ λ μ΄μ μμΉλ₯Ό κΈ°μ΅νλ κ²μ΄ λ λμ κ²½νμ μ 곡ν μλ μμ΅λλ€. λ°λΌμ κ° νμ΄μ§μ νΉμ±κ³Ό μ¬μ©μμ νλ ν¨ν΄μ λ§κ² μ€ν¬λ‘€ μ΄κΈ°ν μ μ± μ μ μ°νκ² μ μ©νλ κ²μ΄ μ’μ΅λλ€. - μλ¬ νΈλ€λ§
λ§μ½ λΌμ°νΈ λ³κ²½ λμ€ μλ¬κ° λ°μνκ±°λ μ€ν¬λ‘€ μ΄κΈ°ν λ‘μ§μ΄ μμλλ‘ μλνμ§ μλ κ²½μ°, μ¬μ©μμκ² νΌλμ μ€ μ μμ΅λλ€. μ΄λ¬ν μν©μ λλΉνμ¬ μ μ ν μλ¬ νΈλ€λ§ λ‘μ§μ μΆκ°νλ κ²μ΄ μ€μν©λλ€.
κ²°λ‘
SPA νκ²½μμ Reactλ₯Ό μ¬μ©νμ¬ νμ΄μ§λ₯Ό ꡬνν λ, μ€ν¬λ‘€ μ΄κΈ°ν κΈ°λ₯μ μ¬μ©μ κ²½νμ ν₯μμν€κΈ° μν νμ μμ μ€ νλμ λλ€. λ³Έ ν¬μ€ν μμλ React Routerλ₯Ό νμ©ν ScrollToTop μ»΄ν¬λνΈ κ΅¬ν λ°©λ²μ λΉλ‘―νμ¬, λ€μν μν©μμ μ€ν¬λ‘€μ κ΄λ¦¬νλ μ λ΅μ λν΄ μ΄ν΄λ³΄μμ΅λλ€. κ°λ¨ν window.scrollTo λ©μλ νΈμΆμμλΆν° 컀μ€ν μ»΄ν¬λνΈλ₯Ό ν΅ν μ μ κ΄λ¦¬κΉμ§, μν©μ λ§λ μ΅μ μ λ°©λ²μ μ ννμ¬ μ μ©νλ κ²μ΄ μ€μν©λλ€.
μ€λ¬΄μμλ λΌμ°ν° λ²μ , μ±λ₯ μ΅μ ν, μ¬μ©μ κ²½ν λ±μ μ’ ν©μ μΌλ‘ κ³ λ €νμ¬ μ€ν¬λ‘€ μ΄κΈ°ν λ‘μ§μ μ€κ³ν΄μΌ ν©λλ€. λν, λ¨μν μ€ν¬λ‘€μ μ΄κΈ°ννλ κ²λΏλ§ μλλΌ, λͺ¨λ¬ μ°½μ΄λ νΉμ νμ΄μ§μ μ€ν¬λ‘€ μνλ₯Ό κ΄λ¦¬νλ λ±μ μΆκ°μ μΈ UX κ°μ μμλ₯Ό ν¨κ» κ³ λ €νλ κ²μ΄ λ°λμ§ν©λλ€. μ΄λ² ν¬μ€ν μ ν΅ν΄ SPA κ°λ° νκ²½μμ μ€ν¬λ‘€ κ΄λ¦¬μ μ€μμ±κ³Ό ꡬν λ°©λ²μ μΆ©λΆν μ΄ν΄νμμ΄, λ³΄λ€ μμ±λ λμ μΉ μ ν리μΌμ΄μ μ ꡬμΆνμκΈΈ λ°λλλ€.
React κΈ°λ°μ SPA νλ‘μ νΈμμ νμ΄μ§ μ΄λ μ μ€ν¬λ‘€μ νμ μ΅μλ¨μΌλ‘ μ μ§ν¨μΌλ‘μ¨ μ¬μ©μμκ² μ§κ΄μ μ΄κ³ κΉλν νλ©΄ μ νμ μ 곡ν μ μμΌλ©°, μ΄λ κ²°κ³Όμ μΌλ‘ μΉμ¬μ΄νΈμ μ λ°μ μΈ νμ§κ³Ό μ¬μ©μμ λ§μ‘±λλ₯Ό λμ΄λ λ° ν¬κ² κΈ°μ¬ν κ²μ λλ€.
λκΈ