프론트엔드

Threshold Slider Filter

프론트엔드

Threshold Slider Filter — 실전 적용 구조와 코드 예시

언제 쓰나 · 사용자가 "얼마 이상만 보기" / "반경 N km 이내만" 같은 수치 임계값을 즉시 바꾸면서 결과를 확인하고 싶을 때 · 슬라이더 드래그 중에 매 프레임 서버 요청을 보내면 안 될 때 (디바운스 필요) · UI 반응성(값 표시)과 서버 부하(fetch) 를 분리해서 최적화해야 할 때

#frontend#Threshold#Slider#Filter
다운로드
# Threshold Slider Filter

## 언제 쓰는가
- 사용자가 "얼마 이상만 보기" / "반경 N km 이내만" 같은 수치 임계값을 즉시 바꾸면서 결과를 확인하고 싶을 때
- 슬라이더 드래그 중에 매 프레임 서버 요청을 보내면 안 될 때 (디바운스 필요)
- UI 반응성(값 표시)과 서버 부하(fetch) 를 분리해서 최적화해야 할 때

## 핵심 구조
- **이중 상태 분리**:
  - UI 상태(슬라이더 position): `onChange`에 즉시 업데이트 → 숫자 표시도 즉시 반영
  - 서버 파라미터: `useEffect` + `setTimeout(300ms)`로 디바운스 후 반영
- **반응형 레인지**: `<input type="range" min max value accent-primary>` 로 네이티브 사용, 값 라벨은 `tabular-nums` 폰트로 폭 고정
- **단위 표기**: min/max가 의미를 가지면 label에 단위 표시 (예: "회", "km")
- **명시적 최소/최대**: 코드 상수로 한계값을 정의해 UI/서버 양쪽에서 동일 범위 사용
- **컨테이너 책임**: 슬라이더는 prop으로 값/onChange만 받는 pure 컴포넌트, 디바운스는 컨테이너의 useEffect에 둠

## 코드 예시
```jsx
// FilterBar.jsx (pure)
<div className="flex items-center gap-2">
  <span>Min count</span>
  <input
    type="range" min={2} max={10} value={minCount}
    onChange={(e) => onMinCountChange(parseInt(e.target.value, 10))}
    className="w-24 accent-primary"
  />
  <span className="font-mono tabular-nums w-5">{minCount}</span>
</div>

// Container.jsx (debounced refetch)
useEffect(() => {
  const h = setTimeout(() => {
    fetch(`/api/data?minCount=${minCount}`).then(...)
  }, 300)
  return () => clearTimeout(h)
}, [minCount])
```

## 주의사항
- 디바운스 시간은 보통 200~400ms. 너무 짧으면 드래그 중 과도한 요청, 너무 길면 "응답이 느리다"는 체감
- 슬라이더 min이 0이 되면 "의미 없음/전체"로 해석되기 쉬운데 서버가 이를 어떻게 처리할지 일관 정의할 것 (예: 0 = "전체"로 매핑)
- 디바운스 유실 방지: AbortController로 이전 요청 취소 병행 권장
- 모바일 터치 이벤트에서 step 크기가 너무 작으면 조작이 어려움. `step` 명시하고 단계 수를 5~10 이내로 제한
- 접근성: 숫자 라벨 옆에 `aria-label`로 현재 값 제공. 키보드 ←→ 조작을 가정하고 min/max 간격을 너무 넓게 잡지 말 것

## 재사용 방법
1. 슬라이더 JSX 블록을 그대로 복사, min/max/label만 교체
2. 컨테이너에 `useEffect` + setTimeout 디바운스 블록 추가
3. 서버 엔드포인트에서 `parseInt + clamp` 로 범위 외 값 방어
4. 참고 구현: `Obsidian_manage/src/components/growth/patterns/PatternFilterBar.jsx`의 `Min count` 슬라이더, `PatternsView.jsx`의 useEffect debounce
jt · v1 · CC0-1.0 · 복사 0