/////

맵핑콘솔 필터 상태 보존과 백네비게이션 충돌 방지 패턴

관리자용 맵핑콘솔처럼 접을 수 있는 필터·벌크 편집·백 내비게이션이 공존하는 UI에서는, 필터 상태를 URL 검색 파라미터(search params)에 단일 진실 소스(single source of truth) 로 관리하는 패턴이 가장 안전하다. 이 패턴은 새로고침·탭 공유·북마크·브라우저 뒤로가기를 자연스럽게 처리하지만, 낙관적 업데이트와 필터 상태 변경이 동시에 일어나면 refetch race가 생길 수 있으므로 별도 방어가 필요하다. ---

/////

Summary#

관리자용 맵핑콘솔처럼 접을 수 있는 필터·벌크 편집·백 내비게이션이 공존하는 UI에서는, 필터 상태를 URL 검색 파라미터(search params)에 단일 진실 소스(single source of truth) 로 관리하는 패턴이 가장 안전하다. 이 패턴은 새로고침·탭 공유·북마크·브라우저 뒤로가기를 자연스럽게 처리하지만, 낙관적 업데이트와 필터 상태 변경이 동시에 일어나면 refetch race가 생길 수 있으므로 별도 방어가 필요하다.


Key Points#

1. URL Search Params를 상태로 취급하라#

  • URL 검색 파라미터는 “2등 상태”가 아니라 직렬화·공유·북마크가 가능한 정식 상태다.
  • TanStack Router의 validateSearch와 스키마 검증(Zod 등)을 라우트 정의에 묶으면 search params의 shape을 라우트 단위에서 통제할 수 있다.
  • 필터 입력처럼 잦은 변경은 대체로 replace를 사용해 히스토리 오염을 줄이고, 상세 진입/목록 복귀처럼 사용자가 의미 있는 이동으로 인식하는 순간에는 push를 사용한다.

2. TanStack Table ↔ URL 양방향 동기화#

  • tanstack-table-search-params(taro-28/tanstack-table-search-params)는 TanStack Table 상태를 라우터의 search params와 연결하는 서드파티 라이브러리다.
  • 주요 대상 상태는 globalFilter, columnFilters, sorting, pagination 등이며, 맵핑콘솔의 접이식 필터 패널과 잘 맞는다.
  • URL이 변하면 라우터가 search params를 갱신하고 테이블이 재렌더되는 구조가 되므로, 일반적인 뒤로가기에는 별도 popstate 핸들러를 만들지 않는 편이 낫다.

3. 콜랩시블 필터와 URL 상태의 경계#

  • 필터 패널의 열림/닫힘 같은 UI 전용 상태는 URL에 넣지 말고 로컬 상태로 유지한다.
  • 실제 필터 값만 URL에 직렬화한다.
  • 패널이 닫혀 있어도 URL 파라미터가 존재하면 필터가 활성화되어 있음을 뱃지나 요약 칩으로 표시해야 한다.
  • paramNames 같은 옵션을 사용하면 기존 쿼리스트링 키와 충돌하지 않게 점진적으로 마이그레이션할 수 있다.

4. 낙관적 업데이트 + 벌크 편집의 Race Condition 실패 모드#

벌크 편집 후 목록이 엉키는 대표 시나리오:

단계 실패 모드
Mutation A 완료 후 refetch 발생 Mutation B가 아직 in-flight인 상태일 수 있다.
refetch 응답이 Mutation B보다 먼저 도착 서버의 이전 응답이 B의 낙관적 업데이트를 덮어쓴다.
현재 필터가 category=X인데 항목을 category=Y로 변경 클라이언트가 서버 필터링 로직을 복제하지 않으면 목록 포함 여부가 흔들린다.

TanStack Query 기준 방어 패턴:

  1. onMutate에서 queryClient.cancelQueries(queryKey)로 진행 중인 refetch를 취소한다.
  2. onMutate에서 이전 스냅샷을 저장하고, onError에서 setQueryData(queryKey, snapshot)으로 롤백한다.
  3. onSettled에서 무조건 invalidate하지 말고, 같은 mutation 범위에 대해 다른 mutation이 남아 있는지 확인한다.
  4. queryClient.isMutating({ mutationKey }) === 1처럼 mutationKey로 범위를 좁혀 “자기 자신만 남은 상태”일 때만 invalidation한다.
  5. mutationKey 없이 전역 isMutating()만 사용하면 무관한 mutation이 필요한 invalidation을 막아 stale UI를 만들 수 있다.

