인터랙션

드래그로 순위를 매기는 랭킹 리스트

항목을 끌어 순서를 바꾸면 다른 항목이 부드럽게 비켜주고 순위 배지가 실시간으로 갱신됩니다. 라이브러리 없이 Pointer Events로 구현하고 키보드 이동까지 지원해요.

ReactPointer Events APICSS transformsetPointerCaptureARIA live region
라이브 데모
새 탭에서 열기
데모 불러오는 중…

제작 과정

한 줄 요약

핸들을 끌어 리스트 순위를 재배치하는 컴포넌트 라이브러리 없이 Pointer Events로 만들고, 형제 항목은 transform으로 자리를 비키며, 순위 배지가 실시간 갱신됩니다.

이럴 때 필요해요

할 일 우선순위, 플레이리스트, 대시보드 위젯 순서처럼 "사용자가 직접 순서를 정하는" UI는 흔하지만, HTML5 native drag-and-drop은 모바일 터치에서 동작하지 않고 드래그 이미지 커스터마이징도 까다롭습니다. dnd 라이브러리를 통째로 얹기엔 부담스러운 작은 리스트에, 의존성 0으로 데스크톱터치를 모두 커버하고 싶을 때 이 패턴이 답입니다.

어떻게 동작하나

  1. 핸들에서 pointerdown setPointerCapture로 포인터를 잡아 리스트 밖으로 나가도 이벤트를 계속 받습니다.

  2. pointermove의 이동 거리(dy)를 행 높이로 나눠 목표 인덱스를 계산하고, 끌리는 항목은 포인터를 따라가고 나머지 항목은 translateY로 자리를 비킵니다(트랜지션은 형제에게만).

  3. pointerup 시점에만 배열 순서를 실제로 커밋 화면이 이미 그 모습이라 깜빡임이 없습니다. 순위 배지는 "보이는 순서" 기준으로 매 프레임 다시 매겨집니다.

놓치기 쉬운 것

  • 핸들에 touch-action: none을 줘야 모바일에서 드래그가 스크롤로 가로채이지 않습니다.

  • 드래그 중 DOM 순서를 매번 바꾸면 reflow와 깜빡임이 생깁니다 시각 이동은 transform, 순서 커밋은 드롭 한 번으로 분리하세요.

  • 마우스로만 끌 수 있으면 접근성 미달입니다. 키보드 위아래 이동과 aria-live 안내를 함께 넣어야 합니다.

이런 곳에 써요

  • 할 일체크리스트 우선순위 정렬, 플레이리스트 곡 순서

  • 대시보드 카드위젯 배치 커스터마이징

  • 설문폼 빌더에서 질문 순서 조정

소스 코드

· 데모 페이지에서 자동 추출
import type { Metadata } from "next";
import { DragSortingDemo } from "./-components/DragSortingDemo";

export const metadata: Metadata = {
  title: "드래그 순위 랭킹 (데모)",
  description:
    "항목을 드래그해 순위를 재배치하는 리스트. Pointer Events + 부드러운 자리 비킴 애니메이션 + 순위 배지 실시간 갱신 + 키보드(↑/↓) 이동.",
  robots: { index: false, follow: false },
};

export default function Page() {
  return (
    <main className="flex min-h-[100dvh] items-center justify-center bg-gradient-to-br from-slate-50 via-white to-violet-50/40">
      <DragSortingDemo />
    </main>
  );
}
28조회수

댓글