사용자가 브라우저 창 외부에서 데이터를 공유할 수 있도록 합니다.
HTML5 드래그 앤 드롭 API 및 클립보드 이벤트의 일부인 DataTransfer API에 대해 들어보셨을 것입니다. 소스와 수신 대상 간에 데이터를 전송하는 데 사용할 수 있습니다.
드래그 앤 드롭 및 복사하여 붙여넣기 상호작용은 페이지 내에서 간단한 텍스트를 A에서 B로 전송하는 상호작용에 자주 사용됩니다. 하지만 이러한 상호작용을 사용하여 브라우저 창을 넘어설 수 있다는 사실은 종종 간과됩니다.
브라우저의 기본 제공 드래그 앤 드롭과 복사 붙여넣기 상호작용은 웹이든 다른 애플리케이션이든 다른 애플리케이션과 통신할 수 있으며 출처에 연결되지 않습니다. 이 API는 데이터가 전송되는 위치에 따라 서로 다른 동작을 가진 여러 데이터 항목을 지원합니다. 웹 애플리케이션은 수신 이벤트를 수신 대기할 때 전송된 데이터를 주고받을 수 있습니다.
이 기능은 데스크톱 웹 애플리케이션의 공유 및 상호 운용성에 대한 생각을 바꿀 수 있습니다. 애플리케이션 간에 데이터를 전송할 때 더 이상 긴밀하게 결합된 통합에 의존할 필요가 없습니다. 대신 사용자에게 데이터를 원하는 위치로 전송할 수 있는 전체 제어 권한을 부여할 수 있습니다.
데이터 전송
시작하려면 드래그 앤 드롭 또는 복사 붙여넣기를 구현해야 합니다. 아래 예에서는 드래그-드롭 상호작용을 보여주지만 복사하여 붙여넣기 프로세스는 유사합니다. 드래그 앤 드롭 API에 익숙하지 않다면 자세한 내용을 설명하는 HTML5 드래그 앤 드롭 설명 문서를 참고하세요.
MIME 유형 키 데이터를 제공하면 외부 애플리케이션과 자유롭게 상호작용할 수 있습니다. 대부분의 WYSIWYG 편집기, 텍스트 편집기 및 브라우저는 아래 예에 사용된 '기본' MIME 유형에 응답합니다.
document.querySelector('#dragSource')
.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text/plain', 'Foo bar');
event.dataTransfer.setData('text/html', '<h1>Foo bar</h1>');
event.dataTransfer.setData('text/uri-list', 'https://example.com');
});
event.dataTransfer
속성을 확인합니다. 그러면 DataTransfer
인스턴스가 반환됩니다. 이 객체는 다른 이름의 속성에서 반환되는 경우도 있습니다.
데이터 전송을 수신하는 방법은 데이터 전송을 제공하는 것과 거의 동일합니다. 수신 이벤트(drop
또는 paste
)를 수신 대기하고 키를 읽습니다. 요소 위로 드래그할 때 브라우저에서는 데이터의 type
키에만 액세스할 수 있습니다. 데이터 자체는 게시 후에만 액세스할 수 있습니다.
document.querySelector('#dropTarget')
.addEventListener('dragover', (event) => {
console.log(event.dataTransfer.types);
// Without this, the drop event won't fire.
event.preventDefault();
});
document.querySelector('#dropTarget')
.addEventListener('drop', (event) => {
// Log all the transferred data items to the console.
for (let type of event.dataTransfer.types) {
console.log({ type, data: event.dataTransfer.getData(type) });
}
event.preventDefault();
});
애플리케이션 전반에서 널리 지원되는 세 가지 MIME 유형은 다음과 같습니다.
text/html
:contentEditable
요소 및 Google Docs, Microsoft Word 등의 서식 있는 텍스트 (WYSIWYG) 편집기에서 HTML 페이로드를 렌더링합니다.text/plain:
입력 요소의 값, 코드 편집기의 콘텐츠,text/html
의 대체 값을 설정합니다.text/uri-list
: URL 표시줄이나 브라우저 페이지에 드롭하면 URL로 이동합니다. 디렉터리나 바탕화면에 드롭하면 URL 바로가기가 생성됩니다.
WYSIWYG 편집자는 text/html
를 광범위하게 채택하여 매우 유용합니다. HTML 문서에서처럼 데이터 URL 또는 공개적으로 액세스할 수 있는 URL을 사용하여 리소스를 삽입할 수 있습니다. 이는 시각 자료 (예: 캔버스에서)를 Google Docs와 같은 편집기로 내보내는 데 적합합니다.
const redPixel = 'data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=';
const html = '<img src="' + redPixel + '" width="100" height="100" alt="" />';
event.dataTransfer.setData('text/html', html);
복사하여 붙여넣기를 사용한 전송
복사-붙여넣기 상호작용과 함께 DataTransfer API를 사용하는 방법은 다음과 같습니다. 클립보드 이벤트의 경우 clipboardData
라는 속성에서 DataTransfer
객체를 반환합니다.
// Listen to copy-paste events on the document.
document.addEventListener('copy', (event) => {
const copySource = document.querySelector('#copySource');
// Only copy when the `activeElement` (i.e., focused element) is,
// or is within, the `copySource` element.
if (copySource.contains(document.activeElement)) {
event.clipboardData.setData('text/plain', 'Foo bar');
event.preventDefault();
}
});
document.addEventListener('paste', (event) => {
const pasteTarget = document.querySelector('#pasteTarget');
if (pasteTarget.contains(document.activeElement)) {
const data = event.clipboardData.getData('text/plain');
console.log(data);
}
});
맞춤 데이터 형식
원시 MIME 유형으로 제한되지 않으며 어떤 키든 사용하여 전송된 데이터를 식별할 수 있습니다. 이는 애플리케이션 내에서 브라우저 간 상호작용에 유용할 수 있습니다. 아래와 같이 JSON.stringify()
및 JSON.parse()
함수를 사용하여 더 복잡한 데이터를 전송할 수 있습니다.
document.querySelector('#dragSource')
.addEventListener('dragstart', (event) => {
const data = { foo: 'bar' };
event.dataTransfer.setData('my-custom-type', JSON.stringify(data));
});
document.querySelector('#dropTarget')
.addEventListener('dragover', (event) => {
// Only allow dropping when our custom data is available.
if (event.dataTransfer.types.includes('my-custom-type')) {
event.preventDefault();
}
});
document.querySelector('#dropTarget')
.addEventListener('drop', (event) => {
if (event.dataTransfer.types.includes('my-custom-type')) {
event.preventDefault();
const dataString = event.dataTransfer.getData('my-custom-type');
const data = JSON.parse(dataString);
console.log(data);
}
});
웹 연결
맞춤 형식은 개발자가 제어하는 애플리케이션 간의 통신에 적합하지만, 개발자가 사용하는 형식이 아닌 애플리케이션으로 데이터를 전송할 때는 사용자를 제한합니다. 웹에서 서드 파티 애플리케이션과 연결하려면 범용 데이터 형식이 필요합니다.
JSON-LD (연결된 데이터) 표준이 이를 위한 적합한 후보입니다. 가볍고 JavaScript에서 읽고 쓰기 쉽습니다. Schema.org에는 사용할 수 있는 사전 정의된 유형이 많이 포함되어 있으며 맞춤 스키마 정의도 옵션입니다.
const data = {
'@context': 'https://schema.org',
'@type': 'ImageObject',
contentLocation: 'Venice, Italy',
contentUrl: 'venice.jpg',
datePublished: '2010-08-08',
description: 'I took this picture during our honey moon.',
name: 'Canal in Venice',
};
event.dataTransfer.setData('application/ld+json', JSON.stringify(data));
Schema.org 유형을 사용할 때는 일반적인 Thing 유형으로 시작하거나 Event, Person, MediaObject, Place와 같이 사용 사례에 더 가까운 유형을 사용하거나 필요한 경우 MedicalEntity와 같이 매우 구체적인 유형을 사용할 수 있습니다. TypeScript를 사용하는 경우 schema-dts 유형 정의의 인터페이스 정의를 사용할 수 있습니다.
JSON-LD 데이터를 송수신함으로써 더욱 연결된 개방형 웹을 지원할 수 있습니다. 동일한 언어를 사용하는 애플리케이션을 사용하면 외부 애플리케이션과의 심층 통합을 만들 수 있습니다. 복잡한 API 통합이 필요하지 않습니다. 필요한 모든 정보가 전송된 데이터에 포함되어 있습니다.
캘린더의 일정을 좋아하는 할 일 앱에 공유하고, 이메일에 가상 파일을 첨부하고, 연락처를 공유하는 등 제한 없이 (웹) 애플리케이션 간에 데이터를 전송할 수 있는 모든 가능성을 생각해 보세요. 좋을 것 같네요. 여러분과 함께 시작합니다. 🙌
문제
DataTransfer API는 현재 사용할 수 있지만 통합하기 전에 알아야 할 몇 가지 사항이 있습니다.
브라우저 호환성
데스크톱 브라우저는 모두 위에 설명된 기법을 잘 지원하지만 휴대기기는 그렇지 않습니다. 이 기술은 모든 주요 브라우저 (Chrome, Edge, Firefox, Safari)와 운영체제 (Android, ChromeOS, iOS, macOS, Ubuntu Linux, Windows)에서 테스트되었지만 Android와 iOS는 테스트를 통과하지 못했습니다. 브라우저가 계속 개발되고 있지만 현재 이 기법은 데스크톱 브라우저로만 제한됩니다.
발견 가능성
드래그 앤 드롭과 복사 붙여넣기는 데스크톱 컴퓨터에서 작업할 때의 시스템 수준 상호작용으로, 40년이 넘은 첫 번째 GUI에 그 뿌리를 두고 있습니다. 파일을 정리하기 위해 이러한 상호작용을 사용한 횟수를 생각해 보세요. 이는 아직 웹에서 흔하지 않습니다.
사용자에게 이 새로운 상호작용에 관해 알리고 UX 패턴을 마련하여 이를 인식할 수 있도록 해야 합니다. 특히 지금까지 컴퓨터 사용 경험이 휴대기기에 국한되어 있는 사용자에게 UX 패턴을 제시해야 합니다.
접근성
드래그 앤 드롭은 접근성이 높지 않지만 DataTransfer API는 복사 붙여넣기에서도 작동합니다. 복사하여 붙여넣기 이벤트를 수신 대기해야 합니다. 추가 작업이 많이 필요하지 않으며 사용자는 추가 작업을 해주면 감사하게 됩니다.
보안 및 개인 정보 보호
이 기법을 사용할 때는 몇 가지 보안 및 개인 정보 보호 고려사항을 알고 있어야 합니다.
- 클립보드 데이터는 사용자 기기의 다른 애플리케이션에서 사용할 수 있습니다.
- 드래그하는 웹 애플리케이션은 데이터가 아닌 유형 키에 액세스할 수 있습니다. 데이터는 드롭 또는 붙여넣기 시점에만 사용할 수 있습니다.
- 수신된 데이터는 다른 사용자 입력과 마찬가지로 취급해야 합니다. 사용하기 전에 정리 및 검증을 거쳐야 합니다.
Transmat 도우미 라이브러리 시작하기
애플리케이션에서 DataTransfer API를 사용하는 데 관심이 있나요? GitHub의 Transmat 라이브러리를 살펴보세요. 이 오픈소스 라이브러리는 브라우저 차이를 조정하고, JSON-LD 유틸리티를 제공하며, 드롭 영역 강조 표시를 위한 전송 이벤트에 응답하는 관찰자를 포함하고, 기존 드래그 앤 드롭 구현 간에 데이터 전송 작업을 통합할 수 있도록 지원합니다.
import { Transmat, TransmatObserver, addListeners } from 'transmat';
// Send data on drag/copy.
addListeners(myElement, 'transmit', (event) => {
const transmat = new Transmat(event);
transmat.setData({
'text/plain': 'Foobar',
'application/json': { foo: 'bar' },
});
});
// Receive data on drop/paste.
addListeners(myElement, 'receive', (event) => {
const transmat = new Transmat(event);
if (transmat.hasType('application/json') && transmat.accept()) {
const data = JSON.parse(transmat.getData('application/json'));
}
});
// Observe transfer events and highlight drop areas.
const obs = new TransmatObserver((entries) => {
for (const entry of entries) {
const transmat = new Transmat(entry.event);
if (transmat.hasMimeType('application/json')) {
entry.target.classList.toggle('drag-over', entry.isTarget);
entry.target.classList.toggle('drag-active', entry.isActive);
}
}
});
obs.observe(myElement);
감사의 말씀
Unsplash의 Luba Ertel님 제공 히어로 이미지