doksam-ui
홈ProfilesTokensIconsComponentsPatternsTemplatesRules
Patterns

리스트 컨트롤 패턴

URLSearchParams 기반 탭·필터·페이지네이션으로 SSR 상태를 유지하는 목록 컨트롤입니다.

#1

URL 탭 + 검색 필터 + 페이지네이션

탭·검색·페이지 상태를 모두 URLSearchParams 하나로 관리해, 새로고침·공유·뒤로가기에서도 같은 결과를 SSR로 재현할 수 있는 목록 컨트롤입니다.

  • 설치 가이드2026-07-01
  • 환경 변수 설정 가이드2026-06-29
  • v3.2 업데이트 노트2026-06-27
  • 정기 점검 공지2026-06-25
  • Previous
  • 1 / 3
  • Next

결과 URL: /

function buildQuery(params: { type: string; q: string; page: number }) {
  const sp = new URLSearchParams()
  if (params.type) sp.set("type", params.type)
  if (params.q) sp.set("q", params.q)
  if (params.page > 0) sp.set("page", String(params.page))
  const qs = sp.toString()
  return qs ? `?${qs}` : ""
}

// 서버 컴포넌트: searchParams prop이 URL과 항상 동기화된 단일 진실원천이다.
export default async function Page({ searchParams }: { searchParams: Promise<Record<string, string>> }) {
  const sp = await searchParams
  const items = await fetchItems({ type: sp.type, q: sp.q, page: Number(sp.page ?? 0) })
  return <List items={items} params={sp} />
}
  • 탭(필터 축)이 바뀌면 이전 페이지 번호가 더 이상 유효하지 않을 수 있으므로 page 파라미터를 항상 0(1페이지)으로 되돌린다.
  • 값이 기본값(전체 탭·빈 검색어·1페이지)이면 해당 파라미터 자체를 URL에서 제거해 쿼리스트링을 짧게 유지한다.
  • 실서비스에서는 버튼 onClick 대신 <Link href={buildQuery(...)}>로 렌더해 실제 페이지 이동 + 서버 컴포넌트 재조회가 일어나게 한다.
#2

상태 → 쿼리스트링 매핑

탭·검색어·페이지 조합이 실제로 어떤 URL로 직렬화되는지 보여주는 예시입니다. 같은 buildQuery 함수 하나로 세 컨트롤의 href를 모두 만든다.

  • 탭=전체, 검색=없음, 페이지=1/
  • 탭=가이드, 검색=없음, 페이지=1/?type=guide
  • 탭=가이드, 검색="설정", 페이지=1/?type=guide&q=%EC%84%A4%EC%A0%95
  • 탭=가이드, 검색="설정", 페이지=2/?type=guide&q=%EC%84%A4%EC%A0%95&page=1
buildQuery({ type: "", q: "", page: 0 })                 // "" (기본값 → 루트 경로)
buildQuery({ type: "guide", q: "", page: 0 })             // "?type=guide"
buildQuery({ type: "guide", q: "설정", page: 0 })          // "?type=guide&q=설정"
buildQuery({ type: "guide", q: "설정", page: 1 })          // "?type=guide&q=설정&page=1"
  • 탭·필터·페이지네이션 3개 컨트롤이 각자 URL을 조립하지 않고, 하나의 buildQuery 함수를 공유해 직렬화 규칙을 한 곳에 둔다.
  • 빈 값/기본값은 파라미터를 생략하므로, 같은 목록이라도 조건이 적을수록 짧고 읽기 쉬운 URL이 된다.