- 동적 라우팅(Dynamic Routing)의 개념에 대해서 설명할 수 있다.
- 컴포넌트에서 Path Parameter를 가져와 활용할 수 있다.
- 쿼리 스트링(Query String)의 개념과 형태에 대해서 설명할 수 있다.
- 컴포넌트 내에서 URL의 쿼리 스트링을 가져와 활용할 수 있다.
-/post/1
, /post/2
처럼 1, 2와 같은 숫자까지 포함해서 URL의 전체 형태를 미리 정의하는 것이 아닌,/post/
로 시작하는 모든 URL은 상세페이지로 연결되게 설정
:
기호를 활용경로/:문자열
형태로 path를 설정하면 URL에서 경로/
뒤에 무슨 글자가 오든 이 Route로 연결:
기호 뒤에 붙는 id 와 같은 문자열이 path parameterimport React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
export default function Router() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<ListComponent />} />
<Route path="/post/:id" element={<DetailPageComponent />} />
</Routes>
</BrowserRouter>
);
}
path parameter는 URL에 있는 값을 마치 매개변수(parameter)처럼 사용
똑같은 함수에 다른 매개변수를 통해서 다양한 결과를 낼 수 있는 것처럼 path parameter를 통해서 큰 틀은 동일하되 다른 UI를 보여주도록 처리할 수 있다.
Route의 path prop에 경로/:문자열
을 넣어줘야 한다고 했다. 이때 문자열 자리에 작성되는 것이 바로 path parameter의 이름
react-router-dom에서는 useParams hook을 제공
useParams hook은 path parameter의 값을 편하게 가져올 수 있게 해주며, state처럼 path parameter의 값이 바뀌면 컴포넌트를 리렌더링 해주는 기능 제공
useParams hook을 호출하면 path params의 값을 객체 형태로 반환.
이때 객체의 프로퍼티의 key는 Route에서 설정한 path parameter의 이름이며 value는 path parameter에 실제로 전달된 값.
즉 블로그 애플리케이션에서는 path parameter의 이름을 id로 지정을 했기 때문에 post/1
로 접속했다면 useParams hook의 return 값은 {id: 1}
이 되는 것
mport { useParams } from 'react-router-dom';
const params = useParams();
/list
페이지로 유저가 접속했을 때 상품이 1억개하면 1억개의 상품 동류를 모두 보여주는 것은 비효율 적
1억개의 상품 정보를 모두 가져와야하기 때문에 오래걸리고, 실제 유저는 판매량순으로 10개, 최신순으로 10개, 리뷰평점순으로 10개처럼 더 정렬되고 특정된 형태의 정보를 보고싶어하기 때문
우리는 단순히 "상품리스트를 보여줘"가 아닌 "상품 리스트를 최신순으로 상위 10개만 보여줘"처럼 구체적으로 요청할수 있어야 하고 이때 활용하는 것이 쿼리스트링이다.
(출처: https://www.semrush.com/)
이름 그대로 문자열 형태, key=value로 표현됨
페어갯수 제한 없음
https://www.example.com/products?sort=popular
이 예시에서 정렬 기준을 나타내는 sort 외에 데이터를 오름차순 또는 내림차순으로 표시할지에 대한 정보인 정렬 방향에 대한 정보를 추가로 포함한다면
https://www.example.com/products?sort=popular&direction=desc
와 같이 표현해서 여러 개의 key=value 페어가 포함된 형태로 쿼리스트링을 만들 수 있다.
<Link to="/list?sort=popular" />
, navigate("/list?sort=popular")
처럼 단순하게 Link
컴포넌트나 navigate
함수의 인자에 쿼리 스트링이 포함된 URL을 전달해주면 됨.useLocation
, useSearchParams
react-router-dom에서는 쿼리 스트링의 값을 편하게 가져올 수 있는 hook 들을 제공. 이 hook 들을 이용하면 쿼리 스트링의 값을 편하게 가져올 수 있으며, state처럼 쿼리 스트링의 값이 바뀌면 컴포넌트를 리렌더링 해주는 기능을 제공
💻 useLocation hook
현재 Location 객체를 리턴
Location 객체는 말 그대로 현재 위치(URL)에 포함된 여러 가지 정보를 가지고 있고 각각의 정보를 pathname, search, hash, state, key 등의 프로퍼티로 표현(Location 객체의 state 프로퍼티는 React의 state와는 다름)
쿼리 스트링을 나타내는 프로퍼티는 search
Location 객체의 search 프로퍼티에는 URL 중 쿼리 스트링에 대한 정보가 문자열 형태로 저장되어 있다. 이를 활용해서 쿼리 스트링의 값을 획득하고 사용
// src/List.js
import React from 'react';
import { useLocation } from 'react-router-dom';
const List = () => {
const location = useLocation();
const queryString = location.search;
return (
<section>
<h1>This is List Page</h1>
<p>
쿼리 스트링: <b>{queryString}</b>
</p>
</section>
);
};
export default List;
다만!
전체 쿼리 스트링을 하나의 문자열 형태(?sort=popular
)로 표현해 주기에 이 중에서 원하는 값만 가져오려면 저 문자열을 자바스크립트를 통해서 Parsing 하는 과정을 거쳐야 한다. 예를 들어 위 쿼리 스트링에서 sort의 값을 얻어내고자 한다면 ?
를 문자열에서 제거하고, sort
문자열을 찾아내고, =
뒤에 위치한 값을 최종적으로 꺼내오는 과정을 거쳐야지만 최종으로 원한 결과값인 popular를
획득할 수 있다.
지금은 쿼리 스트링에서 하나의 key=value
페어밖에 존재하고 있지 않지만, 만약 여러 개의 key=value
페어가 존재해서 &
가 추가된다면 이 과정은 더 복잡해질 것.
또한, 만약 하나의 key
값에 여러 value
를 표현하고 있는 형태(?sort=popular&sort=latest
)의 쿼리 스트링에서 배열의 형태로 sort=["popular", "latest"]
같이 값을 추출하고자 한다면 더더욱 복잡해질 것.
이러한 과정을 거치지않고 원하는 값만 얻을 수 있도록 다양한 메서드를 제공해주는 URLSearchParams라는 객체가 있고
react-router-dom에서는 쿼리 스트링의 값을 이용해서 URLSearchParams 객체를 리턴해주는 useSearchParams
라는 hook을 제공
💻 useSearchParams hook
useSearchParams hook을 호출하면 useState와 비슷하게 배열의 형태로 searchParams와 setSearchParams 함수를 리턴
searchParams는 URLSearchParams 객체이며 URLSearchParams 객체는 쿼리 스트링을 다루기 위한 여러 편리한 메서드를 제공
setSearchParams는 함수를 호출하면서 인자로 객체 또는 문자열을 넣어주면 현재 URL의 쿼리 스트링을 변경하는 기능을 제공
const [searchParams, setSearchParams] = useSearchParams();
1. 값을 읽어오는 메서드
searchParams.get(key)
: 특정한 key의 value를 가져오는 메서드.
원하는 쿼리 스트링의 key를 인자로 넣어서 메서드를 호출하면 해당 key에 부합하는 value가 리턴.
searchParams.getAll(key)
: 특정한 key에 부합하는 value가 두 개 이상일 경우 라면 get
메서드는 제일 먼저 나온 value만 리턴.
만약 모든 value 값들을 얻고 싶다면 getAll
메서드를 이용. getAll 메서드는 해당 key에 해당하는 모든 value를 배열의 형태 리턴.
?sort=popular&sort=latest
의 경우
searchParams.get("sort")
의 리턴값:"popular"
searchParams.getAll("sort")
의 리턴값:["popular","latest"]
searchParams.toString()
: 쿼리 스트링을 string 형태로 리턴.
searchParams
는 객체이기 때문에 여기서 가공되지 않은 쿼리 스트링의 값을 그대로 얻고 싶다면 toString 메서드 호출.
?sort=popular&sort=latest
의 경우
searchParams.toString()
의 리턴값:"?sort=popular&sort=latest"
2. 값을 변경하는 메서드
searchParams.set(key, value)
: 메서드를 호출하면서 인자로 전달한 key 값을 value로 설정하는 메서드. 만약 동일한 key에 여러 value가 이미 존재하고 있었다면, set 메서드를 호출하면서 설정한 값 외에는 삭제.
?sort=popular&sort=latest
의 경우
searchParams.set("sort", "clear")
호출
searchParams.toString()
의 리턴값:"?sort=clear"
searchParams.append(key, value)
: 메서드를 호출하면서 인자로 전달한 key 값을 value로 추가하는 메서드. set 메서드와는 다르게 기존의 값들을 변경하거나 삭제하지 않고 추가하는 방식으로 동작.
?sort=popular&sort=latest
의 경우
searchParams.append("sort", "clear")
호출
searchParams.toString()
의 리턴 값:"?sort=popular&sort=latest&sort=clear"
searchParams를 변경하는 메서드를 이용해서 searchParams의 값을 변경하더라도 실제 URL의 쿼리 스트링은 변경되지 않음. 변경된 searchParams를 이용해서 실제 쿼리 스트링을 변경시키려면 setSearchParams 함수에 searchParams를 인자로 전달하면서 호출해야함.
// src/List.js
// URL: /list?sort=popular&sort=latest
import React from 'react';
import { useSearchParams } from 'react-router-dom';
const List = () => {
const [searchParams, setSearchParams] = useSearchParams();
const setSortParams = () => {
searchParams.set('sort', 'clear');
setSearchParams(searchParams);
};
const appendSortParams = () => {
searchParams.append('sort', 'hello-world');
setSearchParams(searchParams);
};
return (
<section>
<h1>This is List Page</h1>
<p>
toString: <b>{searchParams.toString()}</b>
</p>
<p>
get("sort"): <b>{searchParams.get('sort')}</b>
</p>
<p>
getAll("sort"):
{searchParams.getAll('sort').map((value) => (
<b key={value}>{value} </b>
))}
</p>
<button onClick={setSortParams}>setSortParams</button>
<button onClick={appendSortParams}>appendSortParams</button>
</section>
);
};
export default List;