[React] 리액트 라우터

✨ 강은비·2022년 1월 15일
0

React

목록 보기
21/36
post-thumbnail

React Router v6 기준으로 작성됨.

📌 SPA란?

Single Page Application: 말 그대로 한 개의 페이지로 이루어져 있는 애플리케이션을 말한다.

과거

  • 전통적인 웹 애플리케이션은 여러 개의 페이지로 이루어져 있었다.
  • 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아오고, 해석한 뒤 화면에 보여주었다.
  • 애플리케이션 내에서 페이지 전환이 일어날 때마다 html을 계속 서버에 새로 요청하면 성능상의 문제가 발생할 수 있다.

현재

  • 리액트 같은 라이브러리 혹은 프레임워크를 사용하여 뷰 렌더링을 사용자의 브라우저가 담당하도록 하고, 사용자와의 인터랙션이 발생하면 필요한 부분만 자바스크립트를 사용하여 업데이트해준다.
  • 만약 새로운 데이터가 필요하다면 서버 API를 호출하여 필요한 데이터만 불러와 사용하면 된다.

Routing

  • 싱글 페이지라고 해서 화면의 종류가 하나인 것은 아니다.
  • 다른 주소에 따라 다른 화면을 보여주는 것Routing이라 한다.
  • 리액트 라우팅 라이브러리에는 리액트 라우터, 리치 라우터 등이 있다.

단점

  1. 앱의 규모가 커지면 자바스크립트 파일 크기가 너무 커진다.
    • 페이지 로딩 시 사용자가 실제 방문하지 않을 수도 있는 화면의 자바스크립트도 불러오기 때문이다.
    • code spliting을 이용하면 라우트별로 파일들을 나누어서 트래픽과 로딩속도를 개선할 수 있다.
  2. 리액트 라우터같이 브라우저 측에서 자바스크립트를 이용하여 라우트를 관리하면 자바스크립트를 실행하지 않는 일반 크롤러에서 페이지의 정보를 제대로 수집할 수 없어 검색결과에서 잘 나타나지 않을 수 있다.
  3. 자바스크립트가 실행될 때까지 페이지가 비어있기 때문에, 자바스크립트 파일이 아직 캐싱되지 않은 사용자는 아주 짧은 시간 동안 흰 페이지가 나타날 수 있다.

📌 리액트 라우터 기본적인 사용법

📙 BrowserRouter 컴포넌트

  • 웹 애플리케이션에 HTML5 History API를 사용하여 페이지를 새로고침하지 않고 주소를 변경한다.
  • 현재 주소에 관련된 정보를 컴포넌트에서 사용할 수 있도록 한다.
// index.js
import { BrowserRouter } from "react-router-dom";

ReactDOM.render(
    // 필수!!
    <BrowserRouter>
        <App/>
    </BrowserRouter>
);

📙 Route 컴포넌트

  • 주소규칙(path props)에 따라 어떤 컴포넌트(element props)를 보여줄지 정의한다.
<Route path="주소규칙" element={<컴포넌트 이름/>}/>

📙 Routes 컴포넌트

  • Route 컴포넌트들은 반드시 Routes자식 컴포넌트여야 한다.
  • Routes는 여러 Route를 감싸서 주소규칙이 가장 일치하는 하나의 라우트를 렌더링한다.
  • 모든 주소규칙와 일치하지 않을 때 보여 줄 Not Found 화면도 구현할 수 있다.
    • path props"/*"라고 설정하면 해당 Route는 모든 경로에 매치가 가능하다. 만약 현재 브라우저 주소가 나머지 Route의 주소규칙과 일치하지 않았다면 이 Route가 렌더링된다.
<Routes>
    <Route path="/" .... />
    <Route path="/*" element={<NotFound/>}/>
</Routes>
  • 클릭하면 특정 주소로 이동시켜 주는 컴포넌트이다.
  • 컴포넌트 자체는 a 태그로 이루어져 있지만, 페이지 전환을 방지하는 기능이 내장되어 있다.
  • HTML5 History API를 이용하여 페이지의 주소만 변경한다.
<Link to="주소">내용</Link>
  • Link 컴포넌트와 유사하지만 현재 사용자 브라우저 경로와 to props의 경로가 일치하는 경우 특정 스타일 혹은 CSS 클래스를 적용할 수 있는 컴포넌트이다.
const activeStyle={
    textDecoration: "underline"
};

const activeClassName = "underline";


<NavLink to="messages" style={({ isActive }) => isActive ? activeStyle : undefined}>
    Messages
</NavLink>

<NavLink to="messages" className={({ isActive }) => isActive ? activeClassName : undefined}>
    Tasks
</NavLink>

📌 URL 파라미터와 쿼리

페이지 주소를 정의할 때 가끔은 유동적인 값을 전달해야 할 때가 있다.

  • 파라미터: 아이디 혹은 이름을 사용하여 특정 데이터를 조회할 때 사용 (/profile/eunnbi)
  • 쿼리 스트링: 키워드 검색, 페이지네이션, 정렬 방식 등 데이터 조회에 필요한 옵션을 전달할 때 사용 (/about?details=true)

