동적 라우팅

신주안·2022년 9월 14일

👨‍💻 동적라우팅?

라우팅을 가장 기본적으로 설정하는 방법은 '정적 라우팅'이다.
Router 컴포넌트에서 미리 프로젝트에서 사용할 수 있는 경로들과 해당 경로로 접속했을 때 보여줄 컴포넌트를 모두 정의해두는 방식이다.

// Router.js

function Router() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Main />} />
        <Route path="/detail" element={<Detail />} />
      </Routes>
    </BrowserRouter>

하지만 만약에 디테일 페이지를 100개 이상 쓸려고 한다면 라우트를 100개를 만들어야 써야할 것이다.
이러한 문제점을 해결하기 위한 것이 바로 '동적 라우팅' 이다.
Route를 설정할 때 URL의 전체 형태를 미리 정의하는 것이 아니라
특정 규칙을 정의한 후 규칙에 부합하는 URL의 경우에는 해당 element를 보여주게 설정하는 방식으로 해결하는 것이다.


🚀 동적 라우팅 구현

동적 라우팅을 구현하는 방법은 Route 컴포넌트의 path prop에 : 기호를 활용하는 것이다.
경로/:문자열형태로 path를 설정하면 URL에서 경로/ 뒤에 무슨 글자가 오든 이 Route로 연결되게 된다.

// Router.js

function Router() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Main />} />
        <Route path="/detail/:id" element={<Detail />} />
      </Routes>
    </BrowserRouter>

위 예시 코드와 같이 Route를 설정하게 되면 detail 뒤에 어떤 글자가 와도 모두 상세페이지 컴포넌트를 보여주게 된다.
즉, detail/1 ,detail/1000 , detail/1000000, detail/test 모두 상세페이지 컴포넌트로 연결된다.
여기서 : 기호 뒤에 붙는 id 와 같은 문자열이 path parameter 이다.


👉 Path parameter

path parameter란 URL에 있는 값을 마치 매개변수(parameter)처럼 사용한다.
함수에서 매개변수의 이름을 자유롭게 지을 수 있는 것처럼 path parameter의 이름도 자유롭게 작성할 수 있다.
예시 코드에서는 detail/:id라고 path를 설정했으니까 path parameter의 이름을 id 로 설정하여
결과적으로 유저가 detail/1로 접속하면 id라는 이름으로 1이라는 값이 전달되는 것입니다


🛎 useParams Hook

react-router-dom에서는 useParams hook을 제공해 준다.
useParams hook은 path parameter의 값을 편하게 가져올 수 있게 해주며
마치 state처럼 path parameter의 *값이 바뀌면 컴포넌트를 리렌더링 해주는 기능을 제공해 준다.
useParams는 받아온 값을 객체로 반환한다.

// useParams 활용 예시

import { useParams } from 'react-router-dom';

const params = useParams();
// { [path-parameter-name]: value }

🔥 디테일 페이지 로직 구현

1. Route에서 동적 라우팅을 위해 'detail/:id' 로 path parameter를 지정한다.

// Router.js
function Router() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Main />} />
        <Route path="/detail/:id" element={<Detail />} />
      </Routes>
    </BrowserRouter>

2. 메인 페이지에서 api 를 받아와 state에 저장

//Main.js
function Main() {
  const [cardList, setCardList] = useState([]);
  
  useEffect(() => {
    fetch("api 주소")
      .then((response) => response.json())
      .then((data) => setCard(data));
  }, []);
  
  return(
  	<div className='main'>
    </div>
  )

3. 받아온 State로 map 메서드 사용

그 안에 <Link>로 감싸고 경로를 /detail/${id}로 지정한다. 이렇게 되면 만들어진 요소를 선택할 때 마다
/detail/ 만들어진 요소의 아이디의 url로 이동하게 된다.

// Main.js
function Main() {
  const [cardList, setCardList] = useState([]);
  
  useEffect(() => {
    fetch("api 주소")
      .then((response) => response.json())
      .then((data) => setCard(data));
  }, []);
  
  return(
  	<div className='main'>
    	{cardList.map((card) => {
          <Link to={`/detail/${card.id}`} key={card.id}>
            <Card card={card}></Card>;
          </Link>
        );
      })}
    </div>
  )

4. Detail 컴포넌트에서 useParams 훅을 사용하여 현재 페이지의 매개변수를 가져온다.

여기서 가져온 매개변수는 객체로 받아와지기 때문에 구조분해할당을 통해서 가져오면 좋다.

// Detail.js
import { useParams } from 'react-router-dom';

function Detail(){
const { id } = useParams();
  
  return(
  	<div>
    	<p>현재는 디테일? 페이지입니다.<p/>
    </div>
  )
}

5. detail에 맞는 api를 fetch하는데 api 주소에 매개변수를 알맞게 넣어서 가져온다.

// Detail.js
import React,{ useState } from "react";
import { useParams } from 'react-router-dom';

function Detail(){
const { id } = useParams();
const [detailData, setDetailData] = useState()

useEffet(()=>{
  fetch(`불러올 디테일 주소/${ id }`) // useParams 사용
  .then(res=>res.json())
  .then(data=>setDetailData(data)) // api 데이터 저장
})

  return(
  	<div>
    	<p>현재는 디테일? 페이지입니다.<p/>
    </div>
  )
}

6. 그렇게 가져온 데이터를 state에 저장하고 구조 분해 할당하여 각 필요한 데이터를 바인딩 시켜주면 끝

// Detail.js
import React,{ useState } from "react";
import { useParams } from 'react-router-dom';

function Detail(){
const { id } = useParams();
const [detailData, setDetailData] = useState()

useEffet(()=>{
 fetch(`불러올 디테일 주소/${ id }`) // useParams 사용
 .then(res=>res.json())
 .then(data=>setDetailData(data)) // api 데이터 저장
})

 return(
 	<div>
   	<p>`현재는 디테일 ${detailData.id} 페이지입니다.`<p/>
   </div>
 )
}
profile
끝이 없네!

0개의 댓글