Routing

younghyun·2022년 3월 5일
0

Routing

다른 경로(url 주소)에 따라 다른 View(화면)를 보여주는 것.

SPA (Single Page Application, 단일 페이지 애플리케이션)

사용자가 웹 애플리케이션과 상호 작용하는 방식을 획기적으로 바꾼 기술.
사용자가 다른 뷰로 이동할 때 애플리케이션은 뷰를 동적으로 다시 그림. MPA(Multi Page Application) 대비 페이지 간 이동 시 사용자가 느낄 수 있는 딜레이를 제거해 일반적으로 더 나은 UX를 제공. (페이지 전체를 새로고침 하지 않기 때문! )

  • index.html : public/index.html에 위치하며 React 페이지 로드 시 가장 먼저 호출되는 영역
  • index.js : React 앱을 렌더하고 index.html의 div#root 이하에 끼워넣는 역할
  • Router.js : React 앱이 경로에 따라 어떤 컴포넌트를 보여줄지 결정하는 역할 (화면 바꿔 끼우기)

정적 라우팅

"/"         => <App />
"/users"    => <Users />
"/products" => <Products />

동적 라우팅(Dynamic Routing)

정적이지 않은, 동적일 수 있는 경로에 대하여 라우팅을 하는 것.
라우트 경로에 특정 값을 넣어 해당하는 페이지로 이동할 수 있게 하는 것.



url 을 살펴보면 url 마지막에 특정 id 값이 들어가고(/32692, /53424), 해당 id 값에 따라 서로 다른 상세 페이지 정보가 화면에 그려지는 것을 볼 수 있음. id 값에 따라 무수히 많은 url 이 나타날 것이고, 각각의 모든 url 에 대해 미리 경로의 형태와 갯수를 결정할 수 없게 됨.
즉, URL에 들어갈 id를 변수처럼 다뤄야 할 필요성이 생긴 것.

동적인 라우팅을 처리하는 방법

  • Path Parameter

    // Bad
    "/users/1" => <Users id={1} />
    "/users/2" => <Users id={2} />
    "/users/3" => <Users id={3} />
    "/users/4" => <Users id={4} />
    "/users/5" => <Users id={5} />
    
    // Good
    "/users/:id" => <Users /> // useParams().id
    localhost:3000/product/2
    localhost:3000/product/45
    localhost:3000/product/125

라우트 경로 끝에 들어가는 각기 다른 id 값들이 들어감. 2, 45, 125 url 경로에서 달라지는 부분을 저장하는 매개 변수를 Path Parameter 라고 함.
Path Parameter 는 Router 컴포넌트에서 다음과 같이 정의.

<BrowserRouter>
  <Routes>
    <Route path='/product/**:id**' element={<ProductDetail />} />
  </Routes>
</BrowserRouter>

: 는 Path Parameter 가 올 것임을 의미함.
id 는 해당 Path Parameter 의 이름을 의미함. 변수 명을 짓듯이, 임의의 이름을 지정해줄 수 있음. ex) :productId

1. 카드를 클릭하면, onClick 이벤트시 발생하는 navigate 함수를 통해 /product/1 로 이동함.
URL 이 /product/1 로 변하면, Router 컴포넌트에 정의되어 있는 path='/product/:id' 에 따라, ProductDetail 컴포넌트가 마운트 됨.
2. ProductDetail 컴포넌트에서는 백엔드에 id 가 1 인 아이템에 대한 정보를 요청함.
3. 응답으로 받은 정보를 setData 함수를 통해 data 라는 state에 저장하고, 이를 통해 상세 페이지 UI 가 그려짐.

2번 스텝에서, ProductDetail 컴포넌트의 useEffect 훅을 통해 백엔드에 id 가 1 에 해당하는 정보를 요청 함. 그런데, 1 은 URL 에 담겨 있음.(/product/1). ProductDetail 컴포넌트에서는 이것을 어떻게 가져올 수 있을까요?

