기본적으로 우리 팀이 관리하는 프로젝트는 MPA(Multi-Page-Application) 구조를 가지고 있다.
MPA란, 각각의 Page URL을 통해 그에 맞는 HTML을 불러와서 보여주는 형식을 말한다.
React를 도입하게 되면서 React는 기본적으로 SPA(Single-Page-Application)을 취하고 있기 때문에 그에 맞는 라우팅을 설정해주어야 한다.
즉, SPA는 CSR(Client-Side-Routing)을 취하고 있기 때문에 하나의 HTML 파일에서 모든 라우팅을 다 처리한다는 의미이다.
History and Locations
React Router가 어떠한 라우팅 작업이든 할 수 있으려면 브라우저의 History Stack의 변경 사항을 구독할 수 있어야 한다.
브라우저는 사용자가 웹사이트를 탐색 시 고유한 기록 스택을 유지하는데, 이를 통해서 뒤로가기, 앞으로 가기 버튼이 동작한다.
즉, 브라우저는 사용자가 링크를 클릭하거나 양식을 제출하거나, 뒤로 및 앞으로 가기를 클릭할 때마다 서버에 요청을 보낸다.
- clicks a link to /dashboard
- clicks a link to /accounts
- clicks a link to /cutomer/123
- clicks the back button
- clicks a link to /dashboard
위 순서대로 진행 시 히스토리 스택은 다음과 같이 변경된다(진한 URL이 현재 URL)
- ['/dashboard']
- ['/dashboard', '/accounts']
- ['/dashboard', '/accounts', '/customer/123']
- ['/dashboard', '/accounts', '/customer/123']
- ['/dashboard', '/accounts', '/dashboard']
History Object
CSR을 통해 개발자는 브라우저 History Stack을 조작할 수 있다.
즉, 서버에 요청하는 브라우저의 기본 동작 없이 URL을 변경하기 위해 다음과 같은 코드를 작성할 수 있다.
<a
href="/contact"
onClick={(event) => {
// stop the browser from changing the URL and requesting the new document
event.preventDefault();
// push an entry into the browser history stack and change the URL
window.history.pushState({}, undefined, "/contact");
}}
/>
그러나 위와 같은 코드는 URL을 리스닝하지 않는다.(POP 이벤트는 구독할 수 있다!)
즉, URL에 대한 변경 사항을 클라이언트에서 구독하지 않는다는 것이다.
여기에서 React Router의 History 객체가 작동하게 되는데, History 액션이 PUSH, POP, REPLACE인지 여부에 따라 "URL 리스닝"변경 방법을 제공한다.
let history = createBrowserHistory();
history.listen(({ location, action }) => {
// this is called whenever new locations come in
// the action is POP, PUSH, or REPLACE
});
즉, 사용자 자체적으로 히스토리 객체를 설정할 필요가 없다는 말이다.
이것이 <Router>의 역할인데, 히스토리 객체 하나를 설정하고, 히스토리 스택의 변경사항을 구독하여 URL이 변경되면 상태를 업데이트를 하고 그에 따른 UI를 렌더링하게 된다.
Routes
<Routes>는 porps.children을 재귀하며 props를 제거하고 라우트 객체를 생성한다.
<Routes>
<Route path="/" element={<App />}>
<Route index element={<Home />} />
<Route path="teams" element={<Teams />}>
<Route path=":teamId" element={<Team />} />
<Route path=":teamId/edit" element={<EditTeam />} />
<Route path="new" element={<NewTeamForm />} />
<Route index element={<LeagueStandings />} />
</Route>
</Route>
<Route element={<PageLayout />}>
<Route path="/privacy" element={<Privacy />} />
<Route path="/tos" element={<Tos />} />
</Route>
<Route path="contact-us" element={<Contact />} />
</Routes>
위와 같은 route tree 컴포넌트 들을
let routes = [
{
element: <App />,
path: "/",
children: [
{
index: true,
element: <Home />,
},
{
path: "teams",
element: <Teams />,
children: [
{
index: true,
element: <LeagueStandings />,
},
{
path: ":teamId",
element: <Team />,
},
{
path: ":teamId/edit",
element: <EditTeam />,
},
{
path: "new",
element: <NewTeamForm />,
},
],
},
],
},
{
element: <PageLayout />,
children: [
{
element: <Privacy />,
path: "/privacy",
},
{
element: <Tos />,
path: "/tos",
},
],
},
{
element: <Contact />,
path: "/contact-us",
},
];
위와 같이 만들어주는 것이 <Routes> 컴포넌트의 역할이다.
한줄 요약
react router는 SPA인 React에서 Routing을 처리해주는 라이브러리이며, 내부적으로는 winodw 객체를 사용하여 라우팅을 처리한다.
'리액트' 카테고리의 다른 글
진행률에 따른 텍스트 색상이 바뀌는 프로그레스바 구현하기(2) (0) | 2023.12.13 |
---|---|
웹뷰 로딩 성능 개선하기 (1) | 2023.12.07 |
진행률에 따른 텍스트 색상이 바뀌는 프로그레스바 구현하기 (1) | 2023.12.07 |
Should have a queue. This is likely a bug in React. Please file an issue 해결하기 (1) | 2023.12.06 |
React VS jQuery (0) | 2023.06.21 |