HTML 드래그 앤 드롭 API
=================

HTML 드래그 앤 드롭 인터페이스는 Firefox와 다른 브라우저에서 어플리케이션이 드래그 앤 드롭 기능을 사용하게 해줍니다. 이 기능을 이용해 사용자는 *draggable* 요소를 마우스로 선택해 *droppable* 요소로 드래그하고, 마우스 버튼에서 손을 뗌으로써 요소를 드롭할 수 있습니다. 드래그하는 동안 draggable 요소는 반투명한 채로 마우스 포인터를 따라다닙니다.

웹 사이트나 확장 기능, XUL 어플리케이션을 위해, 다양한 요소를 draggable 요소로 만들 수 있고, 이벤트에 대한 draggable 요소의 반응들을 만들어내거나 droppable 요소를 자유자재로 만들 수 있습니다.

이 문서는 HTML 드래그 앤 드롭에 대한 전반적인 개요입니다. 인터페이스에 대한 설명과 드래그 앤 드롭 기능을 어플리케이션에서 사용하기 위한 기본적인 절차, 인터페이스의 상호 운용성에 대한 요약 등이 이 문서에 담겨있습니다.

드래그 이벤트
-------

HTML 드래그 앤 드롭은 `DOM event model` 과 *`drag events` (en-US)* 를 `mouse events` 로부터 상속받습니다. 보통 드래그는 사용자가 draggable 요소를 마우스로 선택하고, 마우스 포인터를 droppable 요소로 가져가 마우스 버튼을 때는 것으로 이루어집니다. 드래그하는 도중에 많은 이벤트가 발생하고, 몇몇 이벤트는 여러번 발생하기도 합니다. ( `drag (en-US)`와 `dragover (en-US)`).

모든 드래그 이벤트 (en-US)는 글로벌 이벤트 핸들러 (en-US)와 연결되어 있습니다. 각 드래그 이벤트와 드래그 전역 속성은 참조 문서를 가지고 있습니다. 아래 표는 각 이벤트에 대한 간략한 설명과 참조 문서로의 링크를 담고 있습니다.

| 이벤트 | 이벤트 핸들러 | 설명 |
| --- | --- | --- |
| `drag` | `ondrag` (en-US) | 요소나 텍스트 블록을 드래그 할 때 발생한다. |
| `dragend (en-US)` | `ondragend` (en-US) | 드래그를 끝냈을 때 발생한다. (마우스 버튼을 떼거나 ESC 키를 누를 때) (드래그 끝내기 (en-US)를 보시오) |
| `dragenter (en-US)` | `ondragenter` (en-US) | 드래그한 요소나 텍스트 블록을 적합한 드롭 대상위에 올라갔을 때 발생한다. (드롭 대상 지정하기 (en-US)를 보시오.) |
| `dragexit` | `ondragexit` (en-US) | 요소가 더 이상 드래그의 직접적인 대상이 아닐 때 발생한다. |
| `dragleave (en-US)` | `ondragleave` (en-US) | 드래그하는 요소나 텍스트 블록이 적합한 드롭 대상에서 벗어났을 때 발생한다. |
| `dragover (en-US)` | `ondragover` (en-US) | 요소나 텍스트 블록을 적합한 드롭 대상 위로 지나갈 때 발생한다. (매 수백 밀리초마다 발생한다.) |
| `dragstart (en-US)` | `ondragstart` (en-US) | 사용자가 요소나 텍스트 블록을 드래그하기 시작했을 때 발생한다. (드래그 시작하기 (en-US)를 보시오.) |
| `drop (en-US)` | `ondrop` (en-US) | 요소나 텍스트 블록을 적합한 드롭 대상에 드롭했을 때 발생한다. (드롭하기 (en-US)를 보시오.) |

**참고:** `참고: dragstart`와 `dragend` 이벤트는 파일을 브라우저로 드래그할 때는 발생하지 않습니다.

인터페이스
-----

HTML 드래그와 드롭 인터페이스는 `DragEvent` (en-US), `DataTransfer`, `DataTransferItem` (en-US), `DataTransferItemList` (en-US) 입니다.

