React useGesture 훅 설계: 부드러운 UI/UX를 위한 제스처 처리 기술
useGesture 훅은 바텀시트, 사이드 드로어 등 다양한 UI 컴포넌트에서 제스처를 처리하기 위한 범용 훅(Hook)으로, 제스처 관련 로직을 훅으로 분리하여 코드의 재사용성과 가독성을 높임
useRef를 활용한 상태 관리를 통해 리렌더링(Re-rendering) 성능 저하 문제를 해결하고, DOM 직접 조작(Direct DOM Manipulation)을 통해 부드러운 UI/UX를 구현
터치(Touch) 및 마우스(Mouse) 이벤트 통합을 위해 이벤트 시스템의 차이점을 고려하여, 각 이벤트에 맞는 핸들러(Handler)를 구현하고, passive 옵션을 적절히 활용하여 스크롤 성능을 최적화
canDragFromScrollable 콜백을 통해 스크롤 영역에서의 드래그(Drag) 충돌 문제를 해결하고, 다양한 엣지 케이스(Edge Case)를 고려하여 훅의 안정성을 확보
useGesture 훅의 핵심 작동 원리
본문은 useGesture 훅의 핵심 원리를 설명하며, 특히 DOMMatrix(DOMMatrix)를 활용하여 브라우저(Browser)가 반환하는 transform 값을 정확하게 계산하는 방법을 제시한다.
DOMMatrix: 브라우저가 반환하는 복잡한 행렬(Matrix) 값을 표준화된 속성으로 접근하도록 돕는 객체로, translateY 값 추출에 필수적
getComputedStyle: CSS 클래스로 적용된 transform 값을 읽어오기 위해 사용되며, 인라인 스타일(Inline Style)에 없는 경우에도 정확한 값을 반환
rAF(requestAnimationFrame): DOM 조작을 브라우저의 렌더링(Rendering) 주기에 맞춰 실행하여, 부드러운 애니메이션(Animation) 구현 및 성능 저하 방지
useGesture 훅의 성능 최적화 기법
useGesture 훅은 성능 최적화를 위해 다양한 기법을 활용하며, 특히 useRef를 이용한 상태 관리와 rAF를 활용한 DOM 업데이트가 핵심이다.
useRef: 상태 변경 시 리렌더링을 발생시키지 않아, 터치(Touch) 이벤트 발생 시 불필요한 렌더링(Re-rendering)을 방지
지수 이동 평균(Exponential Moving Average): 터치 이벤트의 불규칙성을 보정하여, 부드러운 스크롤(Scroll) 동작을 구현
will-change: transform: 드래그(Drag) 중 GPU 레이어(Layer)를 활성화하여, 레이아웃(Layout) 및 페인트(Paint) 과정을 건너뛰어 성능을 향상
터치(Touch)와 마우스(Mouse) 이벤트 통합
본문은 터치(Touch)와 마우스(Mouse) 이벤트를 통합하여, 다양한 환경에서 일관된 제스처(Gesture) 동작을 구현하는 방법을 제시한다.
이벤트 시스템 차이점: 터치 이벤트와 마우스 이벤트의 시작, 이동, 종료 이벤트가 다르므로, 각 시스템에 맞는 핸들러(Handler)를 구현
getClientY 함수: 터치 이벤트와 마우스 이벤트에서 Y 좌표를 추출하는 방식을 통합하여, 코드 중복을 제거
passive 옵션: touchstart 이벤트에는 passive: true를, touchmove 이벤트에는 passive: false를 설정하여, 스크롤(Scroll) 성능을 최적화
useGesture 훅의 스크롤(Scroll) 충돌 해결
useGesture 훅은 스크롤(Scroll) 영역 내에서 드래그(Drag) 동작을 처리하기 위한 로직을 포함하며, 특히 canDragFromScrollable 콜백과 이벤트 제어가 핵심이다.
canDragFromScrollable 콜백: 호출자가 스크롤 영역에서의 드래그 허용 여부를 결정할 수 있도록, 유연성을 제공
이벤트 제어: 스크롤 영역에서 아래로 드래그 시, scrollTop이 0이면 드래그를 허용하고, 그렇지 않으면 스크롤 동작을 유지
마우스 이벤트 차단: 마우스 환경에서 스크롤 영역 내 드래그를 막아, 예상치 못한 동작을 방지
useGesture 훅의 실전 적용 및 엣지 케이스(Edge Case) 처리
본문은 useGesture 훅을 실제 프로젝트에 적용할 때 발생할 수 있는 문제점과 해결 방법을 제시하며, 특히 stale closure 문제와 useEffect 의존성 배열 관리가 중요하다.
stale closure 문제: onDragEnd와 같은 인라인 함수(Inline Function)를 사용할 때, ref를 사용하여 최신 함수를 참조하도록 해결
useEffect 의존성 배열: enabled, targetRef, scrollableRef, handleRef, rubberBand와 같은 의존성(Dependency)이 변경될 때, effect를 재실행하여 최신 값을 반영
엣지 케이스 처리: 다양한 상황에서 발생할 수 있는 버그(Bug)를 예방하기 위해, transform 초기화, touchcancel 처리, scrollTop 소수점 처리 등 꼼꼼한 검증 수행