React Router 알고 사용하기

thisishwarang·2024년 5월 2일
1
post-thumbnail

Routing을 사용하는 이유는 뭘까?

하나의 웹서비스를 만들기 위해서는 정말 많은 url이 필요합니다.
블로그를 예시로 들자면 로그인페이지로 이동하는 /login, 블로그를 작성하는 페이지로 이동하는 /write, 블로그 게시물들을 전체보기하는 /posts, 특정 게시물 상세페이지로 이동하는 /post/1, /post/2..., 마이페이지로 이동하는 /mypage 등등 이외에도 정말 다양한 경로로의 라우팅이 필요합니다.

a태그 만으론 부족한가?

html 자체적으로 a태그를 사용해서 페이지를 이동할 수 있는데 왜 React-router를 사용해서 라우팅을 하는걸까요?

-> 결론을 먼저 말하자면 SPA 개발에 효율적이기 때문입니다

a 태그를 통해 페이지를 이동하면 페이지 전체가 새로 로딩되면서 사용자에게 화면 깜빡임을 보여주게 되고, 이는 UX를 떨어뜨리는 큰 단점입니다.
SPA는 페이지 전환 없이 동적으로 콘텐츠를 업데이트하고 상호작용하는 방식입니다. React-Router를 사용하면 URL에 따라 콘텐츠를 동적으로 변경할 수 있다는 장점이 있어 UX를 높일 수 있습니다.

SPA 내부에서 모든 페이지를 다 랜더링해주면?

-> 여러가지 문제가 생깁니다.

  1. 즐겨찾기 등록 불가
  2. 뒤로가기 및 새로고침 불가
  3. SEO 측면에서 효율 떨어짐

React-Router의 한 종류 - BrowserRouter

React-Router에는 두가지 종류가 있는데 그중 HTML5를 지원하는 브라우저의 주소를 감지 하고 history API를 사용하는 BrowserRouter를 대부분 사용한다.

* 이때 주의해야할 점으로 BrowserRouter 방식으로 사이트를 배포했을 때 서버에는 기본 라우트 https://페이지이름~/ 정보만 저장되어 있고, 그 뒤로의 경로는 모두 이 default 경로를 통해 이동되기 때문에 정의되지 않은 url로 이동하게 된다면 서버에서 인식하지 못해 404에러가 발생한다. 따라서 이를 대비하여 404에러 페이지를 미리 설정해놓는게 좋다.

React-Router-Dom

React 프로젝트의 SPA에서 브라우저를 위한 routing & navigation을 구현하는데 사용되는 대표적인 라이브러리입니다.

react-router-dom에는 크게 4가지 기능이 있습니다.

1. Routing

  • BrowserRouter 컴포넌트를 통해 프로젝트의 최상위 레벨에서 브라우저 기반의 라우팅을 설정하고, 이를 통해 URL 경로에 따라 다른 컴포넌트를 렌더링할 수 있습니다.

2. nesting된 Route

  • 모든 페이지가 /mypage, /login 과 같이 한 deps만 들어가는것이 아니라 /post/1 과 같이 중첩된 라우팅 경로를 필요로 하는 경우가 있는데 이를 가능하게 도와줍니다.
  • Link 컴포넌트를 사용하여 다른 url로의 이동이 가능하고, Redirect 컴포넌트를 사용하여 리다이렉트할 경로도 설정할 수 있습니다.

4. parameter & query 매개변수 처리

  • 동적으로 생성되는 url parameter와 추가되는 query 부분을 처리할 수 있는 매소드를 제공하여 다양한 처리가 가능합니다.

5. history 관리

  • history API를 사용하여 뒤로 가기, 앞으로 가기 등의 히스토리와 관련된 기능을 처리할 수 있습니다.

react-router-dom 사용방법

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 프로퍼티로 이동시켜줄 수 있습니다.

  1. preventScrollReset
    • 페이지 중간에서 페이지 이동을 할 때 이 속성을 true로 설정하여 스크롤이 초기화 되어 페이지 가장 위로 올라가는것을 방지할 수 있습니다.
  2. state 전달
    • 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

useNavigate

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/1url에서 PostDetail 컴포넌트를 보여주기 위해 중첩 라우팅을 사용할 수 있습니다.

Outlet

모든 페이지에 Header컴포넌트를 통해 상단 nav바를 보여주고싶다면 어떻게 해야할까요? 모든 페이지에 Header 컴포넌트를 붙여주는건 너무 비효율적입니다.

<>
	<Header />
	<Outlet />
</>

이처럼 Header 컴포넌트를 보여줄 최상단 컴포넌트에서 호출하고, 그 밑으로 children 문법처럼 Outlet 컴포넌트를 호출하여 나머지 라우팅 구조를 보여줄 수 있습니다.
이후 next.js의 layout.jsx 컴포넌트와 비슷한 구조라고 생각해서 알고있으면 좋을것 같아요.

Params

url 주소를 자세히 보면 /post/1과 같이 /를 기준으로 url이 달라지는 구조가 있고, ?, &를 기준으로 /search?query=react&page=1 와 같이 key와 value 하나의 세트로 전달되는 데이터구조가 있습니다.
전자의 경우를 url파라미터, 후자의 경우를 queryString 이라고 합니다.

useParams

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>
  );
}

useSearchParams

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>
  );
}

참고문서
https://reactrouter.com/en/main

9개의 댓글

comment-user-thumbnail
2024년 5월 7일