`DataTransfer` 객체는 드래그 형태나 드래그 데이터 (하나 이상의 아이템), 각 드래그 아이템의 종류 (MIME 종류) 와 같은 드래그 이벤트의 상태를 담고 있습니다. `DataTransfer` 는 또한 드래그 데이터에 아이템을 추가하거나 제거하는 메소드를 가지고 있습니다. The `DragEvent` (en-US) 와 `DataTransfer` 인터페이스만 있으면 어플리케이션에 HTML 드래그 앤 드롭 기능을 추가할 수 있습니다. 참고로 Firefox는 `DataTransfer`에 Gecko-specific extensions 와 같은 Firefox에서만 동작하는 추가적인 확장을 제공합니다.

`DataTransfer`는 `DataTransferItem` (en-US)의 `목록` (en-US) 인 `items` 프로퍼티를 가지고 있습니다. 각 `DataTransferItem` (en-US) 는 하나의 드래그 아이템을 나타내고 각 아이템은 데이터의 종류 (`string` 혹은 `file`) 를 나타내는 `kind` (en-US) 프로퍼티와 데이터 아이템의 종류 (MIME 종류) 를 나타내는 `type` (en-US) 프로퍼티를 가집니다. `DataTransferItem` (en-US)은 드래그 아이템의 데이터를 가져오는 메소드를 제공합니다.

`DataTransferItemList` (en-US) 객체는 `DataTransferItem` (en-US)의 리스트입니다. 이 리스트 객체는 세 개의 메소드 - 드래그 아이템을 리스트에 추가하거나, 리스트에서 아이템을 삭제하거나, 모든 드래그 아이템을 리스트에서 삭제하는 메소드 - 를 가집니다.

A key difference between the `DataTransfer` and `DataTransferItem` (en-US) interfaces is that the former uses the synchronous `getData()` method to access a drag item's data, whereas the later uses the asynchronous `getAsString()` (en-US) method to access a drag item's data.

`DataTransfer`와 `DataTransferItem` (en-US)의 가장 중요한 차이점은 전자는 드래그 아이템의 데이터에 접근하기 위해 동기 메소드인 `getData()`를 사용하는데 반해, 후자는 비동기 메소드인 `getAsString()` (en-US)를 사용한다는 점입니다.

**참고:** 참고: `DragEvent` (en-US) and `DataTransfer`는 여러 데스크탑 브라우저에서 폭넓게 지원하고 있습니다. 하지만 `DataTransferItem` (en-US)와 `DataTransferItemList` (en-US)는 제한적으로 사용 가능합니다. 드래그 앤 드롭의 상호 운용성에 대한 더 많은 정보를 찾아보기 위해 Interoperability를 보십시오.

### Gecko 한정 인터페이스

Mozilla와 Firefox는 표준 드래그 앤 드롭 모델에서 제공하지 않는 몇가지 기능들을 추가로 제공합니다. 여러 개의 아이템을 동시에 드래그하거나 파일과 같이 문자열이 아닌 데이터를 드래그 하기 위한 여러 편리한 기능을 제공합니다. 더 많은 정보를 찾아보기 위해, Dragging and Dropping Multiple Items을 보십시오. 덧붙여, 모든 Gecko 한정 프로퍼티나 Gecko 한정 메소드를 찾아보기 위해 `DataTransfer` 참조 페이지도 보시기 바랍니다.

기본
--

이번 절은 드래그 앤 드롭 기능을 추가하기 위한 기본적인 방법을 요약하고 있습니다. 각 절은 단계를 설명하고, 짧은 코드 예제와 추가적인 정보를 위한 링크를 포함합니다.

### 어떤 것이 *draggable*인지 확인하기

하나의 요소를 draggable로 만들기 위해서는 `draggable`와 `ondragstart` (en-US) 전역 이벤트 핸들러를 아래 예제 코드와 같이 추가해야합니다.


```js
function dragstart\_handler(ev) {
  console.log("dragStart");
  // 데이터 전달 객체에 대상 요소의 id를 추가합니다.
  ev.dataTransfer.setData("text/plain", ev.target.id);
}
```



```html
<script>
 function dragstart\_handler(ev) {
 // 데이터 전달 객체에 대상 요소의 id를 추가합니다.
 ev.dataTransfer.setData("text/plain", ev.target.id);
 }

 window.addEventListener("DOMContentLoaded", () => {
 // id를 통해 element를 가져옵니다.
 const element = document.getElementById("p1");
 // 'dragstart' 이벤트 리스터를 추가합니다.
 element.addEventListener("dragstart", dragstart\_handler);
 });
</script>

<p id="p1" draggable="true">This element is draggable.</p>
```


