이번 글에서는 페이지 라우팅 시 여러 가지 path를 사용하지 않고 하나의 URL의 쿼리 문자열 부분을 조작하여 읽어 라우팅을 하는 useSearchParams
에 대해 작성해보려고 한다.
useSearchParams란?
주로 JavaScript 프레임워크와 라이브러리에서 URL 검색 파라미터를 관리하는 데 사용되는 개념이다.
특히 react와 같은 SPA(Single Page Application)에서 많이 사용된다.
보통의 경우 URL의 쿼리 문자열은 `?`로 시작하여 `&`로 구분되는 키-값
쌍으로 이루어져 있다.
예시로 알아보자
http://localhost:3000/survey/new/?step=1
위 주소는 현재 내가 하고 있는 프로젝트에서 설문 생성하기 페이지 중 1페이지를 가리킨다.
그렇다면 어떤 원리로 문자열을 읽고 해당 페이지로 이동하는지 알아보자.
프로젝트 내 코드
import { useSearchParams } from 'react-router-dom';
import { useEffect } from 'react';
import CreateSurveyPageStep1 from './create-survey-page1';
import CreateSurveyPageStep2 from './create-survey-page2';
import CreateSurveyPageStep3 from './create-survey-page3';
import { SurveyPreviewPage } from './survey-preview-page';
export default function CreateSurveyPage() {
const [searchParams, setSearchParams] = useSearchParams();
const step = searchParams.get('step');
useEffect(() => {
if (!step) {
setSearchParams({ step: '1' });
}
}, [step, setSearchParams]);
let content;
if (step === '1') {
content = <CreateSurveyPageStep1 />;
} else if (step === '2') {
content = <CreateSurveyPageStep2 />;
} else if (step === '3') {
content = <CreateSurveyPageStep3 />;
} else if (step === 'preview') {
content = <SurveyPreviewPage />;
} else {
content = <CreateSurveyPageStep1 />; // Default 값으로 첫 페이지
}
return <>{content}</>;
}
const [searchParams, setSearchParams] = useSearchParams();
useSearchParams
훅을 사용하여 searchParams
와 setSearchParams
를 정의한다.
searchParams
는 URL 쿼리 파라미터의 현재 상태를 나타내고, setSearchParams
는 이 파라미터를 업데이트하는 함수이다.
const step = searchParams.get('step');
여기서 get
개념이 중요하다.
get(name)
: 특정 이름의 첫 번째 값을 반환한다.
따라서 URL의 step 이라는 부분의 첫 번째 값을 반환하다고 보면 된다.
useEffect(() => { if (!step) { setSearchParams({ step: '1' }); } }, [step, setSearchParams]);
useEffect
훅을 사용하여 step
이 설정되어 있지 않으면 step
의 값을 1로 설정한다.
그리고 컴포넌트가 처음 마운트 될 때 실행되는데 step
또는 setSearchParams
가 변경될 때마다 이 효과가 재실행된다.
if (step === '1') { content = <CreateSurveyPageStep1 />; } else if (step === '2') { content = <CreateSurveyPageStep2 />; } else if (step === '3') { content = <CreateSurveyPageStep3 />; } else if (step === 'preview') { content = <SurveyPreviewPage />; } else { content = <CreateSurveyPageStep1 />; // Default 값으로 첫 페이지 }
step
뒤에 어떤 숫자가 나오냐에 따라 렌더링되는 페이지가 달라진다. 물론 default
값은 1페이지다.
마지막으로 렌더링하고자 하는 페이지를return <>{content}</>;
return
해준다.
프로젝트 내 또다른 예시
import { NoResult } from '@/components/home/no-result';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { useCallback, useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { HomePageWrapper } from './home-page.styles';
const HomePage = () => {
const [searchParams, setSearchParams] = useSearchParams();
const [activeTab, setActiveTab] = useState<string>('progress');
useEffect(() => {
const type = searchParams.get('type');
if (type && (type === 'progress' || type === 'complete')) {
setActiveTab(type);
} else {
setSearchParams({ type: 'progress' });
}
}, [searchParams, setSearchParams]);
const handleTabChange = useCallback(
(value: string) => {
setActiveTab(value);
setSearchParams({ type: value });
},
[setSearchParams]
);
return (
<HomePageWrapper>
<Header>
<h1>내 이벤트</h1>
</Header>
<Tabs
style={{ height: 'calc(100% - 6.375rem)' }}
value={activeTab}
onValueChange={handleTabChange}
>
<TabsList>
<TabsTrigger value="progress">진행 중</TabsTrigger>
<TabsTrigger value="complete">진행 완료</TabsTrigger>
</TabsList>
<TabsContent value="progress">
<NoResult />
</TabsContent>
<TabsContent value="complete">
<NoResult />
</TabsContent>
</Tabs>
<FloatingButton />
</HomePageWrapper>
);
};
export default HomePage;
위 예시 또한 useSearchParams
를 사용한 예제이지만, 선택한 Tab에 따라 렌더링되는 컴포넌트(페이지)가 달라진다.
원리는 똑같지만 페이지 라우팅뿐만 아니라 선택한 Tab에 따라 보이는 컴포넌트(페이지)가 달라진다는 것을 알려주고자 예시를 첨부하게 되었다.
아래는 예시에 대한 영상이다.
<video autoplay muted controls>
<source src="[https://velog.velcdn.com/images/kop981020/post/893a8974-2dd9-4d4a-89da-d54f569002a9/image.mov](https://velog.velcdn.com/images/kop981020/post/893a8974-2dd9-4d4a-89da-d54f569002a9/image.mov)" type="video/mp4">
</video>
장점
간편한 상태 관리
useSearchParams
를 사용하면 URL의 쿼리 파라미터를 통해 상태를 관리할 수 있다.
이를 통해 사용자가 페이지를 새로고침하거나 직접 URL을 입력해도 상태를 유지할 수 있다. 예를 들어, 필터링, 정렬, 검색어와 같은 UI 상태를 URL에 저장해두면 사용자가 페이지를 다시 방문할 때 동일한 상태로 페이지를 볼 수 있다.
뒤로 가기/앞으로 가기 지원
SPA(Single Page Application)
에서 브라우저의 뒤로 가기 및 앞으로 가기 버튼을 통해 페이지 상태를 쉽게 탐색할 수 있다. useSearchParams
를 사용하면 상태가 URL에 저장되므로, 사용자가 브라우저의 탐색 기능을 사용할 때 URL에 저장된 상태에 따라 페이지가 적절하게 업데이트된다.
SEO 및 웹 분석
쿼리 파라미터를 통해 검색 엔진 최적화(SEO)를 개선하고 웹 분석 도구에서 유용한 데이터를 수집할 수 있다.예를 들어
, 검색어, 카테고리, 페이지 번호 등을 쿼리 파라미터로 설정하면 웹 분석 도구에서 사용자의 행동을 더 잘 이해할 수 있다.
서버 사이드 렌더링 및 코드 분할
쿼리 파라미터를 사용하면 특정 상태에 따라 필요한 데이터를 서버에서 미리 가져오거나 코드 분할을 통해 특정 컴포넌트만 로드할 수 있다. 이는 페이지 로딩 시간을 줄이고 사용자 경험을 향상시키는 데 도움이 된다.
배운 점
위와 같이 여러 가지 장점들을 살펴봤는데 가장 인상 깊었던 부분은 서버 사이드 렌더링과 검색 엔진 최적화를 개선시킬 수 있다는 것이다. 이전 글에서도 최적화에 관심이 있다고 작성한 부분이 있다. 특히 검색 엔진 최적화는 한 번도 생각해 본 적이 없었기에 더 좋은 경험인 것 같다. 재사용성을 고려한다고 하더라도 페이지 또는 컴포넌트 관리에 유용하다.
'React' 카테고리의 다른 글
Context API 쓰다가 프로젝트 터질 뻔 했습니다 (feat. Zustand) (0) | 2025.03.27 |
---|---|
Lazy Loading (1) | 2024.10.05 |