728x90
반응형
정리
searchParams vs useSearchParams
특징 | searchParams | useSearchParams |
사용 환경 | 서버 컴포넌트 | 클라이언트 컴포넌트 |
선언 방식 | props로 자동 전달 | React Hook으로 import |
데이터 형태 | 일반 객체 | URLSearchParams 객체 |
사용 방법 | searchParams.category | searchParams.get('category') |
변경 감지 | 페이지 새로고침 시 | 실시간 (자동 갱신) |
주 사용 목적 | 초기 데이터 로딩, SEO | 동적 필터링, 실시간 업데이트 |
params vs usePathname
특징 | params | usePathname |
사용 환경 | 서버 컴포넌트 | 클라이언트 컴포넌트 |
선언 방식 | props로 자동 전달 | React Hook으로 import |
반환 값 | 동적 라우트 파라미터 객체 | 전체 경로 문자열 |
사용 예시 | params.slug | pathname (전체 경로) |
주요 용도 | 동적 라우팅 처리 | 현재 경로 기반 UI 업데이트 |
데이터 범위 | 동적 세그먼트만 포함 | 전체 URL 경로 반환 |
쿼리 파라미터 관리하기
1. searchParams prop 사용
// app/teams/page.tsx
export default function TeamsPage({
searchParams,
}: {
searchParams: { filter: string; sort: string }
}) {
return (
<div>
<h1>팀 목록</h1>
<p>필터: {searchParams.filter}</p>
<p>정렬: {searchParams.sort}</p>
</div>
);
}
2. useSearchParams 훅 활용 (클라이언트 컴포넌트)
// components/TeamFilter.tsx
'use client';
import { useSearchParams } from 'next/navigation';
export default function TeamFilter() {
const searchParams = useSearchParams();
const filter = searchParams.get('filter');
return (
<div>
<h2>현재 필터</h2>
<div className="filter-status">
{filter === 'active' ? '활성 팀만 보기' : '모든 팀 보기'}
</div>
</div>
);
}
경로 정보 다루기
1. params 사용 (서버 컴포넌트)
// app/products/[category]/page.tsx
export default function CategoryPage({
params,
}: {
params: { category: string }
}) {
return (
<div>
<h1>{params.category} 카테고리</h1>
<ProductList category={params.category} />
</div>
);
}
2. usePathname 사용 (클라이언트 컴포넌트)
// components/Navigation.tsx
'use client';
import { usePathname } from 'next/navigation';
export default function Navigation() {
const pathname = usePathname();
return (
<nav>
<Link
href="/"
className={pathname === '/' ? 'active' : ''}
>
홈
</Link>
<Link
href="/products"
className={pathname.startsWith('/products') ? 'active' : ''}
>
제품
</Link>
</nav>
);
}
예시
1. 필터링과 정렬이 있는 제품 목록
// app/products/page.tsx
import { ProductList } from '@/components/ProductList';
export default function ProductsPage({
searchParams,
}: {
searchParams: {
category?: string;
sort?: string;
page?: string;
}
}) {
return (
<div className="products-page">
<ProductList
category={searchParams.category}
sort={searchParams.sort}
page={searchParams.page}
/>
</div>
);
}
2. 동적 필터 컴포넌트
// components/ProductFilter.tsx
'use client';
import { useSearchParams, useRouter } from 'next/navigation';
export default function ProductFilter() {
const router = useRouter();
const searchParams = useSearchParams();
const updateFilter = (category: string) => {
const params = new URLSearchParams(searchParams.toString());
params.set('category', category);
router.push(`/products?${params.toString()}`);
};
return (
<div className="filter-controls">
<button onClick={() => updateFilter('electronics')}>
전자기기
</button>
<button onClick={() => updateFilter('clothing')}>
의류
</button>
</div>
);
}
주의사항과 모범 사례
1. 레이아웃에서의 쿼리 파라미터 접근
// ❌ 잘못된 사용
// app/layout.tsx
export default function Layout({ children }) {
// 레이아웃에서 직접 쿼리 파라미터 접근 불가
const searchParams = useSearchParams(); // 에러 발생!
return <div>{children}</div>;
}
// ✅ 올바른 사용
// 필요한 정보를 자식 컴포넌트로 전달
export default function Layout({ children }) {
return (
<div>
{children}
</div>
);
}
2. 성능 최적화
// components/ProductList.tsx
'use client';
import { useCallback } from 'react';
import { useSearchParams } from 'next/navigation';
export default function ProductList() {
// searchParams 변경 감지를 위한 메모이제이션
const getFilteredProducts = useCallback(async () => {
const searchParams = useSearchParams();
const filter = searchParams.get('filter');
// 필터링 로직
}, []);
return <div>{/* 제품 목록 렌더링 */}</div>;
}
결론
Next.js의 레이아웃 유지 기능은 성능을 최적화하지만, 쿼리 파라미터와 경로 정보를 올바르게 관리하는 것이 중요합니다. searchParams와 useSearchParams, params와 usePathname을 적절히 활용하여 최신 상태를 유지하면서도 효율적인 애플리케이션을 구축할 수 있습니다.
728x90
반응형
'개발 공부 > Next.js' 카테고리의 다른 글
Request Waterfall / Static Rendering / Parallel Data Fetching (0) | 2025.01.07 |
---|---|
데이터 페칭 방법 선택하기 (0) | 2025.01.06 |
Link 컴포넌트를 이용한 네비게이션 최적화 (2) | 2025.01.02 |
Next.js Layout 이해하기 (0) | 2025.01.01 |
Next.js의 이미지 최적화 (0) | 2024.12.31 |