추가 정보를 위해 draggable attribute reference와 Drag operations guide (en-US)를 참고하세요.

### 드래그 데이터 정의하기

드래그할 때 자유롭게 데이터 아이템을 포함할 수 있습니다. 각 데이터 아이템은 특정 `type`의 `문자열`이며, 보통 `text/html`와 같은 MIME type입니다.

각 `drag event` (en-US) 은 이벤트 데이터를 가지고 있는 `dataTransfer` (en-US) 를 가집니다. 이 프로퍼티는 (`DataTransfer` 객체) 드래그 데이터를 관리하는 메소드를 가집니다. `setData()` (en-US) 는 아래 코드 예제와 같이 아이템을 드래그 데이터에 추가할 때 사용합니다.


```js
function dragstart\_handler(ev) {
  // 드래그 데이터를 추가합니다.
  ev.dataTransfer.setData("text/plain", ev.target.id);
  ev.dataTransfer.setData("text/html", "<p>Example paragraph</p>");
  ev.dataTransfer.setData("text/uri-list", "http://developer.mozilla.org");
}
```


드래그 앤 드롭에 사용할 수 있는 공통 데이터 타입 (텍스트, HTML, 링크, 파일 등) 의 목록을 보려면, Recommended Drag Types (en-US)를 참고하십시오. 드래그 데이터에 대한 추가적인 정보를 위해서는 Drag Data (en-US)를 참고하십시오.

### 드래그 이미지 정의하기

브라우저는 드래그 하는 동안 마우스 포인터 옆에 나타나는 이미지를 기본적으로 제공합니다. 어플리케이션에서 다른 이미지를 사용하기 원한다면 아래 예제와 같이 `setDragImage()` (en-US)를 사용할 수 있습니다.


```js
function dragstart\_handler(ev) {
  // 드래그 이미지로 사용할 이미지를 만듭니다.
  // 참고: "example.gif"를 존재하는 이미지로 바꾸지 않으면 기본 드래그 이미지를 사용합니다.
  var img = new Image();
  img.src = "example.gif";
  ev.dataTransfer.setDragImage(img, 10, 10);
}
```


드래그 이미지에 대해 더 알아보려면, Setting the Drag Feedback Image (en-US)를 참고하세요.

### 드래그 효과 정의하기

`dropEffect` (en-US) 프로퍼티는 드래그 앤 드롭 도중에 사용자에게 피드백 (보통 시각적인) 을 제공하기 위해 사용합니다. 브라우저가 드래그 하는 동안 어떤 마우스 포인터를 보여줄 지 결정합니다. 사용자가 마우스 포인터를 대상 드롭 요소에 올려놓으면, 브라우저는 드래그 효과에 적합한 마우스 포인터를 보여줄 것입니다.

세 개의 효과가 정의되어 있습니다:

`copy`는 현재 위치에서 드롭하는 위치로 데이터가 복사될 것을 암시합니다.

`move`는 현재 위치에서 드롭하는 위치로 데이터가 이동할 것을 암시합니다.

`link`는 드래그하는 위치와 드롭하는 위치 간의 일종의 관계나 연결이 맺어진 다는 것을 암시합니다.

특정 위치에서는 특정 효과가 허용된다는 것을 알려주기 위해 드래그 하는 도중에 효과가 변할 수 있습니다. 허용되는 경우에만 해당 위치에 드롭할 수 있습니다.

다음 예제는 어떻게 이 프로퍼티를 사용하는지 보여줍니다.


```js
function dragstart\_handler(ev) {
  // 드래그 효과를 copy로 지정합니다.
  ev.dataTransfer.dropEffect = "copy";
}
```


더 자세한 설명은 Drag Effects (en-US)를 참고하세요.

### 드롭 지역 정의하기

기본적으로는 브라우저는 HTML 요소에 뭔가를 드롭했을 때 아무 일도 일어나지 않도록 합니다. 특정 요소가 드롭 지역 혹은 droppable로 만들기 위해서는 해당 요소가 `ondragover` (en-US)와 `ondrop` (en-US) 이벤트 핸들러 속성을 가져야합니다. 아래 예제는 두 요소를 어떻게 사용하고, 각 요소에 포함된 기본적인 이벤트 핸들러를 보여줍니다.


