내가 만든 페이지가 마무리가 된 시점부터 추가기능 구현에 힘을 쓰고 있다. 이렇게 시간이 남을때 뭐라도 안해본걸 해야 실력이 늘고 경험이 생기니깐 기쁜 마음으로 하고 있다.
그런 의미에서 드레그앤드롭 이벤트를 만들어보려고 한다. 현재 우리가 구현중인 서비스는 직접 할일의 상태를 옮겨줘야하는 번거로움이 있다. 그래서 사용자가 카드를 드레그해서 영역을 옮겨주기만 한다면 해당 영역으로 할일이 이동되는 기능을 추가하려고 한다.
처음 해당 기능을 구현하기 위해 사용하려고 했던 라이브러리이다. 실제로 일정 관리 서비스인 Jira,Trello를 만든 회사에서 만든 라이브러리이기 때문에 신뢰도 갔고 안정적일거라고 생각했다.
하지만...무엇이든 처음부터 라이브러리를 사용하기보다는 공부하는 입장에서 자바스크립트와 web API를 최대한 사용해보기로 했다. 물론 라이브러리만큼 깔끔한 트랜지션은 어려울수 있지만 그건 나중에 사용해도 된다!
항상 이벤트는 클릭이나 submit과 같은 이벤트만 사용해서 drag이벤트가 있는지조차 몰랐다. 지나가다가 봤어도 실제로 사용해본적은 한번도 없다.
<button
type="button"
onClick={handleOpenModal}
draggable
>
우선 드레그 이벤트를 사용할 요소에 draggable 속성을 추가해준다. 그러면 해당 요소는 드레그가 가능해진다. 이제 드레그 이벤트에 사용할 함수를 만들어주면 된다.
- 드레그 시작
- 드레그 감지
- 아이템 드롭
세가지 순서로 드레그 이벤트가 동작한다. 이 순서에 해당하는 함수를 만들어주겠다.
const dragItem = useRef({ id: 0 })
const baseColumn = useRef(0)
const dragOverColumn = useRef(0)
시작에 앞서 3개의 ref값을 만들어주겠다. dragItem은 드레그 이벤트를 적용할 아이템을 저장할 것이다.
baseColumn은 아이템이 처음 속해있는 column, 즉 서비스에서는 어떤 작업 선상에 있는지를 저장하는 것이다.
dragOverColumn은 이동시킬 column, 즉 어떤 작업으로 이동시킬지 저장한다.
const dragStart = (card: Card, id: number) => {
dragItem.current = card
baseColumn.current = id
}
드레그를 시작하면 드레그한 아이템과 칼럼의 id값을 ref값으로 지정해준다.
const dragEnter = (id: number) => {
dragOverColumn.current = id
}
그리고 다른 칼럼에 진입하면 해당 칼럼의 id값을 저장한다.
const drop = async () => {
if (baseColumn.current !== dragOverColumn.current) {
await updateDashBoardCard({
newCardBody: { ...dragItem.current, columnId: dragOverColumn.current },
cardId: dragItem.current.id,
})
}
}
그리고 아이템을 놓으면 원래 칼럼id값과 이동한 칼럼의 id를 비교해 update요청을 한다. 그래서 처음 ref값으로 저장한 아이템과 칼럼 id를 리퀘스트 body로 같이 보내준다.
이제 이벤트를 적용해보자.
당연히 드레그 시작과 끝이벤트는 아이템에 적용시켜준다.
<button
type="button"
draggable
onDragStart={() => dragStart(card, columnId)}
onDragEnd={drop}
>
...
아까 설정해준대로 아이템 정보와 칼럼 id값을 넘겨주면 된다. 그리고 enter이벤트는
<section
onDragEnter={() => dragEnter(columnId)}
>
...
칼럼에 해당하는 영역에 적용시켜준다. 그러면 마우스 커서가 칼럼에 진입하면 칼럼 id값을 저장할 것이다.

초기 작업 상태이다. 여기에서 테스트를 옮겨보겠다.

이렇게 드레그가 잘 적용되서 리퀘스트를 보내는 것을 확인할 수 있다.

그리고 실제로 잘 옮겨진다.
위에서 드레그앤드롭의 결과로 아이템이 잘 옮겨지는 것을 확인했다. 하지만 이 동작은 드레그앤드롭으로만 구현가능한 것은 아니고 팀원분이 칼럼과 아이템을 전역변수로 관리하시면서 드레그앤드롭의 이벤트 결과에도 적용을 시켜주신 것이다.
그냥 배열이나 데이터를 드레그해서 옮겨서 순서를 바꾸는 동작은 쉽다. 그냥 현재 배열에서 드레그한 아이템을 지우고 중간에 넣어주는 식으로 동작하면 된다. 하지만 지금 페이지는 서버에서 데이터를 받아서 보여주고 있다. 그래서 실제로 여러 곳에서 할일 데이터를 사용하고 있기때문에 바로 서버에 수정된 데이터를 보여줘야한다. 그래서 해당 부분을 전역으로 바꿔주셨다.
아마 다른 부분에서 큰 문제가 없었다면 내가 드레그이벤트로 배열 삭제나 추가까지 했을 것이다. 그러면 지금처럼 딜레이 없이 바로 이동되는 효과를 봤을 것이다.
새로운 기능을 추가하면서 재미있었다. 어떻게 동작하는지 잘 파악이 안되서 여러곳에서 console을 찍으면서 동작하는지 확인했다. 지금 내가 구현한 방식이 잘 맞는지도 솔직히 잘 모른다. 일단 동작하긴 한다...일단은...
프로젝트가 끝나기 전까지 좀더 매끄럽게 동작하는 방법은 없는지 좀 고민해보고 적용해보면 재미있을것 같다. 이제 대략적인 기능은 구현이 되었고 거의 리팩토링과 세세한 부분을 컨트롤하는게 전부다. 앞으로의 포스팅을 거의 그런 방식으로 진행되지 않을까 싶다.