게시글

강좌13 - HTML&DOM - 2년 전 등록

드래그 드롭 API

조회수:
0

안녕하세요. 이번 시간에는 드래그 드롭 api에 대해 알아보겠습니다. 지난 시간에 배운 File API와 같이 사용하면 좋습니다. 보통 파일을 특정 구역에 드롭해서 업로드하기 때문이죠.

우선 HTML 태그를 드래그하는 방법부터 알아보죠. 보통 태그들은 드래그할 수 없습니다. 하지만 태그의 속성으로 draggable="true"를 주면 그제서야 드래그가 되기 시작합니다. 그리고 드롭할 구역이 필요하겠죠? 드롭할 구역에는 JS로 ondragoverondrop 이벤트 핸들러를 연결해주어야 합니다.

위와 같이 드래그 후 드롭할 수 있습니다. 그 와중에 데이터를 전달할 수 있습니다. JS 부분을 보시면

document.getElementById('drag').ondragstart = function() {
  e.dataTransfer.setData('data', this.innerHTML); // 드래그해보세요 문자열 전달
};

document.getElementById('drop').ondragover = function(e) {
  e.preventDefault(); // 필수 이 부분이 없으면 ondrop 이벤트가 발생하지 않습니다.
};
document.getElementById('drop').ondrop = function() {
  alert(e.dataTransfer.getData('data')); // 데이터를 가져옵니다.
};

dragstart 이벤트핸들러에서 e.dataTransfer.setData로 전달할 데이터를 지정해줍니다. setData는 키-값 형식으로 저장하기 때문에, 키만 다르면 여러 개의 데이터를 저장할 수 있습니다. dragover이벤트에서는 e.preventDefault()로 drop 이벤트가 호출될 수 있게 해주고요. drop 이벤트에서 e.dataTransfer.getData로 데이터를 받을 수 있습니다.

이번에는 파일을 직접 드롭해보죠. 아무 파일이나 끌어서 아래에 넣어보세요.

var drop = document.getElementById('drop');
drop.ondragover = function(e) {
  e.preventDefault(); // 이 부분이 없으면 ondrop 이벤트가 발생하지 않습니다.
};
drop.ondrop = function(e) {
  e.preventDefault(); // 이 부분이 없으면 파일을 브라우저 실행해버립니다.
  var data = e.dataTransfer;
  if (data.items) { // DataTransferItemList 객체 사용
    for (var i = 0; i < data.items.length; i++) { // DataTransferItem 객체 사용
      if (data.items[i].kind == "file") { // 아이템 종류가 파일이면
        var file = data.items[i].getAsFile(); // File API 사용
        alert(file.name);
      }
    }
  } else { // File API 사용
    for (var i = 0; i < data.files.length; i++) {
      alert(data.files[i].name);
    }
  }
};

아까와는 다르게 e.dataTransfer.itemse.dataTransfer.files를 사용합니다. files 객체는 File API이기 때문에 그 강좌 에 나오는 대로 하면 드롭한 파일을 처리할 수 있습니다. 하지만 dataTransfer 객체에는 DataTransferItemList라는 특수한 객체가 있습니다. 구형 브라우저에서는 files 객체가 작동하지 않기 때문에 어쩔 수 없이 items 객체를 사용해야 합니다. 참고로 여러 개의 파일을 드롭하면 모두 받아지는데요. 그래서 위의 코드에서 for 문으로 DataTransferItemList를 DataTransferItem으로 나눠준 겁니다.

DataTransferItem 객체 안에는 kind와 type 속성이 있는데요. type은 png파일이면 'image/png' 이렇게 파일의 속성을 알려주고요. kind는 드롭한 것이 파일인지(file) 문자열인지(string) 알려줍니다. 위의 코드에서는 kind가 file일 때 getAsFile 메소드를 호출하라고 되어있습니다. 이 메소드를 호출하면 다시 File API에 해당하는 파일 객체를 반환합니다.

그렇다면 File API를 쓰면 되지 왜 굳이 DataTransferItem 객체를 사용하는 걸까요? 아까도 말씀드렸다시피 파일 말고도 문자열도 드롭할 수 있습니다. 문자열을 드롭하게 되면 kind는 string, type은 text/*가 되고요. 데이터는 getAsString 메소드로 받을 수 있습니다.

data.items[i].getAsString(function(s) {
  console.log(s);
});

getAsFile과는 다르게 콜백 함수를 통해서 데이터를 받습니다. 문자열이 길 경우 등의 이유로 동기적으로 처리하기보다는 비동기적으로 처리하기로 한 것 같습니다.

드래그 앤 드롭의 단점은 모바일에서는 이 API를 사용할 수 없다는 겁니다. 하지만 모바일에서는 거의 드래그 앤 드롭을 쓸 일이 없기 때문에 그렇게 중요한 문제는 아닌 것 같습니다.

드래그 앤 드롭도 별 거 아니죠? 특히 File API와 같이 사용하면 쉽게 이미지 업로드를 할 수 있습니다. 다음 시간에는 이미지를 폼으로 업로드할 수 있는 FormData 객체에 대해 알아봅시다!

투표로 게시글에 관해 피드백을 해주시면 많은 도움이 됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright © 2016- 무단 전재 및 재배포 금지

댓글

1개의 댓글이 있습니다.
2년 전
좋은 글 감사합니다. 요즘 NodeJs 관심이 많은데, 도움이 되는 유용한 글들이 많은 것 같습니다. 계속 좋은 글 부탁드려요.