5. 벌크 편집 후 필터 선택 충돌 방지#

  • 벌크 편집 완료 후 “현재 필터 조건을 더 이상 만족하지 않는 항목”이 목록에 남을 수 있다.
  • 이 경우 클라이언트에서 서버 필터 로직을 재구현하기보다 서버 응답을 권위 소스로 삼아 invalidation + refetch로 수렴시키는 편이 안전하다.
  • 벌크 편집 중에는 필터 변경을 잠시 비활성화하거나, 편집 완료 후 필터 재적용/목록 새로고침을 명시적으로 트리거하면 충돌 창을 줄일 수 있다.
  • react-admin 계열 화면에서는 동일 resource의 여러 list view가 상태를 공유할 수 있으므로, 버전에 맞춰 storeKey 사용 여부를 확인하고 필요하면 고유 storeKey 또는 persistence 비활성화 옵션으로 목록 상태 오염을 격리한다.

Cautions#

  • replace vs push는 제품 UX 정책이다. 필터 입력마다 push하면 뒤로가기 스택이 오염되고, 반대로 모든 이동을 replace하면 사용자가 기대하는 목록 복귀가 깨질 수 있다.
  • Zod/Standard Schema 호환성은 버전 의존적이다. 사용하는 TanStack Router·Zod 버전을 기준으로 어댑터 필요 여부를 확인한다.
  • tanstack-table-search-params는 공식 TanStack 패키지가 아니다. 프로덕션 도입 전 유지보수 상태, malformed URL 파라미터 처리, 라우터별 지원 범위를 확인한다.
  • isMutating()은 범위를 좁혀 사용한다. 전역 카운트만 보면 무관한 mutation 때문에 필요한 invalidation이 생략될 수 있다.
  • 서버 필터링 로직을 클라이언트에 복제하지 말라. 낙관적 업데이트에서 목록 포함 여부까지 예측하려면 서버 로직을 미러링해야 하며, 이는 유지보수 부채가 된다.
  • react-admin의 URL/store persistence 이슈는 버전별로 확인한다. 과거 issue 하나를 일반 규칙으로 고정하지 말고, 현재 사용 중인 react-admin 버전의 storeKey, URL sync, list params persistence 동작을 기준으로 테스트한다.

Sagwan Revalidation 2026-05-25T01:12:53Z#

  • verdict: ok
  • note: URL 상태·TanStack Query 방어 패턴 모두 최근 practice와 부합함

Sagwan Revalidation 2026-05-26T01:15:04Z#

  • verdict: ok
  • note: URL 상태·TanStack Router/Table·Query race 방어 패턴 모두 현재도 유효함

Sagwan Revalidation 2026-05-27T01:55:01Z#

  • verdict: ok
  • note: [chatgpt 오류] The read operation timed out

Sagwan Revalidation 2026-05-28T02:29:21Z#

  • verdict: ok
  • note: URL 상태화·TanStack Router/Table/Query 권장 패턴 모두 현재도 유효함

Sagwan Revalidation 2026-05-29T03:03:28Z#

  • verdict: ok
  • note: URL 상태·TanStack Query race 방어 패턴 모두 현재 practice와 부합함

Sagwan Revalidation 2026-05-30T03:35:43Z#

  • verdict: ok
  • note: URL 상태·TanStack Router/Query 권장 패턴이 현재도 유효합니다.

Sagwan Revalidation 2026-05-31T04:08:42Z#

  • verdict: ok
  • note: URL 상태·TanStack 패턴과 race 방어 권장안이 현재도 유효함

Sagwan Revalidation 2026-06-01T07:14:39Z#

  • verdict: ok
  • note: 전날 검증 이후 핵심 주장과 권장 패턴을 바꿀 만한 변화가 없다.

Sagwan Revalidation 2026-06-02T08:09:32Z#

  • verdict: ok
  • note: URL 상태·TanStack Query 방어 패턴 모두 현재 practice와 충돌 없음

Sagwan Revalidation 2026-06-03T09:00:14Z#

  • verdict: ok
  • note: URL 상태·TanStack Router/Table/Query 권장 패턴이 여전히 유효합니다.

Sagwan Revalidation 2026-06-04T09:29:26Z#

  • verdict: ok
  • note: URL 상태·TanStack Router/Query 패턴 모두 현재 practice와 부합함

Sagwan Revalidation 2026-06-05T09:48:23Z#

  • verdict: ok
  • note: 전날 검증 이후 관련 TanStack Router/Table 관행 변화 징후가 없다.

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1