Advanced Router

Steve·2021년 10월 17일
0

목표

  1. Path parameter와 Query Parameter의 차이점에 대해 설명할 수 있다.
  2. history, location, match 객체의 용도가 무엇인지 설명할수있다.
  3. URL에서 동적인 부분을 변수로 처리할 수 있고, 이를 통해 동적 라우팅 기능을 구현할 수 있다.
  4. offset과 limit개념을 사용하여 페이지네이션 기능을 구현할 수 있다.

라우팅

1-1 경로에 따라 각기 다른 화면 보여주기

route+ing(경로를 찾아가는 행위)

  • 즉, 다른경로(url주소)에 따라 다른 view 보여주는것.

SPA

  • 사용자가 다른뷰로 이동할 때 앱은 뷰를 동적으로 다시 그림.
  • 페이지간 이동시 MPA에 비해 사용자가 느낄수있는 딜레이를 제거해 일반적으로 더 나은 UX를 제공(페이지 전체를 새로고침 하지 않기 때문!)

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

  • 동적인 경로를 처리할 수 있는 방법으로 Path Parameter와 Query Parameter가 있다.
    부모와 자식간의 관계처럼 돼있으면 Path parameter(폴더를 타고 내려가는 느낌)
    product/1
    product아래에 id
    "/search?keyword=위코드" :
    -> search 페이지야, 키워드가 위코드일때 넌 어떻게 생겼니
    에 대한 페이지가 응답
    주소를 불러와서 ex)account?name=yahoo에 있는 값들.
    fetch에 보내는 url에 값들을 추가

path parameter

path parameter는 routes.js에서 아래처럼 정의된다.

<Router>
    <Switch>
       <Route exact path="/products/:id" component={ProductDetail} />
    </Switch>
</Router>

:는 path parameter가 올것임을 알리고, id는 path parameter의 이름을 의미함.변수명 짓든 임의의 값을 넣어줄 수있다. ex) :productId

*history push 못쓰는 경우
-> withRouter HOC 사용해서
Routes.js에 이동경로 직접 안적혀있는 컴포넌트!!( 자식의 자식요소 이런것들 )

this.props.match.params.id <--- 이게 관건
id를 보내주고, 도착한 페이지에서 id를 받아옴. id를 가지고 서버에 요청을하고 받아온 데이터를 setState해서 화면에 보여준다.

Routes.js 의 Route 컴포넌트의 component 프로퍼티에 직접 연결되어 있는 하위 컴포넌트는 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 객체는 페이지 이동을 위한 여러 메서드들을 담고 있습니다. (ex, push)
  • location 객체는 현재 url 경로에 관한 정보를 담습니다.
  • match 객체는 Path Parameter 에 관한 정보를 담습니다.
class ProductDetail extends React.Component {
   ...
   render() {
	    console.log(this.props) // { history: {}, location: {}, match: {}, ... }
      return (
         ...
         <Payment />
      )
   }
}
class Payment extends React.Component {
   ...
   render() {
      console.log(this.props); // {} -> history, location, match 가 없습니다.
      return (
         ...
      )
   }
}

Payment 컴포넌트는 Route 에 연결되어 있지 않기 때문에, history, location, match 객체를 제공받지 못합니다.
하지만, Payment 컴포넌트에서도 세가지 객체를 사용하고 싶을 수 있습니다. 이 경우, 어떻게 할 수 있을까요?

withRouter HOC 가 그 기능을 제공합니다. 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);**

2-4. this.props.match.params.id

다시 돌아와서, 어떻게 URL 에 담겨있는 id 값을 가져올 수 있을까요?

match 객체를 이용하여 가져올 수 있습니다. Path Parameter 로 명시해둔 값은 match 객체에 담기기 때문입니다.

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

class ProductDetail extends React.Component {
	...
	render() {
		**console.log(this.props.match.params.id) // 1**
		return (
			...
		);	
	}
}

따라서 componentDidMount 메서드에서 해당 id 값을 통해 서버에 요청을 보내는 것을 통해 원하는 정보를 받아올 수 있습니다.

