드래그 앤 드롭 기능의 중요성
드래그 앤 드롭은 사용자 인터페이스의 상호 작용성을 높이고, 부드러운 사용자 경험을 제공하는 데 필수적인 기능입니다. 파일 업로드 도구, 정렬 가능한 목록, 또는 인터랙티브 게임을 개발할 때, 이 API를 효율적으로 사용하는 방법을 이해하는 것은 웹 개발자에게 매우 중요한 기술입니다.
HTML 드래그 앤 드롭 기본 원리
일반적인 드래그 앤 드롭 시스템은 크게 두 가지 요소로 구성됩니다. 첫째, 사용자가 마우스로 이동시킬 수 있는 드래그 가능한 요소가 있고, 둘째, 드래그된 요소를 놓을 수 있는 놓기 가능한 요소가 있습니다. 이러한 요소를 통해 사용자는 데이터를 직관적으로 조작할 수 있습니다.
드래그 앤 드롭 기능을 구현하려면, 브라우저에게 어떤 요소가 드래그 가능한지 알려줘야 합니다. 이를 위해 드래그 가능하게 만들고 싶은 요소의 `draggable` HTML 속성을 `true`로 설정해야 합니다.
<div draggable="true">이 요소는 드래그 가능합니다</div>
드래그 이벤트가 시작되면, 브라우저는 일반적으로 드래그되는 요소의 기본 ‘고스트’ 이미지를 표시하여 사용자에게 시각적인 피드백을 제공합니다.
기본 이미지 대신 사용자 정의 이미지를 사용하여 피드백을 제공할 수 있습니다. 이를 위해 DOM에서 드래그 가능한 요소를 선택하고, 사용자 정의 피드백 이미지를 나타내는 새 이미지를 생성한 다음 `dragstart` 이벤트 리스너를 추가합니다.
let img = new Image();
img.src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Twemoji_1f600.svg/220px-Twemoji_1f600.svg.png"; document.querySelector('div').addEventListener('dragstart', (event)=>{
event.dataTransfer.setDragImage(img, 10, 10);
})
위의 코드에서 `setDragImage` 메소드는 세 가지 매개변수를 가집니다. 첫 번째 매개변수는 이미지의 참조이며, 나머지 두 개는 각각 이미지의 수평 및 수직 오프셋을 나타냅니다. 코드를 실행하고 드래그를 시작하면 사용자 정의 드래그 이미지가 나타나는 것을 확인할 수 있습니다.
드롭을 허용하려면, `dragenter`와 `dragover` 이벤트를 모두 취소하여 브라우저의 기본 동작을 막아야 합니다.
const dropElement = document.querySelector("drop-target"); dropElement.addEventListener("dragenter", (ev) => {
ev.preventDefault();
}); dropElement.addEventListener("dragover", (ev) => {
ev.preventDefault();
});
DragEvent 인터페이스 이해
JavaScript의 `DragEvent` 인터페이스는 사용자의 드래그 앤 드롭 상호 작용을 나타냅니다. 다음은 `DragEvent` 인터페이스에서 발생할 수 있는 이벤트 유형 목록입니다.
- `drag`: 사용자가 요소를 드래그하는 동안 발생하는 이벤트입니다.
- `dragend`: 드래그 작업이 완료되거나 사용자가 드래그를 중단할 때 발생합니다. 마우스 버튼을 놓거나 Esc 키를 눌러 드래그를 종료할 수 있습니다.
- `dragenter`: 드래그된 요소가 유효한 드롭 대상에 들어갈 때 트리거됩니다.
- `dragleave`: 드래그된 요소가 드롭 대상을 벗어날 때 발생합니다.
- `dragover`: 사용자가 드래그 가능한 요소를 드롭 대상 위로 드래그할 때 발생합니다.
- `dragstart`: 드래그 작업이 시작될 때 발생합니다.
- `drop`: 사용자가 요소를 드롭 대상에 놓을 때 트리거됩니다.
브라우저 외부 환경(예: 운영 체제의 파일 관리자)에서 파일을 브라우저로 드래그할 때, 브라우저는 `dragstart` 또는 `dragend` 이벤트를 트리거하지 않습니다.
프로그래밍 방식으로 사용자 정의 드래그 이벤트를 발생시키려는 경우 `DragEvent`는 유용할 수 있습니다. 예를 들어, 페이지 로드 시 div 요소에서 사용자 정의 드래그 이벤트를 실행하려면 다음 방법을 따르세요. 먼저, 다음과 같이 새로운 사용자 정의 `DragEvent()`를 만듭니다.
const customDragStartEvent = new DragEvent('dragstart', {
dataTransfer: new DataTransfer(),
}) const customDragEndEvent = new DragEvent('dragend');
위 코드에서 `customDragStartEvent`는 `DragEvent()`의 인스턴스입니다. `customDragStartEvent`는 두 개의 생성자 인수를 갖습니다. 첫 번째는 앞서 언급한 7가지 이벤트 유형 중 하나일 수 있는 드래그 이벤트 유형을 나타냅니다.
두 번째 인수는 `DataTransfer`의 인스턴스를 나타내는 `dataTransfer` 키를 가진 객체입니다. 이에 대해서는 이 가이드의 뒷부분에서 더 자세히 다루겠습니다. 다음으로, DOM에서 이벤트를 트리거하려는 요소를 가져옵니다.
const draggableElement = document.querySelector("#draggable");
그런 다음 이벤트 리스너를 다음과 같이 추가합니다.
draggableElement.addEventListener('dragstart', (event) => {
console.log('드래그 시작!');
event.dataTransfer.setData('text/plain', 'Hello, world!');
}); draggableElement.addEventListener('dragend', () => {
console.log('드래그 종료!');
});
위의 첫 번째 이벤트 리스너에서 콜백 함수는 “드래그 시작!” 텍스트를 콘솔에 출력하고, 이벤트 객체의 `dataTransfer` 속성에 대해 `setData` 메소드를 호출합니다. 이제 다음과 같이 사용자 정의 이벤트를 트리거할 수 있습니다.
draggableElement.dispatchEvent(customDragStartEvent); draggableElement.dispatchEvent(customDragEndEvent);
dataTransfer를 이용한 데이터 전송
`dataTransfer` 객체는 드래그 앤 드롭 작업 중 드래그 가능한 소스 요소와 놓기 가능한 대상 요소 사이를 연결하는 다리 역할을 합니다. 이 객체는 두 요소 간에 공유하려는 데이터의 임시 저장 공간 역할을 합니다.
이 데이터는 텍스트, URL, 사용자 정의 데이터 유형 등 다양한 형식을 취할 수 있어, 다양한 드래그 앤 드롭 기능을 구현하는 데 유용한 도구입니다.
setData()를 사용한 데이터 패키징
드래그 가능한 요소에서 놓기 가능한 요소로 데이터를 전송하려면, `dataTransfer` 객체의 `setData()` 메소드를 사용합니다. 이 메소드는 전송하려는 데이터를 패키징하고 데이터 형식을 지정하는 데 사용됩니다. 기본적인 예는 다음과 같습니다.
element.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text/plain', 'Hello, world!');
});
사용자가 지정된 요소를 드래그하기 시작하면 `setData()` 메소드는 “Hello, world!” 텍스트를 패키징하며 데이터 형식은 `text/plain`으로 설정됩니다. 이제 이 데이터는 드래그 이벤트와 연결되어 놓기 작업 중 놓기 가능한 대상에서 접근할 수 있습니다.
getData()를 사용한 데이터 검색
수신 측에서는, 놓기 가능한 요소의 이벤트 리스너 내에서 `getData()` 메소드를 사용하여 전송된 데이터를 검색할 수 있습니다.
element.addEventListener('drop', (event) => {
const transferredData = event.dataTransfer.getData('text/plain');
console.log(`수신된 데이터: ${transferredData}`);
});
위의 코드 블록은 이전에 `setData()` 메소드를 사용하여 설정한 것과 동일한 데이터 형식(`text/plain`)으로 데이터를 검색합니다. 이를 통해 놓기 가능한 요소의 컨텍스트 내에서 필요에 따라 전송된 데이터를 접근하고 조작할 수 있습니다.
드래그 앤 드롭 인터페이스의 활용 사례
웹 애플리케이션에 드래그 앤 드롭 기능을 통합하는 것은 매우 유용하지만, 이러한 기능을 언제 어떻게 구현해야 하는지 이해하는 것이 중요합니다.
- 파일 업로더: 사용자가 데스크톱이나 파일 관리자에서 지정된 드롭 영역으로 파일을 직접 드래그할 수 있도록 하여 업로드 프로세스를 간소화할 수 있습니다.
- 정렬 가능한 목록: 작업 목록, 재생 목록, 이미지 갤러리 등 항목 목록이 있는 경우, 드래그 앤 드롭을 통해 항목을 재정렬하는 기능을 제공하면 사용자 경험이 향상됩니다.
- 대화형 대시보드: 데이터 시각화 및 보고 도구에서 드래그 앤 드롭은 사용자가 위젯과 차트를 재정렬하여 대시보드를 사용자 정의하는 강력한 방법이 될 수 있습니다.
접근성을 고려하기
드래그 앤 드롭은 시각적으로 매력적이며 사용자 경험을 향상시킬 수 있지만, 장애가 있는 사용자를 포함한 모든 사용자가 구현에 접근할 수 있도록 하는 것이 중요합니다. 키보드 컨트롤과 같은 대체 상호 작용 방법을 제공하여 애플리케이션을 포용적으로 만들 수 있습니다.