```html
<script>
 function dragover\_handler(ev) {
 ev.preventDefault();
 // dropEffect를 move로 설정.
 ev.dataTransfer.dropEffect = "move";
 }
 function drop\_handler(ev) {
 ev.preventDefault();
 // 대상의 id를 가져와 대상 DOM에 움직인 요소를 추가합니다.
 const data = ev.dataTransfer.getData("text/plain");
 ev.target.appendChild(document.getElementById(data));
 }
</script>

<p
 id="target"
 ondrop="drop\_handler(event)"
 ondragover="dragover\_handler(event)">
  Drop Zone
</p>
```


각 핸들러는 `preventDefault()` 를 호출해 추가적인 이벤트 (터치 이벤트나 포인터 이벤트) 가 일어나지 않도록 합니다.

추가적인 정보는, Specifying Drop Targets (en-US)를 참고하세요.

### 드롭 효과 다루기

`drop (en-US)` 이벤트 핸들러는 자유롭게 드래그 데이터를 가공할 수 있습니다. 보통, 드래그 아이템과 각 아이템을 가공하기 위해 `getData()`를 사용합니다. 추가로, `dropEffect` (en-US) 값이나 보조키 상태에 따라 어플리케이션이 어떻게 동작할지를 결정할 수 있습니다.

아래 예제는 드롭 핸들러가 드래그 데이터로부터 드래그하는 요소의 id를 가져와 드래그하는 요소를 드롭하는 요소로 옮기기위해 사용합니다.


```html
<script>
 function dragstart\_handler(ev) {
 // 데이터 전달 객체에 대상 요소의 id를 추가합니다.
 ev.dataTransfer.setData("application/my-app", ev.target.id);
 ev.dataTransfer.dropEffect = "move";
 }
 function dragover\_handler(ev) {
 ev.preventDefault();
 ev.dataTransfer.dropEffect = "move";
 }
 function drop\_handler(ev) {
 ev.preventDefault();
 // 대상의 id를 가져와 이동한 대상 DOM 요소를 추가합니다.
 // Get the id of the target and add the moved element to the target's DOM
 const data = ev.dataTransfer.getData("application/my-app");
 ev.target.appendChild(document.getElementById(data));
 }
</script>

<p id="p1" draggable="true" ondragstart="dragstart\_handler(event)">
  This element is draggable.
</p>
<div
 id="target"
 ondrop="drop\_handler(event)"
 ondragover="dragover\_handler(event)">
  Drop Zone
</div>
```


더 많은 정보를 위해 Performing a Drop (en-US)을 보십시오.

### 드래그가 끝나면

드래그가 끝나면 드래그한 요소에 `dragend (en-US)` 이벤트가 발생합니다. 이 이벤트는 드래그가 완료되거나 중간에 취소되어도 발생합니다. `dragend (en-US)` 이벤트 핸들러는 `dropEffect` (en-US) 프로퍼티를 확인해 드래그가 성공했는지를 확인할 수 있습니다.

드래그 끝을 다루기 위한 더 많은 정보는 Finishing a Drag (en-US)를 참고하세요.

상호 운용성
------

DataTransferItem interface's Browser Compatibility table (en-US)에 나온 대로, 드래그 앤 드롭은 상대적으로 여러 데스크톱 브라우저에서 폭넓게 사용할 수 있습니다 (`DataTransferItem` (en-US)는 `DataTransferItemList` (en-US) 덜 지원하지만). 또한 모바일 브라우저에서는 매우 한정적으로 사용할 수 있습니다.

예제와 데모
------

* Copying and moving elements with the `DataTransfer` interface
* Copying and moving elements with the `DataTransferListItem` interface
* 파일 드래그 앤 드롭; Firefox 전용: http://jsfiddle.net/9C2EF/
* 파일 드래그 앤 드롭; 모든 브라우저: https://jsbin.com/hiqasek/
명세서
---

| Specification |
| --- |
| HTML Standard  |

더보기
---

* Drag Operations (en-US)
* Dragging and Dropping Multiple Items
* Recommended Drag Types (en-US)
* HTML5 Living Standard: Drag and Drop
* Drag and Drop interoperability data from CanIUse