componentDidMount() {
	**fetch(`${API}/${this.props.match.params.id}`)**
	.then(res => res.json())
	.then(res => ...);

2-5. 정리

지금까지의 과정을 다시 한번 그림으로 정리해보겠습니다.

동적 라우팅을 구현할 경우 일반적으로 다음과 같은 흐름으로 로직을 구현하게 됩니다.

  • 리스트 페이지의 개별 상품을 클릭
    this.props.history.push("/product/1") 로 상세 페이지로 이동합니다.
  • 상세 페이지로 이동하면 url은 "http://localhost:3000/product/1" 과 같이 변경되어 있습니다.
  • 페이지에 필요한 데이터를 CDM 에서 fetching 합니다.
    • 필요한 id는 URL에 존재하므로 this.props.match.params.id 에서 가져올 수 있습니다.
    • 해당 id를 가지고 백엔드에서 만들어준 API를 호출합니다.
      componentDidMount() {
      	const id = this.props.match.params.id
      	fetch(`http://123.456.123.123:8000/products/${id}`) // 1
      		.then(res => res.json())
      		.then(res => this.setState({ data: res }))
      }
  • 서버에서 가져온 데이터(res)를 컴포넌트의 state 객체에 저장해 줍니다.
  • state 객체에 담긴 데이터로 컴포넌트 UI 를 render 해줍니다.

페이지네이션

프론트 엔드에서 현재의 위치(Offset)과 추가로 보여줄 컨텐츠의 수(Limit)을 백엔드에 넘겨줘야함
현재위치. 거기로부터 몇개.
10개 씩 볼래 Limit 10
30개 씩 볼래 Limit 30
50개 씩 볼래 Limit 50

Query parameter

여러가지 조건들이 합쳐질때는 &표시 해주세욧
ex) product?limit=10&offset=5
product 페이지에서 5로시작해서 10개 가져와라

Query string을 가져올때는 this.props.location.search를 가져오라!
경로가 바뀌는게 아니라 그 페이지 안에서 각기 다른 옵션을 주는것
ex) 가격순, 가격범위 <<-- query string으로 한다 : 그페이지 내에서 옵션을 주는거기 때문
다른 경로로 이동을 하는게 아님.

1. Pagination

이번에는 Pagination(Paging 이라고도 불리는) 기능에 대해 배워보겠습니다.

  • Pagination 예시 컨버스 메인 페이지 하단 인스타그램 영역 (무한 스크롤) 29cm 상품 목록 페이지 영역 (Pagenation)

백엔드에서 가지고 있는 데이터는 많고, 그 데이터를 한 화면에 전부 보여줄 수 없는 경우에 사용됩니다. 모든 데이터를 한번에 보여줄 수 없다면 일정 길이로 끊어서 전달해야할 겁니다.

흔히 게시판의 "이전/다음 페이지"를 끊어 보여주는 기능으로 익숙할 텐데요. 많은 웹사이트에서 널리 사용되고 있는 개념이기에 친숙하게 느끼실 듯 합니다.

프론트엔드에서 현재의 위치(Offset)과 추가로 보여줄 컨텐츠의 수(Limit)를 백엔드에 전달합니다. 백엔드에서는 그에 해당하는 데이터를 끊어 보내주는 방식으로 구현하게 됩니다.

2. Query Parameter

이 과정에서 Query Parameter(혹은, Query String, 쿼리 스트링)를 사용하게 됩니다. 쿼리 스트링이란 말 그대로 해당 엔드포인트에 대해 질의문(query)를 보내는 요청을 뜻합니다.

예를 들어, localhost:8000/product?limit=10&offset=5 라는 주소가 있다고 가정해보겠습니다. API 뒷 부분에 붙어있는 ? 로 시작하는 텍스트가 바로 쿼리스트링 입니다.

?limit=10&offset=5 의 경우, "limit이 10이면서 offset이 5일 경우의 product 페이지를 보여달라" 는 요청으로 해석됩니다.

  • ? 기호는 쿼리스트링의 시작을 알립니다. url 에서 ? 기호는 유일무이 합니다.
  • limit : 한 페이지에 보여줄 데이터 수
  • offset : 데이터가 시작하는 위치(index)
  • parameter=value 로 필요한 파라미터의 값을 적습니다.
  • 파라미터가 여러개일 경우 &를 붙여서 여러개의 파라미터를 넘길 수 있습니다.

3. this.props.location.search

쿼리스트링을 이용한 페이지 네이션 기능 또한 동적 라우팅 기능과 크게 다르지 않습니다. 두 기능의 구현 순서를 비교해보도록 하겠습니다.

동적 라우팅


  1. 리스트 페이지에서 카드를 클릭 합니다.

  2. url 이동을 합니다. 이때, 카드의 고유한 id 값이 url 에 포함됩니다.

  3. 이동한 페이지에서, url 에 담겨있는 id 값을 match 객체를 이용하여 가져옵니다.

  4. 가져온 id 값을 이용하여 데이터를 요청합니다.

    👉 Dynamic Routing & Path Parameter 정리

페이지네이션


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

Path Parameter 에 대한 정보는 match 객체 안에 담겨있었듯이, 쿼리스트링에 대한 정보는 location 객체 안에 담겨있습니다.

**// current url -> localhost:3000/products?offset=10&limit=10**

class ProductList extends React.Component {
   ...
   render() {
      **console.log(this.props.location.search) // ?offset=10&limit=10**
			return (
         ...				
			)
   }
}

따라서 url 에서 쿼리 스트링에 대한 정보를 받아와서, 해당 정보를 통해 데이터를 요청할 수 있습니다.

fetch(`${API}${this.props.location.search}`)
	.then(res => res.json())
	.then(res => ...)

profile
Front-Dev

0개의 댓글