하나의 웹서비스를 만들기 위해서는 정말 많은 url이 필요합니다.
블로그를 예시로 들자면 로그인페이지로 이동하는 /login
, 블로그를 작성하는 페이지로 이동하는 /write
, 블로그 게시물들을 전체보기하는 /posts
, 특정 게시물 상세페이지로 이동하는 /post/1
, /post/2
..., 마이페이지로 이동하는 /mypage
등등 이외에도 정말 다양한 경로로의 라우팅이 필요합니다.
html 자체적으로 a태그를 사용해서 페이지를 이동할 수 있는데 왜 React-router를 사용해서 라우팅을 하는걸까요?
-> 결론을 먼저 말하자면 SPA 개발에 효율적이기 때문입니다
a 태그
를 통해 페이지를 이동하면 페이지 전체가 새로 로딩되면서 사용자에게 화면 깜빡임을 보여주게 되고, 이는 UX를 떨어뜨리는 큰 단점입니다.
SPA는 페이지 전환 없이 동적으로 콘텐츠를 업데이트하고 상호작용하는 방식입니다.React-Router
를 사용하면 URL에 따라 콘텐츠를 동적으로 변경할 수 있다는 장점이 있어 UX를 높일 수 있습니다.
-> 여러가지 문제가 생깁니다.
- 즐겨찾기 등록 불가
- 뒤로가기 및 새로고침 불가
- SEO 측면에서 효율 떨어짐
React-Router에는 두가지 종류가 있는데 그중 HTML5를 지원하는 브라우저의 주소를 감지 하고 history API를 사용하는 BrowserRouter를 대부분 사용한다.
* 이때 주의해야할 점으로 BrowserRouter 방식으로 사이트를 배포했을 때 서버에는 기본 라우트 https://페이지이름~/
정보만 저장되어 있고, 그 뒤로의 경로는 모두 이 default 경로를 통해 이동되기 때문에 정의되지 않은 url로 이동하게 된다면 서버에서 인식하지 못해 404에러
가 발생한다. 따라서 이를 대비하여 404에러 페이지를 미리 설정해놓는게 좋다.
React 프로젝트의 SPA에서 브라우저를 위한 routing & navigation을 구현하는데 사용되는 대표적인 라이브러리입니다.
react-router-dom에는 크게 4가지 기능이 있습니다.
BrowserRouter
컴포넌트를 통해 프로젝트의 최상위 레벨에서 브라우저 기반의 라우팅을 설정하고, 이를 통해 URL 경로에 따라 다른 컴포넌트를 렌더링할 수 있습니다./mypage
, /login
과 같이 한 deps만 들어가는것이 아니라 /post/1
과 같이 중첩된 라우팅 경로를 필요로 하는 경우가 있는데 이를 가능하게 도와줍니다.1. react-router-dom 설치
npm i react-router-dom
yarn add react-router-dom
2. 초기세팅
// Router.jsx
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import Login from "./pages/Login";
import PostDetail from "./pages/PostDetail";
const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/post-detail/:postId" element={<PostDetail />}></Route>
</Routes>
</BrowserRouter>
);
};
export default Router;
이렇게 Router 컴포넌트로 라우팅이 될 pathname과 해당 path에서 보여줄 컴포넌트를 설정하고
//App.jsx
import Router from "./Router";
function App() {
return (
<>
<Router />
</>
);
}
export default App;
최상단 App컴포넌트에 Router컴포넌트를 붙여줍니다.
<Link to="/login">로그인</Link>
이처럼 특정 컴포넌트에서 다른 url로 이동할 때 Link 컴포넌트에 to
프로퍼티로 이동시켜줄 수 있습니다.
true
로 설정하여 스크롤이 초기화 되어 페이지 가장 위로 올라가는것을 방지할 수 있습니다.useLocation
훅과 함께 사용하여 특정 state를 전달할 수 있습니다.<Link to="/login" state={{ name: 'hwarang' }} />
//Login.jsx
import React from 'react'
import { useLocation } from "react-router-dom"
const Login = () => {
const location = useLocation();
console.log(location)
return (
<div className="login">
hello
</div>
)
}
export default Login
Link컴포넌트로 꼭 감싸서 라우팅하지 않아도 useNavigate
훅을 사용하여 라우팅 할 수 있습니다.
useNavigate
훅을 사용하면 onClick, onChange등 이벤트가 발생했을 때 함수를 호출하는것과 같은 방식으로 라우팅을 할 수 있게 해줍니다.
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const onClick = () => {
navigate('/login')
}
<Routes>
<Route path="/" element={<Home />}>
<Route path="/post" element={<PostList />}>
<Route path=":postId" element={<PostDetail />} />
</Route>
</Routes>
위 코드와 같이 게시물 리스트를 /post
url에서 보여주다가 특정 게시물을 클릭하여 들어갔을 때 /post/1
url에서 PostDetail 컴포넌트를 보여주기 위해 중첩 라우팅을 사용할 수 있습니다.
모든 페이지에 Header컴포넌트를 통해 상단 nav바를 보여주고싶다면 어떻게 해야할까요? 모든 페이지에 Header 컴포넌트를 붙여주는건 너무 비효율적입니다.
<>
<Header />
<Outlet />
</>
이처럼 Header 컴포넌트를 보여줄 최상단 컴포넌트에서 호출하고, 그 밑으로 children
문법처럼 Outlet 컴포넌트를 호출하여 나머지 라우팅 구조를 보여줄 수 있습니다.
이후 next.js의 layout.jsx 컴포넌트와 비슷한 구조라고 생각해서 알고있으면 좋을것 같아요.
url 주소를 자세히 보면 /post/1
과 같이 /를 기준으로 url이 달라지는 구조가 있고, ?, &
를 기준으로 /search?query=react&page=1
와 같이 key와 value 하나의 세트로 전달되는 데이터구조가 있습니다.
전자의 경우를 url파라미터
, 후자의 경우를 queryString
이라고 합니다.
url파라미터의 값을 가져오고 싶을 때 useParams()
훅을 사용해서 쉽게 가져올 수 있습니다.
import { useParams } from 'react-router-dom';
function Post() {
const { post, postId } = useParams();
return (
<div>
<h2>Post: {post}</h2>
<h2>Post ID: {postId}</h2>
</div>
);
}
queryString을 가져올때는 useSearchparams
을 사용하여 객체 형식으로 key값을 통해 가져올 수 있습니다. 가져올때는 get()
메서드를 사용하여 해당 key값의 value를 가져와 활용할 수 있습니다.
import { useSearchParams } from 'react-router-dom';
function SearchResults() {
const [searchParams] = useSearchParams();
const query = searchParams.get('query');
const page = searchParams.get('page');
return (
<div>
<h2>Search Results</h2>
<p>Query: {query}</p>
<p>Page: {page}</p>
</div>
);
}
술술 읽히는 아티클이라 너무 좋았습니다... 🫶 핵심 내용을 먼저 언급하고 자세한 내용을 설명해 주셔서 이해도 잘 되고 친절한 아티클인 것 같아요!! 예제에 대한 설명도 친절하고 react router를 처음 적용해 보는 사람에게 너무 추천하고 싶은 아티클이네요!! 저도 preventScrollReset 속성을 처음 알았는데 덕분에 배워갑니다~ 아티클 작성 고생 많으셨어요 감사합니다 🔥
라우팅을 사용하는 이유부터 사용방법까지 꼼꼼하게 정리하셨네요 특히 Outlet이 어떠한 경우에 쓰이는지 헷갈렸는데 들어주신 예시 덕분에 이해에 많은 도움이 됐습니다! next.js에 비슷한 개념이 있다는 것도 추가로 배워갑니다..!! 그리고 이후에 api 연결할 때 url파라미터와 queryString라는 개념이 한 번 더 나올텐데 이 부분도 간단하게 언급해주셔서 짚고 넘어가기 좋았습니다! 고생 많으셨어요
리엑트 라우팅이 필요한 이유를 설명해주신 덕에 라우터의 사용 이유 및 사용 목적에 대해 잘 알게 되었습니다!
a 태그 사용 시 문제점, spa에서 모든 페이지를 렌더링 할 시의 문제점 등 중요한 부분을 알기 쉽게 집어주셔서 너무 좋았습니다 ㅎㅎ
그 외에도 라우터의 여러가지 사용법을 코드 예시와 함께 보여주셔서 잘 읽고 갑니다 👍👍
좋은 글 감사합니다!
리액트 라우팅에 대한 내용들을 전부 다뤄주셔서 전반적인 이해를 가져가며 잘 읽을 수 있었습니다 !! 또한 outlet에 대한 이해를 가져갈 수 있어서 좋았습니다🙃 바쁜 와중에 좋은 아티클 읽고 갑니다 감사합니다!
지금까지 a태그를 주로 사용해왔는데 화랑님 아티클 덕분에 a태그의 단점을 명확히 이해하게 되었습니다. 뿐 만 아니라 react-router-dom의 주요 기능과 함께 사용법까지 예시와 함께 작성해주셔서 막힘없이 술술 읽을 수 있었습니다. 라우터 사용할 때 막히는 부분이 생기면 화랑님 아티클 다시 읽으러 와야겠어요. 양질의 내용 감사합니다!
핵심을 잘 짚어줘서 퀄리티 좋은 양질의 아티클인것 같아요! 적절한 코드 예시가 있어 이해하기가 더 쉬웠던것 같습니다. 특히 useNavigate 훅은 잘 몰랐었는데 화랑님 덕분에 알아가고 이번주차 과제에 잘 적용할것 같습니다! 깔끔한 아티클 잘 보고갑니다 수고하셨습니다!!!
리액트 라우터를 사용하는 이유와 SPA 개발에 얼마나 효율적인지에 대한 설명이 유익했습니다! 기존에는 단순히 페이지 간의 이동이 더 쉬워진다는 정도로만 알고 있었는데, 사용자 경험(UX)을 향상시키고, 페이지의 전체 로딩 없이도 콘텐츠를 업데이트할 수 있다는 점이 중요한 것이라는 걸 알게 되었어요!
BrowserRouter가 history API를 사용해 브라우저의 주소를 감지하고 관리한다는 것은 알고 있었지만, 정의되지 않은 URL로 이동했을 때 404 에러가 발생할 수 있다는 점과 이를 대비해 404에러 페이지를 설정해야 한다는 점은 새롭게 알게 되었습니다! 세세한 부분까지 신경 써야 한다는 것을 알게되어서 좋았어요!
Link 컴포넌트를 사용할 때 preventScrollReset 속성과 state 전달 방법에 대한 설명도 인상깊었는데요..! 페이지 이동 시 스크롤 위치가 유지되는 것은 사용자 경험에 큰 영향을 미치는데, 이를 간단한 속성 하나로 조절할 수 있다는 것이 놀라웠습니다! 좋은 아티클 감사합니다!
우선 리액트 라우팅이 필요한 이유를 정리해주셔서 목적성을 가지고 아티클을 읽을 수 있었습니다:) 그리고 라우터를 기능별로 공부해본 적이 없었는데 기능을 분류하고 정리해주셔서 넘 좋았습니다! Link 컴포넌트의 preventScrollReset 속성은 처음 알았는데 정말 유용할 것 같네요. Outlet 컴포넌트도 얼른 적용해보고 싶네요:) 덕분에 많이 배우고 갑니다~ 수고하셨어유