

특징
- 클라이언트 중심
- 페이지 로딩과 UI 업데이트는 주로 클라이언트(브라우저)에서 이루어짐
- 필요 데이터만 비동기로 가져와 UI를 업데이트하므로 전체 페이지를 재로드 할 필요 없음
- Javascript 프레임워크 사용
- SPA는 React, Angular, Vue.js와 같은 프레임워크/라이브러리를 사용하여 구축됨
- SPA에서는 URL에 따라 콘텐츠를 변경하기 위해 클라이언트 측 라우팅이 필요함
- SSR : 서버 사이드 렌더링
- 사용자의 요청이 들어올 때마다 서버에서 HTML을 동적으로 생성하여 보내주는 방식
- SSG : 정적 사이트 생성
- 웹사이트를 빌드(배포)할 때 모든 페이지의 HTML을 미리 만들어 두는 방식
- ISR : 점진적 정적 재생성
- SSG의 단점을 보완한 방식으로, 정적 페이지를 미리 만들어두되, 설정한 주기마다 서버가 자동으로 새로운 데이터를 반영해 페이지를 다시 생성
- RSC : 리액트 서버 컴포넌트
- 리액트 컴포넌트 중 일부를 서버에서만 실행하고, 클라이언트에는 결과만 전달하는 방식

라이브러리 설치
npm install react-router-dom
라이브러리 업데이트
npm install react-scripts@5



import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function Home() {
return (
Home Page
);
}
function About() {
return (
About Page
);
}
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}

import { BrowserRouter, Routes, Route, Link, useParams } from "react-router-dom";
function Product() {
const { id } = useParams(); // id 파라미터 읽기
return (
Product ID: {id}
);
}
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/product/:id" element={<Product />} />
</Routes>
</BrowserRouter>
);
}
/product/:id → :id는 동적 파라미터
파라미터 가져오기 : useParams 훅 함수 사용
import { BrowserRouter, Routes, Route, Link, useParams } from "react-router-dom";
function Product() {
const { category, id } = useParams(); // category, id 파라미터 읽기
return (
Product ID: {id}
);
}
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/:category/:id" element={<Product />} />
</Routes>
</BrowserRouter>
);
}
/product/:category/:id → :category, :id는 동적 파라미터
category와 id 값을 기반으로, 해당 상품의 상세 페이지를 출력하는 페이지

App.js
// import logo from './logo.svg';
import './App.css';
import { BrowserRouter, Routes, Route, Link, useParams } from 'react-router-dom'; // Route, Link, useParams도 추가하기 (12주차)
import ProductDetail from './components/ProductDetail';
import MyComponent from './components/MyComponent';
import Detail from './components/Detail';
import Dashboard from './components/Dashboard';
function Home() { // 12주차 추가
return <h1>Home Page</h1>
}
function About() { // 12주차 추가
return <h1>About Page</h1>
}
function Product() {
const {category, id} = useParams();
return <h1>Product({category}) ID : {id}</h1>
}
function App() {
return (
<BrowserRouter>
<nav>
<Link to='/'>Home</Link>
<br />
<Link to='/about'>About</Link>
<br />
<Link to='/product'>Product</Link>
<br />
<Link to='/detail'>Detail</Link>
<br />
</nav>
<Routes>
<Route path="/mycomponent" element={<MyComponent />} />
<Route path="/detail" element={<Detail />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/Home" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/product/:category/:id" element={<ProductDetail />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Login.jsx
import { useNavigate } from 'react-router-dom';
export default function Login() {
const navigate = useNavigate();
const handleLogin = () => { // 로그인 성공 시
navigate('/dashboard');
};
return (
<button onClick={handleLogin}>로그인</button>
);
}
Dashboard.jsx (로그아웃)
import { replace, useNavigate } from "react-router-dom";
export default function Dashboard() {
const navigate = useNavigate();
const handleLogout = () => { // 로그아웃
navigate('/home');
};
return (
<button onClick={handleLogout}>로그아웃</button>
);
}
MyComponent.jsx
import {useNavigate} from 'react-router-dom';
function MyComponent() {
const navigate = useNavigate();
const handleClick = () => {
navigate('/detail', { state : {from:'search', itemId: 5}});
// navigate('/home');
};
return (
<button onClick={handleClick}>홈으로 이동</button>
);
}
export default MyComponent;
Detail.jsx
import { useLocation } from "react-router-dom";
export default function Detail() {
const location = useLocation();
return (
<div>
<h1>Home</h1>
{console.log(location.state)}
</div>
);
}
ProductDetail.jsx
import {useParams} from 'react-router-dom';
import Login from './Login';
const productData = {
'books' : {
'101' : {
name: '리액트 입문',
price: 18000,
},
'102' : {
name: '자바스크립트 입문',
price: 22000,
}
},
'electronics' : {
'201': {
name: '마우스',
price: 25000,
},
'202': {
name: '키보드',
price: 55000
}
}
};
function ProductDetail() {
const {category, id} = useParams();
const categoryData = productData[category]; // 추가
const product = categoryData ? categoryData[id] : null; // 추가
return ( // {product.name} 와 {product.id} 추가
<div>
<Login />
<br />
<h2>상품 상세 정보</h2>
<p>카테고리: {category}</p>
<p>상품 ID: {id}</p>
{ product ? (
<div>
<p>상품명 : {product.name}</p>
<p>가격 : {product.price}</p>
</div>
)
: ( <p style={{ color:'red'}}>해당 상품이 존재하지 않습니다</p>
)
}
</div>
);
}
export default ProductDetail;