본문 바로가기
  • 프론트엔드 개발자 세오세오 | Frontend dev Seo
Learn to Code

[프로젝트] React Drag&Drop: 투두리스트를 칸반 보드로 (1)

by CEOSEO 2021. 8. 25.
728x90
반응형

 

요즘 파이널 프로젝트로 만든 사각사각을 전면 개편하고 있다. 처음 개발 당시 UI와 기능 구현에 급급해 큰 신경을 써주지 못했던 최적화라던가 좀 더 세밀한 기능 구현이라던가와 같은 부분들을 업데이트하고 있다.

 

 

Hoxy 프로젝트가 뭐였는지 궁금하시다면... ☺️ >>>

2021.07.21 - [Learn to Code] - [프로젝트] 실시간 화상채팅앱을 개발했어요! (feat. Socket.IO & WebRTC)

 

[프로젝트] 실시간 화상채팅앱을 개발했어요! (feat. Socket.IO & WebRTC)

🎞 YouTube 발표 영상 GitHub: https://github.com/codestates/sagaksagak-client Wiki: https://github.com/codestates/sagaksagak-client/wiki 발표자료: https://drive.google.com/file/d/1bcdIMkNRRMhKfTnFa8..

seo-tory.tistory.com

 

 

프로젝트 개선 목표로 삼은 것들이 여럿 있었다. 랜딩페이지를 좀 더 가볍게 만들기 위해 새로운 디자인을 적용하는 것은 작업을 이미 마쳤고, 이제는 공부 기록을 보여주는 투두 리스트의 수정 작업을 진행하고 있다.

 

투두 리스트에서 가장 먼저 바꾸고 싶었던 것은, 드래그 & 드랍이 되는 칸반보드 형식으로 구현하는 것이었다. Git repository의 Projects를 사용하다보니, 이 방식이 너무 편해서 이와 비슷하게 만들고 싶었기 때문이다. 아직 서버 통신과의 로직은 적용하지 않았지만, 드래그 & 드랍이 기본적으로 작동되게 만들었기에 해당 내용을 공유하려고 한다.

 

 

Before: Plain To-Do List

Before: 일반적인 투두리스트. 현재 배포되어 있는 상태이다

 

 

After: Kanban Board

aAfter: 드래그&드롭이 되는 칸반보드. 사이트 전체 디자인도 변경 중이라 Before와 많이 다르다.

 

 

 

 

 

 

Drag & Drop 구현하기

드래그 & 드랍의 기본 원리는 굉장히 간단하다. 아래는 드래그 & 드랍의 필수적으로 필요한 단계들을 간단하게 설명한 내용이다.

 

1. 드래그하고 싶은 아이템에 draggable 속성을 더한다.

2. 드랍하고 싶은 곳에 dragover 이벤트를 더한다.

 doragover 이벤트가 걸리는 앨리먼트는 drop이 가능한 상태로 변경되게 된다.

dragover 이벤트에는 default behavior가 있다. 이걸 disable 해주어야 올바르게 작동하기 때문에 콜백함수 안에 e.preventDefault()를 꼭 추가한다.

 

3. 1번에서 draggable 속성을 더한 아이템에 dragstart 이벤트를 더한다.

dragstart 이벤트의 콜백의 주요 목적은 이벤트의 dataTransfer 객체에 현재 드래그하고 있는 아이템이 어떤 아이템인지 특정할 수 있는 정보를 저장하는 것이다. dataTransfer는 Drag & Drop API에서 제공되는, 드래그를 하는 동안 드래그되는 요소의 데이터를 저장하기 위해 사용하는 객체이며, 모든 드래그 이벤트에서 접근할 수 있다. (출처)

 

만약 위의 영상에 나온 것과 같이, 여러 개의 리스트가 있고 그 안에서 아이템을 자유롭게 움직이고 싶다면, 현재 내가 드래그하고 있는 아이템의 원래 고향 리스트(?)도 알 수 있도록 정보를 저장해주어야 한다.

 

위 칸반보드의 경우엔, 아래와 같이 드래그하고 있는 엘리먼트의 id와 그 엘리먼트의 parentElement의 id를 setData 메소드를 이용하여 dataTransfer에 넣어주었다.

 

const handleDragStart = (e, id) => {
    e.dataTransfer.setData('itemId', id)
    e.dataTransfer.setData('listName', e.target.parentElement.id)
}

 

4. 2번에서 만든 drop이 가능한 리스트로 돌아가서, drop 이벤트를 걸어준다.

drop 이벤트의 콜백함수의 역할은, 앞선 이벤트들에서 dataTransfer에 열심히 저장해준 정보들을 가지고, 변경되어야 하는 리스트 상태를 업데이트해주는 것이다. 위에서 e.dataTransfer에 setData를 사용해서 넣었고, 이제 여기서는 getData를 사용해서 아까 넣었던 정보를 가져오면 되는 것이다! 😃

 

위 칸반보드에선, setData로 넣었던 두 개의 정보 - 드래그되는 아이템의 아이디와 그 아이디의 고향 출신 지역 - 를 각각 itemId와 from이라는 변수에 할당했다. 그리고선, 드래그한 아이템을 옮겨 놓을 새로운 이주 지역 리스트(?)를 얻기 위해, drop 이벤트의 e.target으로부터 리스트의 id를 찾아서 to라는 변수에 할당했다. 

 

const handleDrop = (e) => {
    const itemId = Number(e.dataTransfer.getData('itemId'))
    const from = e.dataTransfer.getData('listName')
    const to = e.target.tagName === 'LI' ? e.target.parentElement.id : e.target.id
    
    
    // items는 칸반보드 컴포넌트에서 태스크의 정보를 담고 있는 state이다.
    // 이 이하 부분 코드는 개별 코드의 상황에 따라서 상태를 변경해주는 로직을 넣어주면 된다!
    const updatedList = {...items}
    if (from !== to) {
      const target = updatedList[from].filter(el => el.id === itemId)
      const newTo = [...updatedList[to], ...target]
      const newFrom = updatedList[from].filter(el => el.id !== itemId)

      updatedList[from] = newFrom
      updatedList[to] = newTo
      
      handleItemMovement(updatedList)
    }

	...
  }

 

 

2편: 아이템 드롭 위치 계산하기 >>>

2021.08.26 - [Learn to Code] - [프로젝트] React Drag&Drop: 투두리스트를 칸반 보드로 (2) (feat. getBoundingClientRect())

 

[프로젝트] React Drag&Drop: 투두리스트를 칸반 보드로 (2) (feat. getBoundingClientRect())

본 포스팅은 전편 [프로젝트] React Drag&Drop: 투두리스트를 칸반 보드로 (1)에 이어서 작성한 글입니다! 전편: 2021.08.25 - [Learn to Code] - [프로젝트] React Drag&Drop: 투두리스트를 칸반 보드로 (1) [프..

seo-tory.tistory.com

 

728x90
반응형

댓글