React DnD Tips & Tricks

Channel Talk

  • 테크 인사이트

React DnD 글을 쓰게 된 계기

React DnD는 아이템 간의 순서 변경 등 드래그 액션이 편리한 UX를 만들 수 있는 환경에서 사용됩니다. 아래는 채널톡에서 React DnD를 사용하는 예시입니다.

React DnD를 프로덕트에서 녹여서 사용할때 마주할 수 있는 문제에 대해서 한국어로 된 아티클이 꽤 부족하다고 느꼈습니다. React DnD를 오랫동안 사용했고, 최근에 채널톡에서 JS 기반의 Class Component를 TS 기반의 Functional Component로 마이그레이션하면서 이에 대한 정리가 필요하다고 생각했습니다. Legacy HoC API와 Hooks API를 전부 사용한 사용자 입장에서 짧은 팁을 남깁니다.

React DnD를 선택한 이유

다른 라이브러리와 사용량 비교

Source:

npm trends

react-beautiful-dnd는 UI/UX나 퍼포먼스가 좋은 동작이 predefined 되어있는 것이 특징입니다. React DnD의 경우에는 hover중일때 순서가 변경되는 애니메이션이나 위치 변경을 직접 정의하여야 합니다. react-beautiful-dnd는 특히 애니메이션이나, 어느 좌표부터 순서를 변경할 지 결정하는 로직이 잘 구성되어있는데, 이 Article을 보면 잘 알 수 있습니다.

아쉽게도 react-beautiful-dnd는 React DnD보다 용량이 약 2배 많고, 처음 도입할 시점(2년 전)에는 React DnD보다 커스터마이징할 수 있는 폭이 적었기에 선택지가 되지 못했지만, 지금 새로 도입한다면 충분히 선택을 고려할 수 있을 것 같습니다.

react-draggable은 드래그로 어떠한 아이템 간의 순서 변경 측면보다, 윈도우즈에서 윈도우를 드래그해서 위치를 바꾸는 부분에서 강점이 있는 라이브러리로 보여집니다. 따라서 고려되지 못했습니다.

아래는 React DnD의 사용 예시입니다.

JavaScript

Class Component에서와 Functional Component에서 사용할 때의 차이

Class Component에서는 HoC 형태, Functional Component에서는 Hook 형태로 사용합니다.

Class Component에서 DropTarget, DragSource HoC 메소드(beginDrag, endDrag, drop, hover)의 인자로 해당 Component의 props, monitor, component가 옵니다. 하지만 Functional Component에서는 Component와 Props를 클로저 패턴으로써 사용할 수 있기 때문에 useDrag, useDrop의 메소드에는 기존 HoC에서 monitor만 인자로 들어올 뿐입니다. (정확히는 첫번째 인자로 monitor.getItem(), 두번째 인자로 monitor가 들어옵니다.)

debounce/throttle의 사용

Drop target에 hover하는 중에는 비용이 큰 연산이나 액션을 실행하는 것은 별로 좋은 생각이 아닙니다. React DnD 공식 문서에서도, hover보다는 drop에서의 Flux action을 실행하는 것을 권장하고 있습니다.

drop(item, monitor): (…) Both this method and the source's endDrag method are good places to fire Flux actions.

따라서 hover 메소드에서는 순서 변경을 시각적으로는 볼 수 있도록 하되, 광범위하게 적용될 수 있는 Redux에 아직 반영시키지는 않도록 해주는게 좋습니다. 하지만 UX적으로 hover시에 Redux action을 dispatch하는게 더 좋은 선택일 때가 있습니다. 아래와 같이 마우스를 뗐을때가 아니라, 드래그중에도 즉시 해당 아이템의 변경된 순서를 기록해서 표시해 보여주어야 하는 경우입니다.

하지만 UX적으로 hover시에 Redux action을 dispatch하는게 더 좋은 선택일 때가 있습니다. 아래와 같이 마우스를 뗐을때가 아니라, 드래그 중에도 즉시 다른 영역에 대해 변경된 순서를 보여주어야 하는 경우입니다.

채널톡의 서포트봇 기능 설정 화면 예시

이런 경우 여러 아이템 사이를 빠르게 이동할 때 퍼포먼스 문제가 생길 수 있습니다. 이러한 문제를 해결하기 위해 hover method에 debounce이나 throttle를 적용하는 것이 좋습니다.

JavaScript

크기가 다른 요소간에 React-dnd을 적용할때 나타날 수 있는 문제점

혼돈의 카오스 😱

hover 메소드 내부에서 순서 변경 로직을 단순하게 처리할 경우에는 위 사진처럼 height가 작은 아이템을 잡은 상태로 height가 큰 아이템과 순서를 변경하려고 할때 반복적으로 위치가 바뀌는 문제가 있습니다. 순서가 변경된 후에도 계속 호버된 상태이기 때문인데요.

아래는 height가 다른 아이템을 드래그할 때의 문제를 해결하는 코드 예시입니다.

JavaScript

따라서 height가 가변적인 컴포넌트에 적용할 경우에는 반드시 마우스의 현재 위치와 현재 호버 중인 Component의 위치를 계산하여 Hovered Component의 절반을 지났을 시점에만 아이템 이동이 실행되도록 하는게 좋습니다.


채널톡 프론트엔드팀은 최고의 사용자 경험을 만들기 위해 라이브러리도 꼼꼼한 리서치에 근거해 사용하고 있어요. React DnD를 선택한 과정처럼 말이죠 ✈️

저희 팀은 하루 평균 2.6천만 번 이상의 스크립트 요청이 발생하는 플러그인(채널톡 채팅 버튼)부터 매일 1만 명의 매니저가 사용하는 데스크(채널톡 관리 툴)를 만들어요. 이 멋진 여정에 함께하고 싶은 분이라면 지금 바로 지원해주세요 🙌

We Make a Future Classic Product

채널팀과 함께 성장하고 싶은 분을 기다립니다

사이트에 무료로 채널톡을 붙이세요.

써보면서 이해하는게 가장 빠릅니다

회사 이메일을 입력해주세요