📙 URL 파라미터

  • useParams()를 이용하여 URL 파라미터를 객체 형태로 조회할 수 있다.
<Route path="/profiles/:username" element={<Profile/>}/>
const Profile = () => {
  const { username } = useParams();
  ...
}

📙 URL 쿼리

  • 쿼리는 location 객체의 search 프로퍼티에서 조회할 수 있다.
  • location 객체는 useLocation()를 이용하여 조회할 수 있다.
    • 이 객체는 현재 사용자가 보고 있는 페이지의 정보를 가지고 있다.
  • useSearchParams()를 이용하여 쿼리 스트링을 쉽게 다룰 수 있다.
    • 배열 타입의 값을 반환한다.
    • 첫번째 원소는 쿼리 파라미터를 조회하거나 수정하는 메서드들이 담긴 객체를 반환한다.
    • get메서드를 통해 특정 쿼리파라미터를 조회할 수 있고, set메서드를 통해 특정쿼리 파라미터를 업데이트할수 있다.
    • 두번째 원소는 쿼리 파라미터를 객체 형태로 업데이트할 수 있는 함수를 반환한다.
const About = () => {
    const [ searchParams, setSearchParams] = useSearchParams();
    const detail = searchParams.get("detail");
    
    const onToggleDetail = () => {
        setSearchParams({ detail: detail === "true" ? false : true});
    }

    return (
        <div>
            <h1>About</h1>
            <p>This page is About</p>
            <button onClick={onToggleDetail}>Toggle detail</button>
            {detail && <p>details</p>}
        </div>
    );
}

📌 중첩 라우터

라우트 내부에 또 라우트를 정의하는 것

📙 Outlet 컴포넌트를 사용하지 않는 경우

// App.js
...
return(
    <Link to="/profiles">PROFILE</Link>
    <Routes>
        <Route path="/profiles/*" element={<Profiles/>}/>
    </Routes>
);
// Profiles.js
...
return(
    <Link to="eunnbi">eunnbi</Link>
    <Routes>
        <Route path=":username" element={<Profile/>}/>
    </Routes>
);
  • Profiles 컴포넌트 내부에서 또 다시 Route를 정의했다.
  • Profiles 컴포넌트 밑으로 파라미터에 따라 다른 Profile 컴포넌트가 보여진다.

📙 Outlet 컴포넌트를 사용하는 경우

// App.js
...
return(
    <Link to="/profiles">PROFILE</Link>
    <Routes>
        <Route path="/profiles" element={<Profiles/>}>
            <Route path=":username" element={<Profile/>}/>
        </Route>
    </Routes>
);
// Profiles.js
...
return(
    <Link to="eunnbi">eunnbi</Link>
    <Outlet/>
);
  • Profiles 컴포넌트에 있던 Route 컴포넌트를 옮겨 라우트를 중첩시켰다.
  • Profiles 컴포넌트에는 Outlet 컴포넌트가 사용되었다.

    Outlet 컴포넌트는 자식 라우트에서 보여지는 컴포넌트를 부모 라우트 컴포넌트에서 렌더링하기 위해 사용되어야 한다.

📙 공통 레이아웃 컴포넌트

  • 중첩 라우터와 Oulet은 페이지끼리 공통적으로 보여줘야 하는 컴포넌트가 있을 때 유용하게 사용된다.
const Layout = () => {
    return (
        <div>
            <header>
            ...
            </header>
            <main>
               <Outlet/>
            </main>
        </div>
    );
}
const App = () => {
    return(
        <Routes>
            <Route element={<Header/>}>
               <Route path="/" element={<Home/>}/>
               <Route path="/about" element={<About/>}/>
            </Route>
        </Routes>
    );
    
}


📌 부가 기능

📙 useNavigate

  • useNavigate()Link 컴포넌트를 이용하지 않고도 다른 화면으로 이동해야 하는 상황에 사용한다.
const navigate = useNavigate();
  • navigate 함수는 두 가지 방법으로 사용 가능하다.
    • 첫번째 인자로 이동할 경로(to)를 전달하고 두 번째 인자로는 replace 혹은 state를 전달한다.
      • 이때 첫번째 인자는 Linkto props와 동일한 형태로 넣으면 된다.
      • 두 번째 인자는 필수가 아니다.
      • navigate(to, { replace: true }): 페이지를 이동할 때 현재 페이지를 페이지 기록에 남기지 않는다.
      • navigate(to, { state })
    • 히스토리 스택에서 가고자 하는 델타 값을 인자로 전달한다.
      • navigate(-1): 뒤로 가기

📙 Navigate 컴포넌트

  • 컴포넌트를 화면에 보여주는 순간 다른 페이지로 이동하고 싶을 때 사용한다. 즉, 페이지를 리다이렉트하고 싶을 때 사용한다.
  • 예를 들어, 사용자의 로그인이 필요한 페이지인데 로그인을 안 했다면 로그인 페이지로 이동해야 할 때 Navigate 컴포넌트를 사용한다.

참고

0개의 댓글