[React] # 13 Router(2)

simoniful·2021년 7월 12일
0

React

목록 보기
13/13
post-thumbnail

SPA인 React는 사용자가 다른 뷰로 이동할 때 애플리케이션은 뷰를 동적으로 다시 그리면서 페이지 전체를 새로고침 하지 않기 때문에 사용자가 느낄 수 있는 딜레이를 제거하여 일반적으로 더 나은 UX를 제공합니다.

앞서 즉 라우팅 이란, 다른 경로(url 주소)에 따라 다른 View(화면)를 보여주는 것이라고 배웠습니다. React는 기본적으로 라우팅 시스템을 갖추고 있지 않으므로 서드-파티 라이브러리의 도움을 받아 기능을 추가하여 구현합니다.


동적 라우팅

지금까지 해온 라우팅 방법으로는 완전히 정해진 경우(정적, static)에 대해서만 경로를 표현 할 수 있었습니다.

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

사이트를 살펴보면 url 마지막에 특정 id 값이 들어가고(/32692), 해당 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
<Router>
  <Switch>
    <Route exact path='/product/:id' component={productDetail} />
  </Switch>
</Router>
// this.props.match.params.id로 접근 가능
// useParams hook으로 동적 라우팅 값으로 걸어둔 이름으로 객체를 가져올 수 있다 

👉🏻 Path tutorial

  1. 카드를 클릭하면, onClick 이벤트시 발생하는 push 함수를 통해 /product/1 로 이동합니다. URL 이 /product/1 로 변하면, Route 컴포넌트에 정의되어 있는 path='/product/:id' 에 따라, ProductDetail 컴포넌트가 마운트 됩니다.

  2. ProductDetail 컴포넌트에서는 백엔드에 id 가 1 인 아이템에 대한 정보를 요청합니다. 페이지에 필요한 데이터를 CDM 에서 fetching 합니다. 필요한 id는 URL에 존재하므로 this.props.match.params.id 에서 가져올 수 있습니다. 해당 id를 가지고 백엔드에서 만들어준 API를 호출합니다.

  3. 응답으로 받은 정보를 setState 함수를 통해 state 에 저장하고, state 객체에 담긴 데이터로 상세 페이지 컴포넌트 UI 를 render 해줍니다.

사용자 브라우저에 입력되는 url 주소와 백엔드에 요청하는 API 주소를 구분해야 합니다. 주소라는 공통점만 있을 뿐, 이 둘은 서로 다른 목적으로 사용됩니다.


Query Parameter

페이지네이션

백엔드에서 가지고 있는 데이터는 많고, 그 데이터를 한 화면에 전부 보여줄 수 없는 경우에 사용합니다. 게시판의 "이전/다음 페이지"를 끊어 보여주는 기능으로 프론트엔드에서 현재의 위치(Offset)과 추가로 보여줄 컨텐츠의 수(Limit)를 백엔드에 전달합니다.

이 때, Query Parameter(Query String)를 사용하게 됩니다. 쿼리 스트링이란 말 그대로 해당 엔드포인트에 대해 질의문(query)를 보내는 요청으로 /product?limit=10&offset=5와 같은 예시로 사용 됩니다.

  • ? 기호는 쿼리스트링의 시작을 알립니다. url 에서 ? 기호는 유일무이 합니다.
  • limit : 한 페이지에 보여줄 데이터 수
  • offset : 데이터가 시작하는 위치(index)
  • parameter=value 로 필요한 파라미터의 값을 적습니다.
  • 파라미터가 여러개일 경우 &를 붙여서 여러개의 파라미터를 넘길 수 있습니다.
// Bad
"/search?keyword=위코드"    : <Search keyword="위코드" />
"/search?keyword=리액트"    : <Search keyword="리액트" />
"/search?keyword=라우팅"    : <Search keyword="라우팅" />
"/search?keyword=쿼리스트링" : <Search keyword="쿼리스트링" />
"/search?keyword=SPA"     : <Search keyword="SPA" />
// Good
"/search?keyword=something" : <Search /> 
// this.props.location.search
// useLocation

👉🏻 Query tutorial


비교

패스파라미터를 통한 상세페이지로 접근 방식과 쿼리스트링을 이용한 페이지 네이션 기능 또한 동적 라우팅 기능과 크게 다르지 않습니다. 두 기능의 구현 순서를 비교해보도록 하겠습니다.

Path parameter 동적라우팅

  1. 리스트 페이지에서 카드를 클릭 합니다.
  2. url 이동을 합니다. 이때, 카드의 고유한 id 값이 url 에 포함됩니다.
  3. 이동한 페이지에서, url 에 담겨있는 id 값을 match 객체를 이용하여 가져옵니다.
  4. 가져온 id 값을 이용하여 데이터를 요청합니다.

Query parameter 페이지네이션

  1. 리스트 페이지에서 버튼을 클릭합니다.
  2. url 이동을 합니다. 이때 url 에는 각 버튼에 해당하는 쿼리스트링이 포함됩니다.
  3. 이동한 페이지에서, url 에 담겨있는 쿼리스트링을 location 객체를 이용하여 가져옵니다.
  4. 가져온 쿼리스트링을 이용하여 데이터를 요청합니다.

history, match, location

React Router 에서 제공하는 history, match, location 객체를 사용하여 위의 id 값을 가져올 수 있습니다. Routes.js 의 Route 컴포넌트의 component props에 직접 연결되어 있는 하위 컴포넌트는 history, location, match 3가지 객체를 props를 통해 제공 받습니다.

// Routes.js
<Route exact path='/product/detail/:id' component={ProductDetail} />
// ProductDetail.js
render() {
  console.log(this.props) 
  // { history: {}, location: {}, match: {}, ... }
  return (
    ...
  );	
}
  • history : 페이지 이동을 위한 여러 메서드
  • location : 현재 url 경로에 관한 정보
  • match : Path Parameter 에 관한 정보

📌 withRouter HOC

직접 Route에 연결되어 있지 않아 history, location, match 객체를 제공받지 못한 경우에도 사용해야하는 경우 withRouter 함수를 통하여 인자로 컴포넌트를 받고, 해당 컴포넌트에 3가지 객체를 추가한 컴포넌트를 반환하는 것이 가능합니다.

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

class Payment extends React.Component {
  render() {
    console.log(this.props); 
    // { history: {}, location:{}, match:{}, ... }
    return(
      ...
    )
  }
}

export default withRouter(Payment);

history, location, match 객체의 다양한 기능

profile
소신있게 정진합니다.

0개의 댓글