싱글 페이지 어플리케이션
전통적인 웹 페이지
일반 웹 사이트의 동작 과정
웹 사이트의 화면 일부를 수정하기 위해 노력한 과정
• 초기 웹 사이트
각 화면에 해당하는 웹 문서를 일일이 제작
• 서버에 저장된 값을 화면에 반영하는 동적인 웹 문서 도구 개발
서버 사이드 렌더링(Server Side Rendering)
ASP(Active Server Page), JSP(Java Server Page)
• 웹 서버가 아닌 자바스크립트 코드로 웹 문서를 생성
싱글 페이지 어플리케이션(Single Page Application)
싱글 페이지 어플리케이션(Single Page Application)
기존 html과 달리 많은 페이지가 아니라 하나의 페이지로
자바스크립트나 json으로 전달 (html x)
싱글 페이지 어플리케이션 장점
• 페이지 전환 속도가 빠름
• 주소가 변경되어도 서버에 추가로 웹 문서를 요청하는 작업 필요 없음
(자바스크립트 페이지를 넘겨주기 때문에)
싱글 페이지 어플리케이션 단점
• 어플리케이션의 규모가 커지면 자바스크립트 파일 또한 커짐
👉 페이지 로딩 시, 사용자가 실제로 방문하지 않을 수도 있는 페이지의 스크립트까지 불러옴
리액트 라우터
라우팅이란?
• 사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것
• 페이지 이동
리액트 라우팅 라이브러리
• 리액트 라우터(react-router)
• 리치 라우터(reach-router)
• Next.js
리액트 라우터
(버전이 달라서 최신 글인지 확인 해야 함)
• 사용자가 입력한 주소를 감지하는 역할을 함
• 여러 환경에서 동작할 수 있도록 다양한 라우터 컴포넌트를 제공
• https://reactrouter.com/en/main
Home v6.4.4
I'm on v5 The migration guide will help you migrate incrementally and keep shipping along the way. Or, do it all in one yolo commit! Either way, we've got you covered to start using the new features right away.
reactrouter.com
라우터 컴포넌트 종류
라우터 컴포넌트 종류 | 설명 |
BrowserRouter | HTML5를 지원하는 브라우저의 주소를 감지 |
HashRouter | 해시주소(http://localhost#login)를 감지 |
MemoryRouter | 메모리에 저장된 이전, 이후 주소로 이동 |
NativeRouter | 리액트 네이티브를 지원하는 라우터 |
StaticRouter | 브라우저의 주소가 아닌 프로퍼티로 전달된 주소를 사용 |
리액트 라우터 설치
$ npm install react-router-dom |
리액트 라우터 생성
const router = createBrowserRouter([ //최상단
{
path: "/", path 는 주소 메인페이지가 슬러시로 표현
element: <div>Home</div>
errorElement: <div>Page Not Found</div> 에러났을 때는 이거 보여줘
}
]);
리액트 라우터 적용
이름 고정이라 바꾸면 안 됨! 위에 있는 변수 값을 라우터 안에 넣기
const App = () => {
return <RouterProvider router={router} />;
};
실습) 리액트 라우터 생성 및 적용
App.js
실행 결과)
실습) 컴포넌트로 변경
App.js
import { createBrowserRouter, RouterProvider } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
errorElement: <NotFound />
},
{
path: "/product",
element: <Product />,
errorElement: <NotFound />
}
]);
const App = () => {
return <RouterProvider router={router} />;
};
export default App;
Outlet 컴포넌트 Link 컴포넌트
Outlet 컴포넌트
리액트 라우터 생성
import { createBrowserRouter, RouterProvider } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
errorElement: <NotFound />,
children: [
{ index: true, element: <Home /> },
{ path: "/product", element: <Product /> }
]
}
]);
실습) Outlet 컴포넌트
Root.js
import React from "react";
import Menu from "./Menu";
import { Outlet } from "react-router-dom";
const Root = () => {
return (
<div>
<Menu />
<Outlet />
</div>
);
};
export default Root;
Menu.js
import React from "react";
import { Link } from "react-router-dom";
const Menu = () => {
return (
<div>
<Link to="/">Home</Link>
<Link to="/product">Product</Link>
</div>
);
};
export default Menu;
Link 컴포넌트
웹 페이지에서 링크를 추가할 때 <a>태그를 사용
• 리액트에서는 <a>태그를 직접 사용하면 안됨
• <a>태그를 클릭하여 페이지 이동 시, 브라우저가 페이지를 새로 불러오기 때문
(전체 페이지가 싹 다 초기화 됨. 내가 원하는 건 일부 영역만 바꾸는 것!)
• Link 컴포넌트를 이용하여 페이지 이동 가능
Link 컴포넌트
• 페이지를 새로 불러오는 것을 막고, History API를 통해 브라우저 주소의 경로만 변경하는 기능
<Link to="주소">링크이름</Link> |
Link = a
스타일 적용할 때는 .header .a 이런식으로 쓰기
App.js
import React from "react";
import Home from "./components/1208/Home";
import Product from "./components/1208/Product";
import NotFound from "./components/1208/NotFound";
import Root from "./components/1208/Root";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
errorElement: <NotFound />,
children: [
{ index: true, element: <Home /> },
{ path: "/product", element: <Product /> },
],
},
]);
const App = () => {
return <RouterProvider router={router} />;
};
export default App;
useNavigate()
실습) 페이지 전환
리액트 라우터 생성
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import React from "react";
import Home from "./components/1208/Home";
import Product from "./components/1208/Product";
import NotFound from "./components/1208/NotFound";
import Root from "./components/1208/Root";
import ProductInfo from "./components/1208/ProductInfo";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
errorElement: <NotFound />,
children: [
{ index: true, element: <Home /> },
{ path: "/product", element: <Product /> },
{ path: "/product/:productId", element: <ProductInfo /> },
],
},
]);
const App = () => {
return <RouterProvider router={router} />;
};
export default App;
App.js
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import React from "react";
import Home from "./components/1208/Home";
import Product from "./components/1208/Product";
import NotFound from "./components/1208/NotFound";
import Root from "./components/1208/Root";
import ProductInfo from "./components/1208/ProductInfo";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
errorElement: <NotFound />,
children: [
{ index: true, element: <Home /> },
{ path: "/product", element: <Product /> },
{ path: "/product/:productId", element: <ProductInfo /> },
],
},
]);
const App = () => {
return <RouterProvider router={router} />;
};
export default App;
ProductInfo.js
const ProductInfo = () => {
return <div>제품 상세 페이지</div>;
};
export default ProductInfo;
실행 결과
주소창 ~product/ 뒤에 아무거나 치면 제품상세페이지 글자가 나옴
이유 - { path: "/product/:productId", element: <ProductInfo /> } productId때문!
useNavigate()
• 페이지 방문 기록을 쉽게 관리할 수 있는 hooks
• 내장 함수를 사용하여 뒤로 가기, 특정 페이지로 이동 하기 등이 가능
(-1)쓰면 뒤로가기 등 히스토리 관리 가능
사용 방법
const navigate = useNavigate(); // home 경로로 이동 function goHome(){ navigate(‘/home’); } |
실습) useNavigate()
Product.js
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
const Product = () => {
const [productId, setProductId] = useState("");
const navigate = useNavigate();
const clickHandler = (e) => {
setProductId(e.target.value);
navigate(`/product/${productId}`);
};
return (
<>
<button onClick={clickHandler} value="p001">
1번 제품
</button>
<button onClick={clickHandler} value="p002">
2번 제품
</button>
<button onClick={clickHandler} value="p003">
3번 제품
</button>
</>
);
};
export default Product;
실습) useNavigate()
버튼을 두 번 클릭해야 페이지가 전환되는 문제 발생
이유
• useState()를 이용한 상태 업데이트는 비동기적이기 때문에 변경사항이 즉시 반영되지 않음
Product.js 수정
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
const Product = () => {
const [productId, setProductId] = useState("");
const navigate = useNavigate();
const clickHandler = (e) => {
setProductId(e.target.value);
};
useEffect(() => {
navigate(`/product/${productId}`);
}, [productId]);
return (
<>
<button onClick={clickHandler} value="p001">
1번 제품
</button>
<button onClick={clickHandler} value="p002">
2번 제품
</button>
<button onClick={clickHandler} value="p003">
3번 제품
</button>
</>
);
};
export default Product;
useParams()
useParams()
URL에 포함되어 있는 파라미터 값을 가져와서 사용할 수 있도록 해주는 hooks
사용 방법
• 데이터 전달
{ path: "/product/:productId", element: } |
• 데이터 사용
const { productId } = useParams(); |
productId의 이름이 동일해야함!!
실습) useParams()
ProductInfo.js
import React from "react";
import { useParams } from "react-router-dom";
const ProductInfo = () => {
const { productId } = useParams();
return <div>{productId}제품 상세 페이지</div>;
};
export default ProductInfo;
실행 결과
꼭!
새싹DT 기업연계형 프론트엔드 실무 프로젝트 과정 8주차 블로그 포스팅
'React' 카테고리의 다른 글
[새싹 프론트엔드] 9주차 - 1,2 Firebase (0) | 2022.12.12 |
---|---|
[새싹 프론트엔드] 9주차 - 1 네트워크 통신 (동기 vs 비동기) / fetch (0) | 2022.12.12 |
[새싹 프론트엔드] 8주차 - 3 Context (0) | 2022.12.07 |
[새싹 프론트엔드] 8주차 - 2 Hooks (0) | 2022.12.06 |
[새싹 프론트엔드] 8주차 - 1 Hooks (0) | 2022.12.05 |