HTML5, 자바스크립트를 사용하여 드래그앤드랍(Drag and Drop)을 구현하는 방법에 대하여 알아봅니다.



# 드래그앤드랍이란?
드래그앤드랍은 사용자 인터페이스(UI) 구현 방법 중 하나로 특정 엘리먼트를 원하는 위치로 드래그하여 옮기는 방법을 말합니다. 드래그앤드랍 방식으로 구현하면 매우 직관적이면서 편리한 UI를 제공할 수 있어 매우 많이 사용되는 방법 중 하나입니다.

? 드래그앤 드랍 UI는 언제 사용할 수 있을까요
다음의 경우에 많이 쓰입니다.

  • 데이터를 가진 엘리먼트 위치를 바꾸는 경우
  • 파일을 업로드하는 경우
  • 데이터를 삭제 또는 추가하는 경우

드래그앤드랍은 예전부터 존재했지만 HTML5 이 후 새로운 메소드, 프로퍼티가 추가되고 웹표준화가 가능하면서더 많이 사용되고 있습니다. 그럼 어떻게 구현할 수 있는지 아래에서 간단히 알아보도록 하겠습니다.

구현에 앞서 아래 사항들을 알고 있어야 합니다. 만약 동작하지 않으면 아래 사항을 체크해보세요.

하나. 이동할 요소에 draggable="true" 어트리뷰트를 추가할 것
둘. 드랍될 엘리먼트의 drop 이벤트에 event.preventDefault()를 사용할 것
; 드랍 될 요소에 preventDefault를 사용하지 않으면 브라우저에서 드랍 이벤트를 허용하지 않을 수 있습니다.

드래그앤드랍 구현시 단계별로 프로세스를 나누어보면 다음과 같습니다. 이미 아는 내용이라면 바로 예제로 넘어가셔도 됩니다.

1. 드래그를 할 수 있는 부분과 할 수 없는 부분을 나눌 것
2. 드래그 할 영역은 draggable="true"를 추가할 것
3. 드래그한 엘리먼트가 드랍될 영역은 event.preventDefault()를 추가할 것
4. 다음의 스타일을 정의할 것
  -- 드래그 될 때의 스타일
  -- 드래그가 다른 엘리먼트 위에 있을 때 스타일
  -- 다른 엘리먼트 위에 드랍될 때의 스타일

그럼 아래에서 간단한 예제를 만들어보겠습니다.



# 드래그앤드랍 구현방법 및 예제보기
먼저 아래의 예제 소스를 봐주세요. 1, 2, 3이라는 각각의 박스 형태 엘리먼트가 존재하며 이를 각각 드래그하여 옮길 수 있습니다.

@ dragDrop.html
<div class="test wrap">
  <div class="drag-items">
    <span class="item" id="1" ondragstart="dragStart(event);" draggable="true" ondragend="dragEnd(event)">1</span>
    <span class="item" id="2" ondragstart="dragStart(event);" draggable="true" ondragend="dragEnd(event)">2</span>
    <span class="item" id="3" ondragstart="dragStart(event);" draggable="true" ondragend="dragEnd(event)">3</span>
  </div>
  <div class="bucket" ondragover="allowDrop();" ondrop="dropItem(event);"></div>
</div>

보기에도 무척 간단한 HTML 소스입니다. 드래그 할 요소에는 id값으로 1,2,3을 가지고 있으면 동시에 다음의 어트리뷰트를 가지고 있습니다.
ondragstart="dragStart(event)"
draggable="true"

여기서 ondragstart는 드래그할 경우 dnd.drag() 이벤트 함수를 동작하게 됩니다. 그리고 드래그 해야 하므로 draggable="true"를 추가하였습니다.

다음은 drop이 되는 target 엘리먼트가 가진 어트리뷰트입니다.
ondragover="allowDrop();"
ondrop="dropItem(event);"

이번에는 두 개의 이벤트 함수를 동작하게 됩니다.
ondragover는 특정 엘리먼트가 해당 엘리먼트의 오버 상태인 위에 있을 때를 발생하는 이벤트입니다. 그리고 ondrop은 실제로 드랍(drop)을 수행할 때 나타나는 이벤트입니다.


@ 참고사항
위의 on으로 시작하는 이벤트 어트리뷰트는 모두 다음과 같이 addEventListener를 사용하여 동작하도록 만들 수 있으니 참고하시기 바랍니다. ondragover를 예를들면 아래와 같습니다.
Ex)
ondragover="allowDrop();"
// 상동
element.addEventListener('dragover', allowDrop());

다음은 스크립트 소스입니다.

@ dragDrop.js
allowDrop = function() {
  event.preventDefault();
};

dropItem = function() {
  var _targetEle = event.target;
  var _id = event.dataTransfer.getData('text');
  var _moveEle = document.getElementById(_id );
  _targetEle.before(_moveEle);
};

dragStart = function() {
  var _thisEle = event.target;
  var _thisId = _thisEle.id;
  _thisEle.classList.add('is-dragging');
  event.dataTransfer.setData('text/plain', _thisId);
};

dragEnd = function() {
  var _thisEle = event.target;
  _thisEle.classList.remove('is-dragging');
};

마지막으로 스타일을 정의 부분입니다.
.item {
  background: #999;
  display: inline-block;
  width: 50px;
  height: 50px;
  color: #fff;
  padding: 12px 20px;
  box-sizing: border-box;
  margin: 0 0 10px;
}
.item.is-dragging {
  background-color: red;
}

.bucket {
  display: block;
  width: 200px;
  height: 90px;
  margin: 0 0 18px;
  border: 1px solid;
  text-align: center;
  padding: 15px;
}
여기서 is-dragging 클래스를 준 이유는 현재 드래그 중임을 시각적으로 표현하기 위해 이처럼 다른 스타일을 적용할 수 있습니다.

css는 매우 단순합니다. 여기까지 html, css, 자바스크립트를 사용한 모든 소스코드를 알아보았습니다.


! 드래그앤드랍 주요 메소드 및 프로퍼티 정리
드래그앤드랍 구현시 자주 사용되는 주요한 메소드와 프로퍼티를 알아봅니다.
(업데이트 중임...)


! event.dataTransfer 알아보기
드래그될 경우 데이터를 저장하고 가져올 수 있는 방법으로 event 이벤트 객체의 dataTransfer가 사용됩니다. 아래는 각각 메소드와 프로퍼티입니다.

@ 표준 메소드
.clearData()
.setData(format, data)
.getData(format)

위 표준 메소드를 사용해 데이터를 저장 및 가져오기, 삭제를 수행할 수 있습니다. 이때 format에 따라 값을 가져오므로 어떤 format을 지정할 것인지 설정해야합니다.


@ 표준 프로퍼티
.dropEffect
.effectAllowed
.files
.items
.types


! 참고사항
모바일 브라우저의 경우 drag, drop 이벤트가 아닌 touch 이벤트를 사용하므로 위 방식을 동일하게 적용하기 어렵습니다. 이 경우 touch 이벤트를 추가로 등록하는 방법을 사용할 수 있으니 참고하세요.



# 예제 실제로 동작해보기
위의 예제를 동작하면 어떻게 나타나는지 아래에서 확인해보실 수 있습니다. 직접 이동해보세요.

1 2 3