우선 리액트 라우팅이 필요한 이유를 정리해주셔서 목적성을 가지고 아티클을 읽을 수 있었습니다:) 그리고 라우터를 기능별로 공부해본 적이 없었는데 기능을 분류하고 정리해주셔서 넘 좋았습니다! Link 컴포넌트의 preventScrollReset 속성은 처음 알았는데 정말 유용할 것 같네요. Outlet 컴포넌트도 얼른 적용해보고 싶네요:) 덕분에 많이 배우고 갑니다~ 수고하셨어유

답글 달기
comment-user-thumbnail
2024년 5월 8일

술술 읽히는 아티클이라 너무 좋았습니다... 🫶 핵심 내용을 먼저 언급하고 자세한 내용을 설명해 주셔서 이해도 잘 되고 친절한 아티클인 것 같아요!! 예제에 대한 설명도 친절하고 react router를 처음 적용해 보는 사람에게 너무 추천하고 싶은 아티클이네요!! 저도 preventScrollReset 속성을 처음 알았는데 덕분에 배워갑니다~ 아티클 작성 고생 많으셨어요 감사합니다 🔥

답글 달기
comment-user-thumbnail
2024년 5월 8일

라우팅을 사용하는 이유부터 사용방법까지 꼼꼼하게 정리하셨네요 특히 Outlet이 어떠한 경우에 쓰이는지 헷갈렸는데 들어주신 예시 덕분에 이해에 많은 도움이 됐습니다! next.js에 비슷한 개념이 있다는 것도 추가로 배워갑니다..!! 그리고 이후에 api 연결할 때 url파라미터와 queryString라는 개념이 한 번 더 나올텐데 이 부분도 간단하게 언급해주셔서 짚고 넘어가기 좋았습니다! 고생 많으셨어요

답글 달기
comment-user-thumbnail
2024년 5월 8일

리엑트 라우팅이 필요한 이유를 설명해주신 덕에 라우터의 사용 이유 및 사용 목적에 대해 잘 알게 되었습니다!
a 태그 사용 시 문제점, spa에서 모든 페이지를 렌더링 할 시의 문제점 등 중요한 부분을 알기 쉽게 집어주셔서 너무 좋았습니다 ㅎㅎ
그 외에도 라우터의 여러가지 사용법을 코드 예시와 함께 보여주셔서 잘 읽고 갑니다 👍👍
좋은 글 감사합니다!

답글 달기
comment-user-thumbnail
2024년 5월 8일

리액트 라우팅에 대한 내용들을 전부 다뤄주셔서 전반적인 이해를 가져가며 잘 읽을 수 있었습니다 !! 또한 outlet에 대한 이해를 가져갈 수 있어서 좋았습니다🙃 바쁜 와중에 좋은 아티클 읽고 갑니다 감사합니다!

답글 달기
comment-user-thumbnail
2024년 5월 8일

지금까지 a태그를 주로 사용해왔는데 화랑님 아티클 덕분에 a태그의 단점을 명확히 이해하게 되었습니다. 뿐 만 아니라 react-router-dom의 주요 기능과 함께 사용법까지 예시와 함께 작성해주셔서 막힘없이 술술 읽을 수 있었습니다. 라우터 사용할 때 막히는 부분이 생기면 화랑님 아티클 다시 읽으러 와야겠어요. 양질의 내용 감사합니다!

답글 달기
comment-user-thumbnail
2024년 5월 8일

핵심을 잘 짚어줘서 퀄리티 좋은 양질의 아티클인것 같아요! 적절한 코드 예시가 있어 이해하기가 더 쉬웠던것 같습니다. 특히 useNavigate 훅은 잘 몰랐었는데 화랑님 덕분에 알아가고 이번주차 과제에 잘 적용할것 같습니다! 깔끔한 아티클 잘 보고갑니다 수고하셨습니다!!!

답글 달기
comment-user-thumbnail
2024년 5월 8일

리액트 라우터를 사용하는 이유와 SPA 개발에 얼마나 효율적인지에 대한 설명이 유익했습니다! 기존에는 단순히 페이지 간의 이동이 더 쉬워진다는 정도로만 알고 있었는데, 사용자 경험(UX)을 향상시키고, 페이지의 전체 로딩 없이도 콘텐츠를 업데이트할 수 있다는 점이 중요한 것이라는 걸 알게 되었어요!
BrowserRouter가 history API를 사용해 브라우저의 주소를 감지하고 관리한다는 것은 알고 있었지만, 정의되지 않은 URL로 이동했을 때 404 에러가 발생할 수 있다는 점과 이를 대비해 404에러 페이지를 설정해야 한다는 점은 새롭게 알게 되었습니다! 세세한 부분까지 신경 써야 한다는 것을 알게되어서 좋았어요!
Link 컴포넌트를 사용할 때 preventScrollReset 속성과 state 전달 방법에 대한 설명도 인상깊었는데요..! 페이지 이동 시 스크롤 위치가 유지되는 것은 사용자 경험에 큰 영향을 미치는데, 이를 간단한 속성 하나로 조절할 수 있다는 것이 놀라웠습니다! 좋은 아티클 감사합니다!

답글 달기
comment-user-thumbnail
2024년 5월 8일

React 프로젝트에서 라우팅을 구현하는 데 있어 유용한 가이드를 제공해주신 것 같습니다. SPA가 주는 사용자 경험의 연속성과 그로 인한 UX 개선 방법에 대해 잘 이해할 수 있었습니다. React Router의 다양한 기능과 컴포넌트 등의 사용법을 자세히 알 수 있었고, 복잡한 라우팅 요구사항을 어떻게 충족시키는지에 대한 이해도를 높일 수 있었습니다. 각 기능에 대한 상세한 설명과 함께 구체적인 예제 코드를 제공해주셔서 더 좋았습니다! 좋은 아티클 감사합니다 :)

답글 달기