useNavigate, useLocation, useParams Hook

  • useNavigate Hook
    url 에 담겨있는 id 값을 가져올 수 있음.

    function Product(props) {
      const navigate = useNavigate();
    
      const goToDetail = () => {
        navigate(`/product/${props.id}`);
      }
    
      return (
        <div className="productContainer" onClick={goToDetail}>
        ...
        </div>
      )
    }

    useNavigate 훅을 실행하면 페이지를 이동시키는(url을 변경시키는) 함수를 반환함. 위 예제 코드에서 해당 함수를 navigate 라는 변수에 할당함. 따라서, navigate()와 같은 방식으로 함수를 호출할 수 있음.
    navigate() 함수의 인자에 이동하고자 하는 url(ex. /products)을 전달하면, 해당 url로 화면을 이동함.

    navigate('/product/1'); // '/product/1' 로 이동

    인자에 정수값을 넣어주면 브라우저 방문 기록에 남아있는 경로들을 앞 뒤로 탐색할 수도 있음.

    navigate(-1); // 뒤로 가기
    navigate(-2); // 뒤로 2페이지 가기
    navigate(1);  // 앞으로 가기
  • useLocation Hook

    function ProductDetail(props) {
      const location = useLocation();
      console.log(location);
    
      return (
        ...
      )
    }

    useLocation 훅을 실행하면 경로 정보를 담고 있는 객체 를 반환함. 위 코드에서 해당 객체를 location 이라는 변수에 할당해 줌. location 변수를 콘솔로 출력해 보면 다음과 같은 로그가 출력됨.

    {
      pathname: '/product/1', 
      search: '', 
      hash: '', 
      state: null, 
      key: 'default'
    }

    pathname: 현재 경로 값
    search: 현재 경로의 query parameter 값

  • useParams Hook

    // 현재경로: /product/1
    
    function ProductDetail(props) {
      const params = useParams();
    
      console.log(params);
    
      return (
        ...
      )
    }

    useParams 훅을 실행하면 path parameter 정보를 담고 있는 객체 를 반환함. 위 코드에서 해당 객체를 params 라는 변수에 할당해 줌. params 변수를 콘솔로 출력해 보면 다음과 같은 로그가 출력 됨.

    {
      id: 1
    }

    여기서 id 라는 프로퍼티 키 네임은 Router 에서 :id 로 표기해준 값

    <BrowserRouter>
     <Routes>
       <Route path='/product/**:id**' element={<ProductDetail />} />
     </Routes>
    </BrowserRouter>

    :productId 라고 표기 했다면 다음과 같은 객체가 출력됨

    {
     productId: 1
    }

    useNavigate 훅은 url 를 변경하는 함수 를 반환
    useLocation 훅은 현재 경로 정보를 담고 있는 객체 를 반환
    useParams 훅은 Router 에 등록해준 path parameter 정보를 담고 있는 객체 를 반환

useParams().id

어떻게 URL 에 담겨있는 id 값을 가져올 수 있을까요?
useParams 훅을 이용하여 가져올 수 있음. Path Parameter 로 명시해둔 값은 useParams 훅이 리턴하는 객체에 담기기 때문.

// ProductDetail.js
// current url -> localhost:3000/product/1

function ProductDetail() {
  const params = useParams();

  console.log(params.id) // 1

  return (
    ...
  );	
}

따라서 useEffect 훅에서 해당 id 값을 통해 서버에 요청을 보내는 것을 통해 원하는 정보를 받아올 수 있음.

useEffect(() => {
  fetch(`${API}/${params.id}`)
    .then(res => res.json())
    .then(res => setData(res));
},[]);

정리

지금까지의 과정을 다시 한번 그림으로 정리
동적 라우팅을 구현할 경우 일반적으로 다음과 같은 흐름으로 로직을 구현하게 됨.

  • 리스트 페이지의 개별 상품을 클릭 → navigate("/product/1") 로 상세 페이지로 이동함.

  • 상세 페이지로 이동하면 url은 "http://localhost:3000/product/1" 과 같이 변경되어 있음.

  • 페이지에 필요한 데이터를 useEffect 에서 fetching 함

  • 필요한 id는 URL에 존재하므로 useParams().id 에서 가져올 수 있음.

  • 해당 id를 가지고 백엔드에서 만들어준 API를 호출.

    function ProductDetail() {
      const params = useParams();
    
      useEffect(() => {
        const productId = params.id;
        fetch(`http://123.456.789:8000/products/${productId}`) // 1
          .then(res => res.json())
          .then(res => setData(res));
      },[]);
    
      return (
        ...
      )
    }
  • 서버에서 가져온 데이터(res)를 컴포넌트의 data state 에 저장.

  • state 에 담긴 데이터로 컴포넌트 UI 를 render 해줌.

profile
선명한 기억보다 흐릿한 메모

0개의 댓글