한 줄 요약
핸들을 끌어 리스트 순위를 재배치하는 컴포넌트 라이브러리 없이 Pointer Events로 만들고, 형제 항목은 transform으로 자리를 비키며, 순위 배지가 실시간 갱신됩니다.
이럴 때 필요해요
할 일 우선순위, 플레이리스트, 대시보드 위젯 순서처럼 "사용자가 직접 순서를 정하는" UI는 흔하지만, HTML5 native drag-and-drop은 모바일 터치에서 동작하지 않고 드래그 이미지 커스터마이징도 까다롭습니다. dnd 라이브러리를 통째로 얹기엔 부담스러운 작은 리스트에, 의존성 0으로 데스크톱터치를 모두 커버하고 싶을 때 이 패턴이 답입니다.
어떻게 동작하나
핸들에서 pointerdown setPointerCapture로 포인터를 잡아 리스트 밖으로 나가도 이벤트를 계속 받습니다.
pointermove의 이동 거리(dy)를 행 높이로 나눠 목표 인덱스를 계산하고, 끌리는 항목은 포인터를 따라가고 나머지 항목은 translateY로 자리를 비킵니다(트랜지션은 형제에게만).
pointerup 시점에만 배열 순서를 실제로 커밋 화면이 이미 그 모습이라 깜빡임이 없습니다. 순위 배지는 "보이는 순서" 기준으로 매 프레임 다시 매겨집니다.
놓치기 쉬운 것
핸들에 touch-action: none을 줘야 모바일에서 드래그가 스크롤로 가로채이지 않습니다.
드래그 중 DOM 순서를 매번 바꾸면 reflow와 깜빡임이 생깁니다 시각 이동은 transform, 순서 커밋은 드롭 한 번으로 분리하세요.
마우스로만 끌 수 있으면 접근성 미달입니다. 키보드 위아래 이동과 aria-live 안내를 함께 넣어야 합니다.
이런 곳에 써요
할 일체크리스트 우선순위 정렬, 플레이리스트 곡 순서
대시보드 카드위젯 배치 커스터마이징
설문폼 빌더에서 질문 순서 조정