클립보드 API 및 이벤트

W3C 작업 초안,

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2025/WD-clipboard-apis-20251124/
최신 공개 버전:
https://www.w3.org/TR/clipboard-apis/
에디터스 드래프트:
https://w3c.github.io/clipboard-apis/
이전 버전:
히스토리:
https://www.w3.org/standards/history/clipboard-apis/
피드백:
GitHub
명세 내 인라인
편집자:
(Microsoft)
(Microsoft)
이전 편집자:
(Google)
(Microsoft)
(Mozilla)
(Microsoft)
설명서:
비동기 클립보드 API 설명서

요약

이 문서는 시스템 클립보드의 데이터에 접근하기 위한 API를 설명합니다. 기본 클립보드 동작(잘라내기, 복사, 붙여넣기)을 재정의하는 작업과 클립보드 내용을 직접적으로 접근하는 작업을 제공합니다.

이 문서의 상태

이 섹션은 본 문서가 발행된 시점에서의 상태를 설명합니다. 현재 W3C의 발행 목록과 이 기술 보고서의 최신 판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.

본 문서는 Web Editing Working Group에서 작업 초안으로 권고안 경로를 사용하여 발행하였습니다.
작업 초안으로 발행되었다고 해서 W3C 및 그 회원들의 공식적인 승인이나 지지를 의미하지는 않습니다.

이 문서는 초안 문서로, 언제든지 다른 문서로 대체·수정·폐기될 수 있습니다.
진행 중인 작업 이외의 인용은 적절하지 않습니다.

이 문서의 변경 사항은 https://github.com/w3c/clipboard-apis에서 추적할 수 있습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었습니다. W3C는 그룹 산출물과 관련되는 공개 특허 공개 목록을 유지하고 있으며, 해당 페이지에는 특허 공개 방법도 안내되어 있습니다. 특정 특허가 필수 청구항(Essential Claim)을 포함한다고 실제로 인지한 개인은 W3C 특허 정책 6절에 따라 반드시 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 절차 문서의 규율을 받습니다.

1. 소개

이 섹션은 규범적이지 않습니다.

이 명세서는 시스템 클립보드가 웹 애플리케이션에 어떻게 노출되는지 정의합니다.

이 명세서에는 두 가지 일반적인 API가 설명되어 있습니다:

2. 사용 사례

이 섹션은 규범적이지 않습니다.

2.1. 기본 클립보드 동작 변경

기본 클립보드 작업(잘라내기/복사/붙여넣기)을 변경하고 싶은 다양한 시나리오가 있습니다. 몇 가지 예시를 들면 다음과 같습니다:

2.2. 원격 클립보드 동기화

원격 기기와 통신하는 웹 애플리케이션(예: 원격 액세스 또는 원격 셸 애플리케이션)에서는 클립보드 데이터가 두 기기 간에 동기화되어야 할 필요가 자주 있습니다.

이 사용 사례에서 중요한 점은 사용자 제스처나 상호작용 없이도 클립보드에 접근해야 한다는 것입니다.

원격 기기에서 로컬 클립보드로 클립보드 데이터를 복사하려면, 웹 애플리케이션이 원격 클립보드 데이터를 가져와 write() 메서드를 통해 로컬 클립보드에 데이터를 씁니다.
로컬 클립보드 데이터를 원격 기기로 복사하려면, 웹 애플리케이션이 clipboardchange 이벤트를 감지하고, 클립보드가 업데이트될 때마다 read() 메서드로 클립보드에서 새로운 데이터를 읽은 후, 그 데이터를 원격 기기로 전송합니다.

2.3. 클립보드 작업 트리거

사용자 에이전트에 대체 인터페이스를 제공하는 애플리케이션은 때때로 사용자 에이전트에서 클립보드 작업을 트리거할 필요가 있습니다.

예를 들어, 보다 접근성 높은 인터페이스를 제공하는 화면 판독기 애플리케이션을 생각해 볼 수 있습니다. 이 판독기는 콘텐츠를 표시하고 사용자가 상호작용할 수 있도록 하지만, 클립보드 복사와 같은 작업은 브라우저에서 수행되어야 클립보드 콘텐츠가 올바르게(브라우저가 복사 시 추가하는 메타데이터 포함) 설정됩니다.

3. 용어 정리

editable contextediting host이거나 textarea 요소, 또는 type 속성이 "text", "search", "tel", "url", "email", "password", "number" 중 하나로 설정된 input 요소를 의미합니다.

4. 모델

플랫폼은 시스템 클립보드를 제공합니다.

시스템 클립보드는 여러 시스템 클립보드 아이템의 목록을 가지고 있으며, 이들은 총칭해서 시스템 클립보드 데이터라 부릅니다.

시스템 클립보드 아이템은 여러 시스템 클립보드 표현의 목록을 가집니다.

시스템 클립보드 표현은 문자열인 name과 바이트 시퀀스인 data를 가집니다.

5. 클립보드 이벤트

5.1. 클립보드 이벤트 인터페이스

ClipboardEvent 인터페이스는 Event 인터페이스를 확장합니다.

dictionary ClipboardEventInit : EventInit {
  DataTransfer? clipboardData = null;
};
clipboardData

이 이벤트와 관련된 데이터 및 메타데이터를 저장하는 DataTransfer 객체입니다.

[Exposed=Window]
interface ClipboardEvent : Event {
  constructor(DOMString type, optional ClipboardEventInit eventInitDict = {});
  readonly attribute DataTransfer? clipboardData;
};
clipboardData

clipboardData 속성은 DataTransfer 인터페이스의 인스턴스로, 스크립트가 사용자가 복사, 잘라내기, 붙여넣기 작업을 할 때 시스템 클립보드의 값을 읽고 조작할 수 있도록 합니다. 관련 drag data store는 시스템 클립보드의 필터링된 실시간 뷰로, 구현체가 스크립트가 안전하게 접근할 수 있다고 아는 필수 데이터 타입만 노출합니다. 합성 이벤트에서는 drag data store에 이벤트를 생성한 스크립트가 추가한 데이터만 포함됩니다.

clipboardData 객체의 itemsfiles 속성을 통해 클립보드에서 다중 파트 혹은 비텍스트 데이터를 처리할 수 있습니다.

이 인터페이스는 이벤트를 생성하는 데 사용할 수 있습니다. 아래는 예시입니다:

var pasteEvent = new ClipboardEvent('paste');
pasteEvent.clipboardData.items.add('My string', 'text/plain');
document.dispatchEvent(pasteEvent);

참고: 합성 클립보드 이벤트는 실제로 클립보드나 문서를 변경하지 않습니다. 즉, 위의 스크립트는 paste 이벤트를 발생시키지만, 데이터가 문서에 붙여넣어지지는 않습니다.

5.2. 클립보드 이벤트

5.2.1. clipboardchange 이벤트

clipboardchange 이벤트는 시스템 클립보드의 내용이 변경될 때마다 발생합니다. 이러한 변경은 다음과 같은 원인(포괄적이지 않음)일 수 있습니다:

5.2.1.1. clipboardchange 이벤트 발생 단계

Document document에 대해 clipboardchange 이벤트를 발생시키려면:

  1. document지속적 활성화가 없고 document에 클립보드에서 읽기 권한이 없다면, 반환합니다.

  2. globaldocument관련 글로벌 객체로 둡니다.

  3. document시스템 포커스가 있는 경우:

    1. types시스템 클립보드에서 사용 가능한 필수 데이터 타입의 목록으로 둡니다.

    2. changeIddocument를 인자로 하여 changeId 생성을 실행한 결과로 둡니다.

    3. eventInit를 새 ClipboardChangeEventInit 딕셔너리로 두고, types 멤버는 types로, changeId 멤버는 changeId로 설정합니다.

    4. ClipboardChangeEventeventInit을 사용하여, global에서 clipboardchange라는 이름의 이벤트를 발생시킵니다.

  4. document시스템 포커스가 없는 경우:

    1. documentclipboardchange 보류 플래그를 true로 설정합니다.

사용자 에이전트는 이벤트가 전달되기 전에 새 변경 사항에 의해 대체된 클립보드 변경에 대해 clipboardchange 이벤트 발생을 건너뛸 수 있습니다(MAY). 이 최적화는 클립보드가 빠르게 연속 변경되는 상황에서 성능을 높일 수 있습니다. 왜냐하면 오래된 변경 알림을 전달하는 것은 웹 애플리케이션에 가치 없이 처리 리소스만 소모하기 때문입니다.

5.2.1.2. 문서 포커스 단계

Document document시스템 포커스를 얻을 때:

  1. documentclipboardchange 보류 플래그가 true이면:

    1. documentclipboardchange 보류 플래그를 false로 설정한다.

    2. types시스템 클립보드에서 사용 가능한 필수 데이터 타입의 목록으로 둔다.

    3. changeIddocument를 인자로 하여 changeId 생성을 실행한 결과로 둔다.

    4. eventInit을 새 ClipboardChangeEventInit 딕셔너리로 두고, types 멤버는 types로, changeId 멤버는 changeId로 설정한다.

    5. globaldocument관련 글로벌 객체로 둔다.

    6. eventInit을 사용하여, global에서 clipboardchange라는 이름의 이벤트를 ClipboardChangeEvent발생시킨다.

중첩된 브라우징 컨텍스트의 문서의 경우, clipboardchange 이벤트는 각 Document 에서 자신의 포커스 상태에 따라 독립적으로 발생합니다. 클립보드 변경은 시스템 포커스가 있는 단일 문서(그 문서에 지속적 활성화 또는 영구적인 클립보드 권한이 있는 경우)에 대해 이벤트를 발생시킵니다.

참고: clipboardchange 이벤트는 지속적 활성화 이후에만 사용할 수 있으며, 문서에 클립보드에서 읽기 위한 영구 권한이 없는 한 그렇습니다. 영구 클립보드 권한을 지원하는 사용자 에이전트에서는, 해당 권한이 있는 사이트가 sticky activation 없이도 clipboardchange 이벤트를 받을 수 있습니다. 왜냐하면 그 권한이 이미 더 민감한 클립보드 데이터에 접근 권한을 부여하기 때문입니다.

changeId 는 각 클립보드 변경 작업에 대한 고유 식별자를 제공합니다. 동일한 클립보드 변경에 대해 동일한 storage key를 가진 모든 창과 탭은 동일한 changeId 값을 가진 이벤트를 받으므로, 여러 창이 있을 때도 한 번만 이벤트를 처리하도록 중복 처리가 가능합니다. 이 식별자는 storage key에 한정되며 교차 storage key 상관 기능은 제공하지 않습니다.

clipboardchange 이벤트는 버블링되지 않으며 취소도 불가능합니다. 이 이벤트는 사용자 동작이 아니라 시스템 클립보드의 상태 변화에 의해 트리거되기 때문입니다.

dictionary ClipboardChangeEventInit : EventInit {
  sequence<DOMString> types = [];
  bigint changeId = 0;
};
types

시스템 클립보드에 존재하는 필수 데이터 유형DOMString 시퀀스로 반환합니다.

changeId

클립보드 변경 작업에 대한 고유 식별자를 나타내는 bigint입니다.

[Exposed=Window]
interface ClipboardChangeEvent : Event {
  constructor(DOMString type, optional ClipboardChangeEventInit eventInitDict = {});
  readonly attribute FrozenArray<DOMString> types;
  readonly attribute bigint changeId;
};
types

이 이벤트가 발생할 때 시스템 클립보드에 사용 가능한 필수 데이터 유형을 나타내는 FrozenArray DOMString 객체를 반환합니다. 옵션 데이터 유형과 커스텀 포맷은 지문 수집 표면을 줄이기 위해 제외됩니다.

changeId

이 특정 클립보드 변경 작업에 대한 고유 식별자를 나타내는 bigint 를 반환합니다. 이 식별자는 동일한 storage key를 가진 모든 창과 탭에서 동일한 클립보드 변경에 대해 일치하므로, 여러 창에서 동일한 클립보드 변경 알림이 발생할 때 이벤트를 중복 처리하지 않도록 할 수 있습니다.

changeId 는 암호학적으로 파생된 128비트 정수입니다. 클립보드에 무언가를 쓴 후에는 changeId 값이 쓰기 전과 다른 값이 나올 것이라는 보장만 있습니다.

5.2.1.3. ClipboardChangeEvent 생성자 단계

ClipboardChangeEvent(type, eventInitDict) 생성자 단계는 다음과 같습니다:

  1. this.typeseventInitDict["types"]의 복제본(clone)으로 설정합니다.

  2. this.changeIdeventInitDict["changeId"]로 설정합니다.

5.2.1.4. ChangeId 생성

Document document에 대해 changeId 생성은 다음 단계를 따릅니다:

  1. globalChangeId를 현재 시스템 클립보드 상태를 나타내는 사용자 에이전트 고유 식별자로 둡니다. 이 값은 시스템 클립보드가 변경될 때마다 바뀌며, 사용자 에이전트가 재시작되면 초기화됩니다.

  2. storageKeydocument비스토리지 목적의 스토리지 키 얻기 실행 결과로 둡니다.

  3. storageKeyBytesstorageKey의 사용자 에이전트 고유 이진 표현으로 둡니다.

  4. hashedValueglobalChangeId(바이트)와 storageKeyBytes를 이어붙인 값에 대해 암호화 해시 함수(예: SHA-256)를 적용한 결과로 둡니다.

  5. hashedValue에서 파생된 128비트 정수를 반환합니다(예: 해시 출력의 처음 128비트).

위 알고리즘은 동일한 출처, 동일 파티셔닝인 문서에 대해 동일한 클립보드 변경에는 동일한 change ID를 반환해 여러 창/탭에서의 이벤트 중복을 예방합니다. 파티션 간 추적에 사용될 수 있는 교차 파티션 상관 기능은 불가능하며, 클라이언트 측 저장소 파티셔닝 변경이 도입될 때도 자동 익명성을 제공합니다.

changeId 는 브라우저 재시작 시 유지되지 않습니다. 왜냐하면 globalChangeId 카운터가 재시작 시 초기화되기 때문입니다. 마찬가지로 사이트 데이터를 지우면, 해당 탭은 새로고침되어야 하고, 새 이벤트 리스너는 앞으로 발생하는 새로운 changeId에 대한 이벤트만 받습니다.

합성 cutcopy 이벤트는 시스템 클립보드를 변경하지 않으므로, "clipboardchange" 이벤트를 트리거하지 않습니다.

clipboardchange 이벤트를 사용하면 웹 애플리케이션이 효율적으로 클립보드 변경을 감지해, 사용 가능한 데이터 포맷에 따라 동적으로 UI를 업데이트할 수 있습니다:
// 다중 창 앱은 처리된 changeId를 추적해 중복을 피합니다.
const processedChangeIds = new Set();

// 클립보드 변경 이벤트 리스너 등록
navigator.clipboard.addEventListener('clipboardchange', (e) => {
  // 여러 창에서 동일 changeId 중복 방지
  if (processedChangeIds.has(e.changeId)) {
    return; // 이미 처리한 변경입니다.
  }
  processedChangeIds.add(e.changeId);
				
  // 클립보드의 데이터 유형 확인
  const hasText = e.types.includes('text/plain');
  const hasHTML = e.types.includes('text/html');
  const hasImage = e.types.includes('image/png');
				
  // 사용 가능한 포맷에 따라 UI 갱신
  document.getElementById('paste-text-btn').disabled = !hasText;
  document.getElementById('paste-html-btn').disabled = !hasHTML;
  document.getElementById('paste-image-btn').disabled = !hasImage;
				
  // 원격 데스크톱 앱은 changeId당 한 번만 동기화
  if (hasText || hasHTML || hasImage) {
    syncClipboardToRemote(e.changeId);
  }
});

// 또는, onclipboardchange 속성을 사용할 수도 있습니다.
// navigator.clipboard.onclipboardchange = (e) => { ... };

이벤트 기반 방식은 read() 또는 readText() 로 폴링하는 것보다 효율적이며, 클립보드 접근에 사용자 활성화를 요구하는 브라우저에서도 동작합니다. UI가 타이머 대기 없이 클립보드 변경에 즉시 반응할 수 있기 때문입니다. changeId 는 여러 창을 가진 앱에 특히 유용하며, 동일 storage key를 가진 모든 창에서 각 클립보드 변경을 한 번만 처리하도록 해줍니다.

5.2.2. copy 이벤트

사용자가 복사 작업을 시작하면, 사용자 에이전트는 클립보드 이벤트 copy를 발생시킵니다.

이 이벤트가 취소되지 않으면, 현재 선택된 데이터가 시스템 클립보드에 복사됩니다. 현재 문서의 선택 영역은 영향을 받지 않습니다.

copy 이벤트는 버블링되며, 취소 가능하고, composed입니다.

이 이벤트의 처리 모델에 대한 자세한 설명은 § 8.1 복사 동작을 참고하세요.

합성 copy 이벤트를 수동으로 생성하여 디스패치할 수 있지만, 시스템 클립보드의 내용에는 영향을 주지 않습니다.

5.2.3. cut 이벤트

사용자가 잘라내기 작업을 시작하면, 사용자 에이전트는 클립보드 이벤트 cut를 발생시킵니다.

editable context에서, 이벤트가 취소되지 않으면 선택된 데이터가 시스템 클립보드에 저장되고 문서에서 선택 영역이 제거됩니다. cut 이벤트는 선택 영역이 제거되기 전에 발생합니다. 잘라내기 작업이 완료되면 선택이 접힙니다.

비-editable context에서는 clipboardData 가 빈 리스트입니다. 이 경우에도 cut 이벤트는 여전히 발생합니다.

cut 이벤트는 버블링되며, 취소 가능하고, composed입니다.

이 이벤트의 처리 모델에 대한 자세한 설명은 § 8.2 잘라내기 동작을 참고하세요.

합성 cut 이벤트를 수동으로 생성하여 디스패치할 수 있지만, 문서나 시스템 클립보드의 내용에는 영향을 주지 않습니다.

5.2.4. paste 이벤트

사용자가 붙여넣기 작업을 시작하면, 사용자 에이전트는 클립보드 이벤트 paste를 발생시킵니다. 이 이벤트는 클립보드 데이터가 문서에 삽입되기 전에 발생합니다.

커서가 editable context에 있으면, 붙여넣기 동작은 해당 컨텍스트에서 지원하는 가장 적합한 포맷(있는 경우)으로 클립보드 데이터를 삽입합니다.

비-editable context에서는 붙여넣기 동작이 아무런 영향을 미치지 않지만, paste 이벤트는 항상 발생합니다.

paste 이벤트는 버블링되며, 취소 가능하고, composed입니다.

이 이벤트의 처리 모델에 대한 자세한 설명은 § 8.3 붙여넣기 동작을 참고하세요.

합성 paste 이벤트를 수동으로 생성하여 디스패치할 수 있지만, 문서의 내용에는 영향을 주지 않습니다.

5.3. 다른 스크립트 및 이벤트와의 통합

5.3.1. 클립보드 수정을 허용하는 이벤트 핸들러

다음 조건 중 하나라도 true이면, 이벤트 핸들러는 클립보드에 쓸 수 있습니다:

구현체는 해당 이벤트 타입이 사용자 의도를 반영한다고 판단될 경우, 다른 신뢰할 수 있는 이벤트 타입에도 클립보드 수정 권한을 허용할 수 있습니다. 또한 구현체가 특정 사이트나 앱에 원천 스레드와 무관하게 클립보드 수정을 신뢰하도록 구성할 수도 있습니다.

합성 cutcopy 이벤트는 시스템 클립보드의 데이터를 수정해서는 안 됩니다.

5.3.2. 클립보드 읽기를 허용하는 이벤트 핸들러

다음 조건 중 하나라도 true이면, 이벤트 핸들러는 시스템 클립보드에서 데이터를 읽을 수 있습니다:

합성 paste 이벤트는 스크립트에 실제 시스템 클립보드의 데이터 접근 권한을 주어서는 안 됩니다.

5.3.3. 서식 있는 텍스트 편집 API와의 통합

구현체가 스크립트를 통해 클립보드 명령을 실행하는 방법을 지원하는 경우, 예를 들어 document.execCommand() 메서드에 "cut", "copy", "paste" 명령을 넘기는 방식이라면, 구현체는 반드시 해당 동작을 트리거하고, 그에 따라 관련 클립보드 이벤트를 디스패치해야 합니다.

스크립팅 API를 통해 복사, 잘라내기, 붙여넣기 동작을 트리거할 때 따라야 할 단계는 다음과 같습니다:

  1. 해당 동작을 동기적으로 실행합니다.

  2. 동작의 반환값을 API 호출의 반환값으로 사용합니다.

참고: 스크립팅 API를 통해 트리거된 복사 및 잘라내기 명령은 이벤트가 신뢰되고 사용자가 트리거한 경우 또는 구현체가 이를 허용하도록 설정된 경우에만 실제 클립보드 내용을 변경합니다. 붙여넣기 명령은 구현체가 허용하도록 설정된 경우에만 paste 이벤트를 발생시키고 클립보드 내용에 접근할 수 있습니다. 구현체가 클립보드 읽기 및 쓰기 접근을 허용하도록 구성하는 방법은 이 명세서의 범위에 포함되지 않습니다.

5.3.4. 다른 이벤트와의 상호작용

클립보드 작업이 키보드 입력에 의해 트리거된 경우, 구현체는 반드시 해당 클립보드 작업을 시작하는 이벤트를 발생시켜야 합니다. 이 이벤트는 비동기적이지만, 반드시 관련 키의 keyup 이벤트 전에 디스패치되어야 합니다.

잘라내기 및 붙여넣기 작업은 구현체가 지원하는 다른 이벤트(예: textInput, input, change, validation 이벤트, DOMCharacterDataModified, DOMNodeRemoved / DOMNodeInserted 등)를 발생시킬 수 있습니다. 이러한 이벤트는 cut/paste 이벤트 처리 후에 큐에 따라 발생합니다.

구현체는 복사 작업에 대해 textInput, input, change, validation과 같은 다른 입력 관련 이벤트를 발생시켜서는 안 됩니다.

5.3.5. 선택 영역이나 포커스를 수정하는 이벤트 리스너

이벤트 리스너가 선택 영역이나 포커스 가능한 영역을 수정한 경우, 클립보드 동작은 반드시 수정된 선택 영역에서 완료되어야 합니다.

6. 클립보드 이벤트 API

클립보드 이벤트 API를 사용하면 사용자 에이전트의 기본 잘라내기, 복사, 붙여넣기 동작을 오버라이드할 수 있습니다.

클립보드 접근은 표준 DataTransfer 메서드를 사용하여 items 를 변형합니다. 이 작업은 ClipboardEventclipboardData 속성을 통해 이루어집니다. 이 API들은 ClipboardEvent 핸들러의 컨텍스트 내에서만 클립보드 데이터에 접근할 수 있습니다.

참고: 클립보드 이벤트 핸들러 외부에서 클립보드에 접근해야 한다면 § 7 비동기 클립보드 API를 참고하세요.

참고: 클립보드 이벤트 API는 동기적이므로, 할 수 있는 작업에 제한이 있습니다. 권한 요청이나 이미지 트랜스코딩 같은 잠재적으로 블로킹되는 동작은 지원하지 않습니다. 블로킹 또는 시간이 오래 걸리는 작업을 지원하는 더 강력한 API는 § 7 비동기 클립보드 API를 참고하세요.

6.1. 복사 이벤트 오버라이드

기본 copy 이벤트 동작을 오버라이드하려면 copy 이벤트 핸들러를 추가하고, 이 핸들러에서 preventDefault() 를 호출하여 이벤트를 취소해야 합니다.

이벤트를 취소해야만 시스템 클립보드clipboardData 의 데이터로 업데이트됩니다. ClipboardEvent 가 취소되지 않으면, 현재 문서 선택 영역의 데이터가 복사됩니다.

// 클립보드에 복사되는 내용을 덮어쓰는 예시
document.addEventListener('copy', function(e) {
  // e.clipboardData는 처음에 비어 있지만, 복사하려는 데이터를 직접 설정할 수 있습니다.
  e.clipboardData.setData('text/plain', 'Hello, world!');
  e.clipboardData.setData('text/html', '<b>Hello, world!</b>');

  // 현재 문서 선택 영역이 클립보드에 기록되는 것을 막기 위해 반드시 필요합니다.
  e.preventDefault();
});

6.2. 잘라내기 이벤트 오버라이드

기본 cut 이벤트 동작을 오버라이드하려면 cut 이벤트 핸들러를 추가하고, 이 핸들러에서 preventDefault() 를 호출하여 이벤트를 취소해야 합니다.

이벤트를 취소해야만 시스템 클립보드clipboardData 의 데이터로 업데이트됩니다. ClipboardEvent 가 취소되지 않으면, 현재 문서 선택 영역의 데이터가 복사됩니다.

또한 cut 이벤트를 취소하면 문서가 갱신되지 않습니다(즉, 선택 영역이 제거되지 않습니다). 이벤트 핸들러에서 직접 선택된 텍스트를 문서에서 제거하는 작업을 해야 합니다.

// 클립보드에 복사되는 내용을 덮어쓰는 예시
document.addEventListener('cut', function(e) {
  // e.clipboardData는 처음에 비어 있지만, 잘라내기 작업의 일부로 클립보드에 복사할 데이터를 직접 설정할 수 있습니다.
  // 클립보드에 복사할 데이터를 직접 작성합니다.
  e.clipboardData.setData('text/plain', 'Hello, world!');
  e.clipboardData.setData('text/html', '<b>Hello, world!</b>');

  // 잘라내기 작업을 취소할 것이므로, 선택된 텍스트를 직접 문서에서 제거해야 합니다.
  deleteCurrentDocumentSelection();

  // 현재 문서 선택 영역이 클립보드에 기록되는 것을 막기 위해 반드시 필요합니다.
  e.preventDefault();
});

6.3. 붙여넣기 이벤트 오버라이드

기본 paste 이벤트 동작을 오버라이드하려면 paste 이벤트 핸들러를 추가하고, 이 핸들러에서 preventDefault() 를 호출하여 이벤트를 취소해야 합니다.

이벤트를 취소해야만 사용자 에이전트가 시스템 클립보드의 데이터로 문서를 갱신하지 않습니다.

또한 paste 이벤트를 취소하면 문서가 갱신되지 않습니다(즉, 아무것도 문서에 붙여넣어지지 않습니다). 이벤트 핸들러에서 직접 데이터를 문서에 붙여넣는 작업을 해야 합니다.

붙여넣기 시 drag data store mode 플래그가 읽기 전용이므로, setData()paste 이벤트 핸들러에서 호출해도 삽입되는 데이터나 클립보드 데이터에는 영향을 주지 않습니다.

// 클립보드에 붙여넣는 내용을 덮어쓰는 예시
document.addEventListener('paste', function(e) {
  // e.clipboardData에는 곧 붙여넣을 데이터가 들어 있습니다.
  if (e.clipboardData.types.indexOf('text/html') > -1) {
    var oldData = e.clipboardData.getData('text/html');
    var newData = '<b>Ha Ha!</b> ' + oldData;

    // 붙여넣기 작업을 취소할 것이므로, 직접 데이터를 문서에 붙여넣어야 합니다.
    pasteClipboardData(newData);

    // 기본 붙여넣기 동작을 막기 위해 반드시 필요합니다.
    e.preventDefault();
  }
});

6.4. 필수 데이터 타입

구현체는 아래 데이터 타입에 대해 운영체제의 기본 클립보드 포맷 설명을 인식해야 하며, DataTransferItemListClipboardItem 에서 붙여넣기 이벤트에 올바른 설명을 제공하고, 복사/잘라내기 이벤트에 대해 OS 클립보드에 올바른 데이터 포맷을 설정해야 합니다.

6.4.1. 클립보드에서 읽기

아래 데이터 타입은 클립보드에 해당하는 네이티브 타입이 있으면 붙여넣기 이벤트에서 노출되어야 합니다:

6.4.2. 클립보드에 쓰기

아래 데이터 타입은 복사잘라내기 이벤트에서 DataTransfer 객체에 추가될 때, 해당 네이티브 타입 설명과 함께 클립보드에 저장되어야 합니다.

경고! 신뢰되지 않은 스크립트가 클립보드에 쓸 수 있는 데이터 타입은 보안 예방 차원에서 제한되어 있습니다. 신뢰되지 않은 스크립트가 클립보드에 로컬 소프트웨어의 보안 취약점을 유발하는 데이터를 넣으려 시도할 수 있습니다.

6.5. 선택적 데이터 타입

구현체는 아래 데이터 타입에 대해 운영체제의 기본 클립보드 포맷 설명을 인식할 수 있으며, ClipboardItem 에서 붙여넣기 이벤트에 올바른 설명을 제공하고, 복사/잘라내기 이벤트에 대해 OS 클립보드에 올바른 데이터 포맷을 설정할 수 있습니다.

아래 데이터 타입은 클립보드에 해당하는 네이티브 타입이 있으면 UA에서 노출할 수 있습니다:

6.6. 비정제 데이터 타입

이 섹션은 규범적이지 않습니다.

아래 데이터 타입은 UA가 반드시 정제(sanitize)하지 않아야 합니다:

아래 데이터 타입은 UA가 정제하지 않을 수도 있습니다:

선택적 비정제 데이터 타입은 웹 저자가 지정한 mime type 중 UA가 반드시 정제하지 않을 수도 있는 타입입니다. 선택적 비정제 데이터 타입의 유효 목록은 아래와 같습니다:

선택적 비정제 데이터 타입은 프라이버시 요구로 인해 UA에서 지원하지 않을 수 있습니다.

7. 비동기 클립보드 API

partial interface Navigator {
  [SecureContext, SameObject] readonly attribute Clipboard clipboard;
};

7.2. ClipboardItem 인터페이스

typedef Promise<(DOMString or Blob)> ClipboardItemData;

[SecureContext, Exposed=Window]
interface ClipboardItem {
  constructor(record<DOMString, ClipboardItemData> items,
              optional ClipboardItemOptions options = {});

  readonly attribute PresentationStyle presentationStyle;
  readonly attribute FrozenArray<DOMString> types;

  Promise<Blob> getType(DOMString type);

  static boolean supports(DOMString type);
};

enum PresentationStyle { "unspecified", "inline", "attachment" };

dictionary ClipboardItemOptions {
  PresentationStyle presentationStyle = "unspecified";
};
clipboardItem = new ClipboardItem([items, options])
새로운 ClipboardItem 객체를 생성합니다. items표현 목록을 나타내며, 각 표현mime typePromise (해당 mime type에 맞는 Blob 또는 DOMString)를 가집니다. optionsClipboardItemOptions 를 채우는 데 사용할 수 있습니다. 아래 예시 참고.
const format1 = 'text/plain';
const promise_text_blob = Promise.resolve(new Blob(['hello'], {type: format1}));
const clipboardItemInput = new ClipboardItem(
  {[format1]: promise_text_blob},
  {presentationStyle: "unspecified"});
clipboardItem.getType(type)
mime type type에 해당하는 Promise (그 Blob)를 반환합니다.
clipboardItem.types
clipboard item 객체에 포함된 mime type 목록을 반환합니다.
ClipboardItem.supports(type)
type필수 데이터 타입 또는 선택적 데이터 타입에 있으면 true, 아니면 false를 반환합니다.
clipboard item은 사용자가 "잘라내기" 또는 "복사" 명령을 실행함으로써 공유할 의사를 밝힌 데이터입니다. clipboard item은 두 가지 목적을 가집니다. 첫째, 웹사이트가 사용자가 시스템 클립보드에 복사한 데이터를 읽을 수 있게 합니다. 둘째, 웹사이트가 시스템 클립보드에 데이터를 쓸 수 있게 합니다.

예를 들어, 사용자가 네이티브 앱의 스프레드시트에서 셀 범위를 복사하면 하나의 clipboard item이 생성됩니다. 사용자가 데스크톱에서 여러 파일을 복사하면, 그 파일 목록은 여러 clipboard item으로 표현됩니다.

일부 플랫폼은 클립보드에 한 번에 둘 이상의 clipboard item을 허용할 수 있고, 다른 플랫폼은 이전 clipboard item을 새 항목으로 대체합니다.

클립보드 항목표현 목록을 가지고 있으며, 각각의 표현에는 연결된 mime 타입(MIME type), isCustom 플래그(처음엔 false)가 있으며, 이 표현시스템 클립보드의 잘 알려진 포맷이 아니라 웹 커스텀 포맷으로 취급되어야 하는지 나타냅니다. 그리고 data(ClipboardItemData)가 있습니다.

웹 커스텀 포맷isCustomtrue로 설정된 것입니다.

예시에서 사용자가 스프레드시트에서 셀 범위를 복사할 때, 이미지(image/png), HTML 테이블(text/html), 평문(text/plain), 웹 커스텀 포맷(web text/csv) 등 다양한 형태로 표현될 수 있습니다.

MIME 타입은 동일한 clipboard item의 다른 표현을 설명하며, 다양한 fidelity 수준에서 붙여넣기 대상 애플리케이션이 더 쉽게 활용할 수 있게 합니다.

셀 범위를 이미지로 제공하면 사용자가 사진 편집 앱에 붙여넣을 수 있고, text/plain 포맷은 텍스트 편집 앱에서 사용할 수 있습니다.

clipboard item프레젠테이션 스타일 (PresentationStyle)을 가지고, 이는 붙여넣기하는 앱이 clipboard item의 적절한 표현을 붙여넣기 위치에 인라인으로 삽입해야 할지, 첨부파일로 처리해야 할지 구분하는 데 도움을 줍니다. 단일 clipboard item만 지원하는 웹 앱은 첫 번째 clipboard item을 사용해야 합니다.

write() 는 마지막 clipboard item을 선택합니다.

둘 이상의 clipboard item 붙여넣기를 지원하는 웹 앱은 각 clipboard item의 내용을 미리 보여주고 사용자가 어떤 항목을 붙여넣을지 선택할 수 있는 UI를 제공할 수 있습니다. 또한, 앱은 붙여넣을 MIME 타입을 열거하고, 앱별 알고리즘에 따라 가장 적합한 타입을 선택할 수도 있습니다. 또는, "이미지로 붙여넣기", "서식있는 텍스트로 붙여넣기" 등 옵션을 사용자에게 제공할 수도 있습니다. ClipboardItem 객체에는 clipboard item이 연결되어 있으며, 이는 clipboard item입니다. ClipboardItem 객체에는 types array가 연결되어 있으며, 이는 FrozenArray<DOMString> ClipboardItem 객체 생성을 위해 clipboard item clipboardItem과 Realm realm이 주어지면, 다음 단계를 실행합니다:
  1. clipboardItemObjectnew ClipboardItemrealm과 함께 생성합니다.

  2. clipboardItemObjectclipboard itemclipboardItem으로 설정합니다.

new ClipboardItem(items, options) 생성자 단계:
  1. items가 비어 있으면 TypeError를 던진다.

  2. options가 비어 있으면 options["presentationStyle"] = "unspecified"로 설정한다.

  3. thisclipboard item을 새로운 clipboard item으로 설정한다.

  4. thisclipboard itempresentation styleoptions["presentationStyle"]로 설정한다.

  5. typesDOMString의 리스트로 한다.

  6. items의 각 (key, value)에 대해:

    1. representation을 새로운 representation으로 한다.

    2. isCustomfalse로 한다.

    3. key"web " prefix로 시작하면,

      1. "web " prefix를 제거하고 남은 문자열을 key에 할당한다.

      2. isCustomtrue로 설정한다.

    4. representationisCustom 플래그를 isCustom으로 설정한다.

    5. mimeTypeMIME 타입 파싱 결과(key 기준)로 한다.

    6. mimeType이 실패이면 TypeError를 던진다.

    7. thisclipboard itemlist of representationsrepresentationMIME typemimeType이고 [representation/isCustom]이 isCustom인 항목을 포함하면 TypeError를 던진다.

    위 단계는 사용자 에이전트가 잘 아는 mime-type과 저자가 커스텀 타입으로 다루길 원하는 타입 간의 충돌을 방지합니다. 예를 들어 저자의 items 목록에 "text/html" 과 "web text/html" 두 representation이 들어가는 것도 가능합니다.

    1. representationMIME typemimeType으로 설정한다.

    2. representationdatavalue로 설정한다.

    3. representationthisclipboard itemlist of representations에 추가한다.

    4. mimeTypeStringMIME 타입 직렬화(mimeType 기준) 결과로 한다.

    5. isCustomtrue이면 mimeTypeString 앞에 "web "을 붙인다.

    6. mimeTypeStringtypes에 추가한다.

  7. thistypes arraycreate a frozen array(types 기준) 결과로 설정한다.

7.2.1. presentationStyle

presentationStyle getter의 단계는 thisclipboard itempresentation style을 반환하는 것이다.

7.2.2. types

types getter의 단계는 thistypes array를 반환하는 것이다.

7.2.3. getType(type)

이 메서드는 아래 단계를 실행해야 한다:

  1. realmthisrelevant realm으로 한다.

  2. isCustomfalse로 한다.

  3. type"web " prefix로 시작하면:

    1. "web " prefix를 제거하고 남은 문자열을 type에 할당한다.

    2. isCustomtrue로 설정한다.

  4. mimeTypeMIME 타입 파싱(type 기준) 결과로 한다.

  5. mimeType이 실패이면 TypeError를 던진다.

  6. itemTypeListthisclipboard itemlist of representations로 한다.

  7. p새로운 promise(realm 기준)로 한다.

  8. itemTypeList의 각 representation에 대해:

    1. representationMIME typemimeType이고, representationisCustomisCustom이면:

      1. representationDataPromiserepresentationdata로 한다.

      2. representationDataPromise가 settle되면 반응:

        1. representationDataPromise가 값 v로 fulfilled되면:

          1. vDOMString이면 아래 단계를 따른다:

            1. dataAsBytesUTF-8 인코딩(v 기준) 결과로 한다.

            2. blobDataBlob으로 생성한다. 데이터는 dataAsBytes, typemimeType직렬화한 값으로 한다.

            3. pblobData로 resolve한다.

          2. vBlob이면 아래 단계를 따른다:

            1. pv로 resolve한다.

        2. representationDataPromise가 reject되면:

          1. p를 reject한다. 값은 "NotFoundError" DOMException (realm 기준).

            웹 개발자는 실제 rejection 이유에 관심이 있을 수 있습니다.

      3. p를 반환한다.

  9. p를 reject한다. 값은 "NotFoundError" DOMException (realm 기준).

  10. p를 반환한다.

7.2.4. supports(type)

이 메서드는 아래 단계를 실행해야 한다:

  1. type필수 데이터 타입 또는 선택적 데이터 타입에 포함되어 있으면 true를 반환한다.

  2. 그렇지 않으면 false를 반환한다.

7.3. Clipboard 인터페이스

typedef sequence<ClipboardItem> ClipboardItems;

[SecureContext, Exposed=Window]
interface Clipboard : EventTarget {
  Promise<ClipboardItems> read(optional ClipboardUnsanitizedFormats formats = {});
  Promise<DOMString> readText();
  Promise<undefined> write(ClipboardItems data);
  Promise<undefined> writeText(DOMString data);
};

dictionary ClipboardUnsanitizedFormats {
  sequence<DOMString> unsanitized;
};

Clipboard 인터페이스의 일부 메서드는 여러 ClipboardItem 객체를 인자로 받거나 반환할 수 있습니다. 하지만, 모든 플랫폼이 하나 이상의 클립보드 항목을 지원하는 것은 아니며, 이런 플랫폼에서는 아래의 알고리즘에서 write()로 전달된 첫 번째 ClipboardItem 이외의 객체들은 무시되며, read()readText() 는 OS에서 단 하나의 클립보드 항목만 가져옵니다.

clipboard items 객체는 시퀀스 형태의 클립보드 항목들의 집합입니다.

웹 작성자는 data라는 ClipboardItem 배열을 만들어야 시스템 클립보드write(data) 메서드를 사용해 콘텐츠를 쓸 수 있습니다. read()clipboard items 객체에 대한 Promise 를 반환하며, 이 객체는 시스템 클립보드 데이터의 내용을 나타냅니다.

unsanitized시퀀스 형태의 DOMString 들로, 작성자가 옵션 비정제 데이터 타입으로 처리하길 원하는 mime type에 해당합니다.

unsanitized 옵션은 사용자 에이전트에서 지원하지 않을 수 있습니다. 웹 작성자는 unsanitized 에 명시한 MIME 타입의 콘텐츠가 실제로 비정제 상태로 반환된다고 가정해서는 안 됩니다. 이 옵션이 허용되지 않는 개인정보 보호 모드가 있을 수도 있기 때문입니다.

clipboard task source시스템 클립보드 데이터를 읽거나 쓸 때 실행됩니다.

7.3.1. read(formats)

read(formats) 메서드는 다음 단계를 실행해야 합니다:
  1. realmthis관련 realm으로 둡니다.

  2. prealm 안에서의 새 프라미스로 둡니다.

  3. formats가 비어 있지 않으면:

    1. formats["unsanitized"]의 각 format에 대해:

      1. format옵션 비정제 데이터 타입에 없다면 pformat "NotAllowedError" DOMException 으로 realm에서 reject 합니다.

  4. 다음 단계를 병렬로 실행합니다:

    1. r클립보드 읽기 권한 확인을 실행한 결과로 둡니다.

    2. r이 false이면:

      1. 글로벌 태스크 큐잉permission task source 위에서 realm글로벌 객체와 함께 p"NotAllowedError" DOMException 으로 realm에서 reject 하게 합니다.

      2. 이 단계를 중단합니다.

    3. data시스템 클립보드 데이터의 복사본으로 둡니다.

    4. items시퀀스<클립보드 항목>로 둡니다.

    5. data의 각 systemClipboardItem에 대해:

      1. item을 새 클립보드 항목으로 둡니다.

      2. systemClipboardItem의 각 systemClipboardRepresentation에 대해:

        1. mimeTypesystemClipboardRepresentationname을 인자로 OS 특화 포맷에서 잘 알려진 mime type 얻기 알고리즘 실행 결과로 둡니다.

        2. mimeType이 null이면, 이 반복을 건너뜁니다.

        3. representation을 새 표현으로 둡니다.

        4. representationMIME 타입mimeType으로 설정합니다.

        5. isUnsanitizedfalse로 둡니다.

        6. formats가 비어 있지 않으면:

          1. formats["unsanitized"]의 각 format에 대해:

            1. formatMIME 타입과 같으면, isUnsanitized를 true로 설정합니다.

        7. representationdatasystemClipboardRepresentationdata로 resolve 합니다.

          저자는 getType을 호출한 뒤에도 시스템 클립보드에서 데이터를 비동기로 읽을 수 있어야 하지만, 이 단계 집합은 read 시점에 데이터가 제공됨을 암시합니다.

        8. 사용자 에이전트는 representationdata를 정제(sanitize)할 수 있으나, representationMIME 타입의 essence가 "image/png"라면 메타데이터 보존을 위해 정제하지 않아야 하며, 아래 조건을 만족해도 정제하지 않아야 합니다:

          1. representationMIME 타입이 옵션 비정제 데이터 타입 리스트에 포함된 경우.

          2. isUnsanitized가 true인 경우.

        9. representationitem표현 목록에 추가합니다.

        10. isUnsanitizedfalse로 설정합니다.

      3. item표현 목록 크기가 0보다 크면 itemitems에 추가합니다.

    6. items의 크기가 0보다 크면:

      1. firstItemitems[0]로 둡니다.

      2. firstItem에 대해 웹 커스텀 포맷 읽기 알고리즘을 실행합니다.

    7. 그렇지 않으면:

      1. customItem을 새 클립보드 항목으로 둡니다.

      2. customItem에 대해 웹 커스텀 포맷 읽기 알고리즘을 실행합니다.

      3. customItem표현 목록 크기가 0보다 크면 customItemitems에 추가합니다.

    8. 글로벌 태스크 큐잉clipboard task source 위에서 realm글로벌 객체와 함께 아래 단계를 실행하도록 합니다:

      1. clipboardItems시퀀스<ClipboardItem>로 둡니다.

      2. items의 각 클립보드 항목 underlyingItem에 대해:

        1. clipboardItemunderlyingItem, realm을 인자로 ClipboardItem 객체 생성 단계를 실행한 결과로 둡니다.

        2. clipboardItemclipboardItems에 추가합니다.

      3. pclipboardItems로 resolve합니다.

  5. p를 반환합니다.

const items = await navigator.clipboard.read();
const textBlob = await items[0].getType("text/plain");
const text = await (new Response(textBlob)).text();

7.3.2. readText()

The readText() 메서드는 다음 단계를 실행해야 합니다:
  1. realmthis관련 realm으로 둡니다.

  2. prealm 내의 새 프라미스로 둡니다.

  3. 다음 단계를 병렬로 실행합니다:

    1. r클립보드 읽기 권한 확인 실행 결과로 둡니다.

    2. r이 false이면:

      1. 글로벌 태스크 큐잉permission task source 위에서, realm글로벌 객체를 함께, p"NotAllowedError" DOMException 으로 realm에서 reject 하게 합니다.

      2. 이 단계를 중단합니다.

    3. data시스템 클립보드 데이터의 복사본으로 둡니다.

      일부 OS(예: Linux, "primary", "secondary", "selection")는 여러 개의 클립보드를 가집니다. 어떤 클립보드의 데이터를 읽을지 정의해야 합니다.

      정제(sanitized) 복사본의 정의를 추가할 것.

    4. 글로벌 태스크 큐잉clipboard task source 위에서, realm글로벌 객체를 함께, 아래 단계를 실행하도록 합니다:

      1. data의 각 systemClipboardItem에 대해:

        1. systemClipboardItem의 각 systemClipboardRepresentation에 대해:

          1. mimeTypesystemClipboardRepresentationname을 인자로 OS 특화 포맷에서 잘 알려진 mime type 얻기 알고리즘 실행 결과로 둡니다.

          2. mimeType이 null이면 이 반복을 계속합니다.

          3. representation을 새 표현으로 둡니다.

          4. representationMIME 타입essence가 "text/plain"이면:

            1. representationMIME 타입mimeType으로 설정합니다.

            2. representationDataPromiserepresentationdata로 둡니다.

            3. React 하여 representationDataPromise가 완료될 때:

              1. representationDataPromise가 값 v로 성공(fulfilled)된 경우:

                1. vDOMString이면, 다음을 따릅니다:

                  1. pv로 resolve합니다.

                  2. p를 반환합니다.

                2. vBlob이면, 다음 단계를 따릅니다:

                  1. stringv의 바이트 시퀀스에 대해 UTF-8 디코딩 실행 결과로 둡니다.

                  2. pstring으로 resolve합니다.

                  3. p를 반환합니다.

              2. representationDataPromise가 reject된 경우:

                1. p"NotFoundError" DOMException 과 함께 realm에서 Reject 합니다.

                2. p를 반환합니다.

      2. p"NotFoundError" DOMException 과 함께 realm에서 Reject 합니다.

      3. p를 반환합니다.

navigator.clipboard.readText().then(function(data) {
  console.log("Your string: ", data);
});

7.3.3. write(data)

write(data) 메서드는 다음 단계를 실행해야 한다:
  1. realmthis관련 realm으로 둡니다.

  2. prealm 내의 새 프라미스로 둡니다.

  3. 다음 단계를 병렬로 실행합니다:

    1. r클립보드 쓰기 권한 확인 실행 결과로 둡니다.

      clipboard-write는 https://github.com/w3c/clipboard-apis/pull/164 에서 제거되었습니다.

    2. r이 false이면:

      1. 글로벌 태스크 큐잉permission task source 위에서, realm글로벌 객체로, p"NotAllowedError" DOMException 으로 realm에서 reject 하게 합니다.

      2. 이 단계를 중단합니다.

    3. 글로벌 태스크 큐잉clipboard task source 위에서, realm글로벌 객체로, 아래 단계를 실행하도록 합니다:

      1. itemListcleanItemList를 빈 시퀀스<Blob>로 둡니다.

      2. dataList시퀀스<ClipboardItem>로 둡니다.

      3. 만약 data크기가 1보다 크고, 현재 운영체제가 시스템 클립보드에서 여러 기본 클립보드 항목을 지원하지 않으면 data[0]을 dataList에 추가하고, 그렇지 않으면 dataListdata로 설정합니다.

        data에 여러 항목이 있고 운영체제가 여러 기본 클립보드 항목을 지원한다면, 현재 알고리즘은 항목들을 집합적으로 기록하는 대신 순차적으로 기록합니다.

      4. dataList의 각 clipboardItem에 대해:

        1. clipboardItem클립보드 항목표현 목록의 각 representation에 대해:

          1. representationDataPromiserepresentationdata로 둡니다.

          2. 반응 하기를 representationDataPromise가 완료될 때:

            1. representationDataPromise가 값 v로 fulfill된 경우:

              1. vDOMString이면, 아래 단계를 따릅니다:

                1. dataAsBytesUTF-8 인코딩 v의 결과로 둡니다.

                2. blobDatadataAsBytes를 사용해 Blob으로 만들고, typerepresentationMIME 타입으로 설정합니다.

                3. blobDataitemList에 추가합니다.

              2. vBlob이면 vitemList에 추가합니다.

            2. representationDataPromise가 reject된 경우:

              1. p"NotAllowedError" DOMException 과 함께 realm에서 Reject합니다.

              2. 이 단계를 중단합니다.

        2. itemList의 각 blob에 대해:

          1. typeblobtype으로 둡니다.

          2. type필수 데이터 타입 또는 옵션 데이터 타입 리스트에 없으면, p"NotAllowedError" DOMException 과 함께 realm에서 reject하고 이 단계를 중단합니다.

          3. cleanItemblob의 (선택적으로 정제된) 복사본으로 둡니다.

            정제 복사의 정의 추가할 것.

          4. 정제가 시도되었으나 성공적으로 완료되지 않은 경우, 다음 단계를 따르십시오:

            1. p"NotAllowedError" DOMException 과 함께 realm에서 Reject합니다.

            2. 이 단계를 중단합니다.

          5. cleanItemcleanItemList에 추가합니다.

        3. optionclipboardItem클립보드 항목프레젠테이션 스타일로 둡니다.

        4. 클립보드에 blobs와 option을 기록cleanItemListoption으로 실행합니다.

      5. p를 resolve합니다.

  4. p를 반환합니다.

var data = [new ClipboardItem({ "text/plain": Promise.resolve(new Blob(["Text data"], { type: "text/plain" })) })];
navigator.clipboard.write(data).then(function() {
  console.log("Copied to clipboard successfully!");
}, function() {
  console.error("Unable to write to clipboard. :-(");
});

7.3.4. writeText(data)

writeText(data) 메서드는 다음 단계를 실행해야 한다:
  1. realmthis관련 realm으로 둡니다.

  2. prealm 내의 새 프라미스로 둡니다.

  3. 다음 단계를 병렬로 실행합니다:

    1. r클립보드 쓰기 권한 확인의 실행 결과로 둡니다.

      clipboard-write는 https://github.com/w3c/clipboard-apis/pull/164에서 삭제되었습니다.

    2. r이 false이면:

      1. 글로벌 태스크 큐잉permission task source 위에, realm글로벌 객체를 넘겨 p"NotAllowedError" DOMException과 함께 realm에서 reject 하게 합니다.

      2. 이 단계를 중단합니다.

    3. 글로벌 태스크 큐잉clipboard task source 위에, realm글로벌 객체를 넘겨 아래 단계를 실행하도록 합니다:

      1. itemList를 빈 시퀀스<Blob>로 둡니다.

      2. textBlob을 새 Blob으로 만듭니다. type 속성은 "text/plain;charset=utf-8"로, 그 내부 바이트 시퀀스는 UTF-8 인코딩data로 설정합니다.

        참고: Windows에서는 datatextBlob으로 만들기 전에 `\n` 문자를 `\r\n`으로 바꿔야 합니다.

      3. textBlobitemList에 추가합니다.

      4. option을 "unspecified"로 설정합니다.

      5. 클립보드에 blobs 및 옵션 쓰기itemListoption으로 실행합니다.

      6. p를 resolve합니다.

  4. p를 반환합니다.

await navigator.clipboard.writeText("Howdy, partner!");

8. 클립보드 동작

이 섹션은 클립보드 동작과 이벤트 디스패치 처리 모델을 정의합니다.

각 클립보드 동작은 스크립트-트리거됨스크립트-클립보드-접근-허용이라는 두 개의 플래그를 가집니다.

스크립트-트리거됨 플래그는 동작이 스크립트로 인해 실행될 때(예: document.execCommand() 호출) 설정됩니다. 클립보드와 상호작용하는 향후 스크립팅 API도 이 플래그를 사용해야 하며, 스크립트-트리거됨 플래그가 올바르게 설정되어야 합니다.

스크립트-클립보드-접근-허용 플래그는 다음과 같이 설정됩니다:

  1. 동작이 복사 또는 잘라내기이고, 스크립트 스레드가 클립보드 수정 허용이면,

    1. 동작의 스크립트-클립보드-접근-허용 플래그를 설정한다

  2. 동작이 붙여넣기이고, 스크립트 스레드가 클립보드 읽기 허용이면,

    1. 동작의 스크립트-클립보드-접근-허용 플래그를 설정한다.

8.1. 복사 동작

복사 동작은 다음 단계로 구성됩니다:

  1. script-triggered 플래그가 설정되어 있으면,

    1. script-may-access-clipboard 플래그가 설정되어 있지 않으면,

      1. 복사 작업에서 false를 반환하고, 이 알고리즘을 종료합니다.

  2. "copy"라는 이름의 copy 클립보드 이벤트를 발생시킵니다.

  3. 이벤트가 취소되지 않았다면,

    1. 선택한 내용(있는 경우)을 클립보드에 복사합니다. 구현체는 웹 페이지에서 내용이 선택되었을 때 대체 text/html 및 text/plain 클립보드 포맷을 생성하는 것이 권장됩니다.

    2. "clipboardchange"라는 이름의 clipboardchange 클립보드 이벤트를 발생시킵니다.

  4. 그렇지 않고 이벤트가 취소되었다면,

    1. 클립보드에 내용 쓰기 알고리즘을 호출합니다. 이때 DataTransferItemList 리스트 itemsclear-was-called 플래그, types-to-clear 리스트를 전달합니다.

  5. 복사 작업에서 true를 반환합니다.

8.2. 잘라내기 동작

잘라내기 동작은 다음 단계로 구성됩니다:

  1. script-triggered 플래그가 설정되어 있다면,

    1. script-may-access-clipboard 플래그가 설정 해제되어 있다면,

      1. 잘라내기 작업에서 false를 반환하고, 이 알고리즘을 종료합니다.

  2. "cut"라는 이름의 cut 클립보드 이벤트를 발생시킵니다.

  3. 이 이벤트가 취소되지 않았다면,

    1. 선택 영역이 편집 가능한 컨텍스트 내에서 잘라내기가 활성화된 상태라면,

      1. 선택된 내용(있는 경우)을 클립보드에 복사합니다. 구현체는 웹 페이지에서 내용이 선택되었을 때 대체 text/html 및 text/plain 클립보드 포맷을 생성하는 것이 권장됩니다.

      2. 문서에서 해당 선택 영역의 내용을 제거하고 선택 영역을 축소합니다.

      3. "clipboardchange"라는 이름의 clipboardchange 클립보드 이벤트를 발생시킵니다.

      4. 변경으로 인해 발생해야 하는 모든 이벤트를 큐에 넣어 발생시키십시오. 자세한 내용은 § 5.3 다른 스크립트 및 이벤트와의 통합을 참조하세요.

    2. 그렇지 않고 선택 영역이 없거나, 컨텍스트가 편집 가능하지 않으면,

      1. false를 반환합니다.

  4. 그 외에, 만약 이벤트가 취소되었다면,

    1. 클립보드에 내용 쓰기 알고리즘을 호출합니다. 이때 DataTransferItemList 리스트 items와, clear-was-called 플래그, types-to-clear 리스트를 넘깁니다.

    2. "clipboardchange"라는 이름의 clipboardchange 클립보드 이벤트를 발생시킵니다.

  5. 잘라내기 작업에서 true를 반환합니다.

8.3. 붙여넣기 동작

붙여넣기 동작에서 스크립트-클립보드-접근-허용 플래그는 어떤 사이트나 앱이 클립보드에서 읽을 수 있는지 결정하기 위한 구현체별 권한 메커니즘에 따라 달라집니다. 붙여넣기 동작이 스크립트로 트리거될 때, 구현체는 사용자의 허락 없이 클립보드 내용을 노출해서는 안 됩니다. 권한이 미리 부여되지 않은 경우, 권한 프롬프트에는 스크립트 스레드에 연결된 문서의 호스트명이 반드시 포함되어야 합니다.

붙여넣기 동작은 다음 단계로 구성됩니다:

  1. 스크립트-트리거됨 플래그가 설정되어 있으면,

    1. 스크립트-클립보드-접근-허용 플래그가 설정되어 있지 않으면,

      1. 붙여넣기 동작에서 false를 반환하고, 알고리즘을 종료한다

  2. paste라는 이름의 클립보드 이벤트를 발생시킨다

  3. 이 이벤트가 취소되지 않았으면,

    1. editable context에서 붙여넣기가 허용된 선택 영역이나 커서가 존재하면,

      1. 클립보드에서 찾은 가장 적합한 콘텐츠(있는 경우)를 해당 컨텍스트에 삽입한다.

      2. 수정으로 인해 발생해야 하는 이벤트들을 큐에 추가한다. 자세한 내용은 § 5.3 다른 스크립트 및 이벤트와의 통합을 참고한다.

    2. 그렇지 않으면

      1. false를 반환한다

  4. 그렇지 않고 이벤트가 취소되었다면

    1. false를 반환한다

  5. 동작에서 true를 반환한다

9. Permissions API 연동

[permissions] API는 웹사이트가 강력한 기능(예: 클립보드)에 접근할 수 있는 통합 방식을 제공합니다. 웹사이트는 사용자의 권한을 요청하고, 어떤 권한을 가지고 있는지 조회할 수 있습니다.

클립보드의 경우, 하나의 권한이 정의되어 있습니다: "clipboard-write"

참고: 클립보드 권한은 현재 비동기 클립보드 API에만 적용됩니다. 향후 이 명세의 버전에서는 다른 클립보드 상호작용에도 이 권한이 적용될 수 있습니다.

다음과 같이 클립보드 권한은 강력한 기능이며, 권한 관련 알고리즘과 타입은 다음과 같이 정의됩니다:

permission descriptor type
dictionary ClipboardPermissionDescriptor : PermissionDescriptor {
  boolean allowWithoutGesture = false;
};

클립보드 권한은 4가지가 있습니다:

관계는 다음과 같습니다:

사용자 에이전트는 반드시 명세서에 설명된 대로 ClipboardPermissionDescriptor 를 지원해야 하지만, 기본 설정과 사용자에게 어떻게 노출하는지는 완전히 제어할 수 있습니다.

클립보드에 대해 별도의 사용자 설정 가능 쓰기 제어와 항상 사용자 제스처를 요구하는 사용자 에이전트는 각 디스크립터를 다음과 같이 처리합니다:

9.1. 클립보드 읽기 권한

9.1.1. 클립보드 읽기 권한 확인

  1. hasGesturerelevant global objectthis에서 일시적 활성화(transient activation)를 가지고 있으면 true, 그렇지 않으면 false로 한다.

  2. hasGesture이면,

    1. 현재 스크립트가 사용자 에이전트나 OS가 생성한 "Paste" 요소와의 사용자 상호작용 결과로 실행되고 있다면 true를 반환한다.

  3. false를 반환한다.

9.2. 클립보드 쓰기 권한

9.2.1. 클립보드 쓰기 권한 확인

  1. writeWithoutGesturepermission state({ name: "clipboard-write", allowWithoutGesture: true } 권한 기준)로 한다.

  2. writeWithoutGesturegranted이면 true를 반환한다.

  3. hasGesturethis관련 글로벌 객체일시적 활성화(transient activation)가 있으면 true로, 그렇지 않으면 false로 둡니다.

  4. hasGesture이면,

    1. 현재 스크립트가 사용자 에이전트나 OS가 생성한 "cut" 또는 "copy" 요소와의 사용자 상호작용 결과로 실행되고 있다면 systemCopy를 true로 한다.

    2. systemCopy가 true이면 true를 반환한다.

    3. request permission to use({ name: "clipboard-write", allowWithoutGesture: false } 권한 기준) 결과를 반환한다.

      참고: 사용자 에이전트는 더 강력한 권한을 요청하여 이 권한을 암묵적으로 업데이트할 수도 있습니다.

  5. request permission to use({ name: "clipboard-write", allowWithoutGesture: true } 권한 기준) 결과를 반환한다.

10. 보안 고려사항

저자가 사용자가 복사하는 내용을 변경하거나, 선택된 적이 없는 내용을 자동으로 복사하거나, 정보 붙여넣기를 제한 없이 호출할 수 있도록 하면 다양한 보안 문제가 발생할 수 있습니다.

예시 시나리오:

10.1. HTML 및 멀티파트 데이터 붙여넣기

이 섹션은 규범적이지 않습니다.

서식 있는 데이터나 멀티파트 데이터를 붙여넣는 데에는 특정 보안 위험이 있습니다.

어떤 정책을 사용할지 결정하기 위해 고려하는 요소는 다음과 같습니다:

각 시나리오와 적용 가능한 보안 정책 개요:

데이터 출처 스크립트 출처 규칙
온라인 소스에서 기원 데이터와 동일 HTML을 정제하지 않음. 로컬 파일 접근 불가.
다른 출처 콘텐츠 선택적 정제. 로컬 파일 접근 불가.
로컬 애플리케이션에서 기원 상관 없음 HTML을 정제하지 않음. 로컬 파일 접근 허용

일부 구현체는 서식 있는 텍스트 붙여넣기 관련 위험을 완화하기 위해, 기본적으로 SCRIPT 요소나 javascript: 링크 등 잠재적으로 악성인 콘텐츠를 제거하지만, paste 이벤트 핸들러에서는 원본, 비정제 데이터를 처리할 수 있도록 허용합니다.

10.2. 일반 보안 정책

구현체는 온라인에서 참조된 리소스를 다운로드하거나, 그 내용을 files 리스트나 DataTransferItemList 에 노출해서는 안 됩니다.

클립보드 데이터가 로컬 애플리케이션 출신이 아니라면, 구현체는 참조된 로컬 파일에 대한 접근을 허용해서는 안 됩니다. 예를 들면, 데이터에 <img src="file://localhost/example.jpg">가 포함되어 있고 데이터 출처가 온라인 리소스라면, 구현체는 clipboardData.items 리스트에 example.jpg 항목을 추가해서는 안 됩니다.

10.3. 이미지 트랜스코딩

악성 이미지 데이터가 클립보드에 저장되는 것을 방지하기 위해, 이미지 데이터를 안전한 버전으로 트랜스코딩할 수 있습니다. 이를 통해 웹사이트가 다른 애플리케이션의 보안 취약점을 악용하는 것을 막을 수 있습니다.

구현체는 클립보드에서 읽는 이미지를 트랜스코딩해서는 안 됩니다. 트랜스코딩하면 이미지의 물리적 해상도와 같은 중요한 메타데이터가 손실될 수 있습니다. 이는 <input type=file> 등 웹사이트에서 이미지를 공유하는 다른 방식과도 일치합니다.

10.4. 방해 고려사항

스크립트는 DataTransfer API를 사용하여 복사 및 잘라내기 이벤트에서 시스템 클립보드의 데이터를 변경함으로써 사용자를 혼란스럽게 하거나 괴롭힐 수 있습니다. 이 명세서는 이런 방해를 방지하려고 하지 않지만, 구현체는 추가 제한을 둘 수 있습니다.

구현체는 스크립트가 클립보드에 과도한 양의 데이터를 저장하려는 시도를 우아하게 처리해야 합니다.

11. 프라이버시 고려사항

이 API들은 사용자의 클립보드 데이터에 접근할 수 있으므로, 이름, 주소, 비밀번호 등 개인정보(PII)가 클립보드에 저장될 수 있어 심각한 프라이버시 문제가 있습니다.

일반적으로, 사용자 에이전트는 신뢰되지 않은 스크립트가 이러한 API를 통해 사용자의 클립보드 데이터를 무제한으로 접근하지 못하도록 반드시 보장해야 합니다.

11.1. 프라이버시와 클립보드 이벤트 API

클립보드 이벤트 API는 클립보드 이벤트 핸들러 컨텍스트에서 실행되는 스크립트가 시스템 클립보드의 복사본에 접근하고, 클립보드에 쓰이는 데이터를 수정할 수 있도록 허용합니다.

사용자 에이전트는 클립보드 이벤트 API를 통해 접근하는 데이터 보안을 위해 다음 요구사항을 인지해야 합니다:

클립보드 이벤트 API는 클립보드 권한에 적용되지 않지만, 사용자 에이전트는 사용자가 이 API를 비활성화하거나 특정 사이트에만 접근을 허용하도록 설정할 수 있는 방법을 제공할 수 있습니다.

11.2. 프라이버시와 비동기 클립보드 API

비동기 클립보드 API는 강력한 기능입니다. 이벤트 핸들러 컨텍스트에 국한되지 않고, 모든 스크립트가 클립보드 데이터에 접근할 수 있으며, 사용자 제스처 없이도 데이터에 접근할 수 있습니다.

남용을 막기 위해, 이 API는 문서가 포커스를 가지고 있을 때만 사용할 수 있어야 합니다.

11.2.1. 프라이버시와 클립보드 권한

클립보드 권한은 이 API 접근을 제한하지만, 사용자 에이전트는 권한의 기본값과 어떤 권한 설정을 사용자가 조정할 수 있을지 선택할 수 있습니다. 예를 들어, 사용자 에이전트는 사용자 제스처가 있는 경우에만 비동기 클립보드 API 접근을 허용하고, 제스처 없는 스크립트 요청은 항상 거부할 수 있습니다.

사용자 에이전트는 사용자가 권한을 부여한 후 권한이 자동으로 만료되도록 선택할 수 있습니다. 예를 들어, 권한 만료 조건은 다음과 같습니다:

11.3. 기타 프라이버시 우려

사용자 에이전트가 document.execCommand("paste")를 통해 클립보드 데이터를 읽을 수 있게 허용하는 경우, 반드시 사용자가 명시적으로 접근을 허용했는지 확인해야 합니다.

12. 감사의 글

이 섹션은 규범적이지 않습니다.

에디터들은 이전 에디터들의 기여를 인정합니다. 그들은 이 명세가 지금의 형태에 이르기까지 다양한 회의와 메일링 리스트 논의를 통해 발전시켜 주었습니다.

에디터들은 또한 Microsoft의 Data Transfer 기능 문서 [MICROSOFT-CLIP-OP][HTML5] 명세의 이전 초안에 지적 빚을 졌음을 인정합니다. 또한 Paul Libbrecht의 "safe copy and paste" 초안에도 감사드립니다 (이 초안은 현재 웹에서 제공되지 않습니다).

마지막으로 다음 분들의 기여에 감사드립니다:

Adam Barth, Shawn Carnell, Daniel Cheng, Daniel Dardailler, Domenic Denicola, Al Gilman, James Graham, James Greene, Ian Hickson, Darwin Huang, Lachlan Hunt, Philip Jägenstedt, Anne van Kesteren, Marijn Kruisselbrink, Aaron Leventhal, Jim Ley, Paul Libbrecht, "Martijn", Glenn Maynard, Chris Mills, ms2ger, Ryosuke Niwa, Robert O’Callahan, Dave Poehlman, "ROBO Design", Janina Sajka, Rich Schwerdtfeger, Jonas Sicking, Maciej Stachowiak, Mihai Sucan, Dmitry Titov, Ojan Vafai, Tarquin Wilton-Jones, Tom Wlodkowski, Bo Cupp, mbrodesser 그리고 Boris Zbarsky.

부록 A: 알고리즘

클립보드에 콘텐츠 쓰기

입력

items : DataTransferItemList 클립보드에 쓸 아이템 리스트

clear-was-called : boolean 값

types-to-clear : 리스트

출력

없음

  1. items 리스트가 비어 있지 않으면,

    1. 클립보드를 비운다

    2. 리스트의 각 파트에 대해,

      1. 데이터 타입이 text/plain이면,

        1. OS 및 로캘 관례에 따라 인코딩이 올바른지 확인

        2. 플랫폼 관례에 따라 줄바꿈을 정규화

        3. OS 클립보드 포맷 설명에 맞게 텍스트를 클립보드에 넣는다

      2. 그 외, 데이터가 필수 데이터 타입 리스트에 포함된 타입이면,

        1. OS 클립보드 포맷 설명에 맞게 파트를 클립보드에 넣는다

      3. 그 외의 경우

        1. 이는 구현체에 맡긴다...

          구현체에 맡기는 것은 바람직하지 않음. 여기서 무엇을 해야 할까?

          참고: OS 클립보드 구현의 한계로 인해, 스크립트는 커스텀 포맷이 시스템의 다른 애플리케이션에서도 사용 가능할 것이라 가정해서는 안 됩니다. 예를 들어, Microsoft Windows에서는 등록할 수 있는 커스텀 클립보드 포맷 수에 제한이 있습니다. setData()의 type 인자로 아무 문자열이나 사용할 수 있지만, 필수 데이터 타입을 사용하는 것이 강력히 권장됩니다.

  2. 그 외, items 리스트가 비어 있다면, 아래와 같이 클립보드를 비울지 결정한다:

    1. 아이템 리스트가 비어 있고 clear-was-called 플래그가 true이면,

      1. types-to-clear 리스트가 비어 있으면,

        1. 클립보드를 비운다

      2. 그 외의 경우

        1. OS 및 구현체별 방식으로 types-to-clear 리스트의 타입들을 클립보드에서 제거한다

          "클립보드에서 특정 타입 제거" 기능은 위험에 처해있음. 꼭 필요하지 않고, 모든 플랫폼에서 쉽게 구현할 수 있는지 불명확함.

블롭과 옵션을 클립보드에 기록하기

입력

items시퀀스<Blob>

presentationStyle클립보드 항목프레젠테이션 스타일

출력

없음

  1. webCustomFormats시퀀스<Blob>로 둡니다.

  2. items의 각 item에 대해:

    1. formatStringitemtype을 인자로 운영체제 특화 잘 알려진 포맷 알고리즘을 실행한 결과로 둡니다.

    2. formatString이 비어 있다면 다음 하위 단계를 따릅니다:

      1. webCustomFormatStringitemtype으로 둡니다.

      2. webCustomFormat을 빈 type으로 둡니다.

      3. webCustomFormatString"web " 접두사로 시작한다면, "web " 접두사를 제거한 나머지 문자열을 webMimeTypeString에 저장합니다.

      4. webMimeTypewebMimeTypeString을 인자로 MIME 타입 파싱 알고리즘을 실행한 결과로 둡니다.

      5. webMimeType이 실패(failure)이면, 모든 단계를 중단합니다.

      6. webCustomFormattypeessencewebMimeType으로 지정합니다.

      7. itemtypewebCustomFormat으로 설정합니다.

      8. webCustomFormatwebCustomFormats에 추가합니다.

    3. payloaditem의 바이트 시퀀스에 UTF-8 디코딩을 실행한 결과로 둡니다.

    4. payloadpresentationStyleformatString을 네이티브 클립보드 포맷으로 사용하여 시스템 클립보드에 삽입합니다.

    일부 OS(예: Linux "primary", "secondary", "selection")는 여러 클립보드를 가지고 있습니다. 어느 쪽에 데이터를 쓸지 정의해야 합니다.

  3. 웹 커스텀 포맷 쓰기webCustomFormats에 대해 실행합니다.

OS별 알려진 포맷

입력

mimeType : type

출력

wellKnownFormat : 플랫폼별 문자열 타입 (Mac: NSPasteboardType, Windows: LPCWSTR, Linux: const char*)

Windows: https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats 및 https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-atom-tables?redirectedfrom=MSDN Mac: https://developer.apple.com/documentation/appkit/nspasteboardtype

  1. wellKnownFormat을 빈 문자열로 한다.

  2. mimeTypeessence가 "text/plain"이면,

    Windows에서는 다음과 같이:

    1. wellKnownFormat에 CF_UNICODETEXT 할당

    MacOS에서는 다음과 같이:

    1. wellKnownFormat에 NSPasteboardTypeString 할당

    Linux, ChromeOS, Android에서는 다음과 같이:

    1. wellKnownFormat에 "text/plain" 할당

  3. 그 외, mimeTypeessence가 "text/html"이면,

    Windows에서는 다음과 같이:

    1. wellKnownFormat에 CF_HTML 할당

    MacOS에서는 다음과 같이:

    1. wellKnownFormat에 NSPasteboardTypeHTML 할당

    Linux, ChromeOS, Android에서는 다음과 같이:

    1. wellKnownFormat에 "text/html" 할당

  4. 그 외, mimeTypeessence가 "image/png"이면,

    Windows에서는 다음과 같이:

    1. wellKnownFormat에 "PNG" 할당

    MacOS에서는 다음과 같이:

    1. wellKnownFormat에 NSPasteboardTypePNG 할당

    Linux, ChromeOS, Android에서는 다음과 같이:

    1. wellKnownFormat에 "image/png" 할당

  5. 그 외, mimeTypeessence가 "image/svg+xml"이면,

    Windows에서는 다음과 같이:

    1. wellKnownFormat에 CFSTR_MIME_SVG_XML 할당

    MacOS에서는 다음과 같이:

    1. wellKnownFormat에 UTTypeSVG 할당

    Linux, ChromeOS, Android에서는 다음과 같이:

    1. wellKnownFormat에 "image/svg+xml" 할당

  6. wellKnownFormat을 반환한다.

OS별 포맷에서 알려진 MIME 타입

입력

osFormatName : 플랫폼별 문자열 타입 (Mac: NSPasteboardType, Windows: LPCWSTR, Linux: const char*)

출력

mimeType : MIME type

Windows: https://docs.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats 및 https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-atom-tables?redirectedfrom=MSDN Mac: https://developer.apple.com/documentation/appkit/nspasteboardtype

Windows에서는 다음과 같이:

  1. osFormatName이 "UnicodeText"면 mimeTypeString을 "text/plain"으로 설정

  2. 그 외, osFormatName이 "HTML Format"이면 mimeTypeString을 "text/html"로 설정

  3. 그 외, osFormatName이 "PNG"이면 mimeTypeString을 "image/png"로 설정

  4. 그 외, osFormatName이 CFSTR_MIME_SVG_XML이면 mimeTypeString을 "image/svg+xml"로 설정

MacOS에서는 다음과 같이:

  1. osFormatName이 NSPasteboardTypeString이면 mimeTypeString을 "text/plain"으로 설정

  2. 그 외, osFormatName이 NSPasteboardTypeHTML이면 mimeTypeString을 "text/html"로 설정

  3. 그 외, osFormatName이 NSPasteboardTypePNG이면 mimeTypeString을 "image/png"로 설정

  4. 그 외, osFormatName이 UTTypeSVG이면 mimeTypeString을 "image/svg+xml"로 설정

Linux, ChromeOS, Android에서는 다음과 같이:

  1. osFormatName이 "text/plain"이면 mimeTypeString을 "text/plain"으로 설정

  2. 그 외, osFormatName이 "text/html"이면 mimeTypeString을 "text/html"로 설정

  3. 그 외, osFormatName이 "image/png"이면 mimeTypeString을 "image/png"로 설정

  4. 그 외, osFormatName이 "image/svg+xml"이면 mimeTypeString을 "image/svg+xml"로 설정

  1. mimeTypeMIME 타입 파싱(mimeTypeString 기준) 결과로 한다.

  2. mimeType을 반환한다.

웹 커스텀 포맷 읽기

입력

item, 클립보드 아이템

  1. webCustomFormatMapOS별 커스텀 포맷 맵 이름으로 한다.

  2. webCustomFormatMap시스템 클립보드에서 읽는다.

    webCustomFormatMap을 읽는 과정 자세히 명시 필요.

  3. webCustomFormatMap이 비어 있으면 item을 반환한다.

  4. webCustomFormatMapStringwebCustomFormatMap에서 역직렬화한 JSON 문자열로 한다.

    참고: webCustomFormatMap의 내용을 역직렬화할 JSON 리더 필요.

  5. webCustomFormatMapString의 각 (key, value)에 대해:

    1. mimeTypeMIME 타입 파싱(key 기준) 결과로 한다.

    2. mimeType이 실패이면 루프 계속.

    3. representation을 새로운 representation으로 한다.

    4. representationMIME typemimeType으로 설정.

    5. representationisCustom 플래그를 true로 설정.

    6. webCustomFormat시스템 클립보드에서 value로 읽는다.

    7. 읽기 성공 시 representationdata시스템 클립보드에서 가져온 데이터로 설정, 실패 시 루프 계속.

    8. representationitemlist of representations에 추가.

웹 커스텀 포맷 쓰기

입력

items, sequence<Blob>

  1. idx를 0으로 초기화.

  2. webCustomFormatMapOS별 커스텀 포맷 맵 이름으로 한다.

  3. webCustomFormatMapString을 빈 JSON 문자열로 한다.

  4. items의 각 item에 대해:

    1. webCustomFormatOS별 커스텀 포맷 이름으로 한다.

    2. webCustomFormatIdxidxwebCustomFormat에 붙인 결과로 한다.

    3. itemtype 을 key로, webCustomFormatIdx을 value로 하여 webCustomFormatMapString에 JSON serializer로 삽입.

      참고: webCustomFormatMapString으로 직렬화할 JSON writer 필요.

    4. item시스템 클립보드webCustomFormatIdx 포맷으로 삽입.

    5. idx를 증가.

    6. idx가 100보다 크면 루프 종료.

  5. webCustomFormatMapString시스템 클립보드webCustomFormatMap 포맷으로 삽입.

OS별 커스텀 포맷 맵 이름

출력

webCustomFormatMap, 문자열

Windows에서는 다음과 같이:

  1. webCustomFormatMap에 "Web Custom Format Map" 할당.

  2. webCustomFormatMap 반환.

MacOS에서는 다음과 같이:

  1. webCustomFormatMap에 "org.w3.web-custom-format.map" 할당.

  2. webCustomFormatMap 반환.

Linux, ChromeOS, Android에서는 다음과 같이:

  1. webCustomFormatMap에 "application/web;type=\"custom/formatmap\"" 할당.

  2. webCustomFormatMap 반환.

운영체제별 커스텀 이름

출력

webCustomFormat, 문자열

Windows에서는 다음 기준을 따른다:

  1. webCustomFormat에 "Web Custom Format"을 할당한다.

  2. webCustomFormat을 반환한다.

MacOS에서는 다음 기준을 따른다:

  1. webCustomFormat에 "org.w3.web-custom-format.type-"을 할당한다.

  2. webCustomFormat을 반환한다.

Linux, ChromeOS, Android에서는 다음 기준을 따른다:

  1. webCustomFormat에 "application/web;type="custom/format"을 할당한다.

  2. webCustomFormat을 반환한다.

클립보드 이벤트 발생시키기

입력

e, ClipboardEvent 발생시킬 이벤트

출력

없음

  1. clear-was-calledfalse로 한다.

  2. types-to-clear를 빈 리스트로 한다.

  3. clipboard-event-data를 새로운 DataTransfer 객체로, items 리스트는 빈 값으로 생성한다.

  4. clipboard-entry를 현재 클립보드 콘텐츠의 시퀀스 번호로 하거나, OS 클립보드가 시퀀스 번호를 지원하지 않는 경우 null로 한다.

  5. trusted를 이벤트가 사용자 에이전트에 의해 생성된 경우 true, 그렇지 않으면 false로 한다.

  6. target을 다음과 같이 설정한다:

    1. 컨텍스트가 편집 가능하면,

      1. target을 선택 영역이나 커서가 있는 요소(문서 순서상)로 하거나, 선택 영역/커서가 없으면 body 요소로 한다.

    2. 그 외 컨텍스트가 편집 불가능하면,

      1. target을 포커스된 노드로 하거나, 포커스된 노드가 없으면 body 요소로 한다.

  7. 이벤트를 다음과 같이 처리한다:

    1. e가 "paste"이면,

      1. clipboard-event-data의 내부 drag data store mode 플래그를 read-only로 설정한다.

      2. trustedtrue이거나, 구현체가 스크립트 생성 이벤트에 OS 클립보드 읽기 권한을 부여하도록 설정된 경우,

        1. OS 클립보드의 각 clipboard-part에 대해 아래를 수행한다:

          1. clipboard-part가 평문 텍스트를 포함하면,

            1. 텍스트가 스크립트 엔진 내부 인코딩에 맞는지 확인한다.

            2. new-data를 새로운 DataTransferItem 으로, drag data item kindstring, drag data item type stringtext/plain으로 한다.

            3. new-data의 데이터를 평문 텍스트로 설정한다.

            4. new-dataclipboard-event-dataitems 리스트에 추가한다.

          2. clipboard-part가 파일 참조를 나타내면, 각 파일 참조에 대해:

            1. 참조된 파일의 MIME 타입을 결정한다.

            2. new-data를 새로운 DataTransferItem 으로, drag data item kindfile, drag data item type string은 해당 MIME 타입(모르면 application/octet-stream)으로 한다.

            3. new-data의 데이터를 파일 참조 데이터로 설정한다.

            4. new-dataclipboard-event-dataitems 리스트에 추가한다.

          3. clipboard-part가 HTML 또는 XHTML 형식의 텍스트를 포함하면(OS 클립보드 포맷 설명 기준),

            1. 구현체가 HTML 붙여넣기를 지원하면, HTML 붙여넣기 이벤트 처리(clipboard-part, clipboard-event-data)를 호출한다.

          4. clipboard-part가 다른 지원되는 바이너리 혹은 텍스트 기반 포맷(see 필수 데이터 타입)의 데이터를 포함하면,

            1. 데이터의 MIME 타입 결정

            2. new-data를 새로운 DataTransferItem 으로, drag data item kindfile, drag data item type string은 해당 MIME 타입으로 한다.

            3. new-data의 데이터를 바이너리 또는 텍스트 기반 데이터로 설정한다.

            4. new-dataclipboard-event-dataitems 리스트에 추가한다.

      3. clipboard-event-datafiles 속성을 clipboard-event-dataitems 항목에 맞게 갱신한다.

      4. clipboard-event-datatypes 속성을 clipboard-event-dataitems 항목에 맞게 갱신한다.

    2. e가 "copy" 또는 "cut"이면,

      1. 해당 DataTransfer 객체의 내부 drag data store mode 플래그를 read/write로 한다.

  8. eclipboardDataclipboard-event-data로 설정한다.

  9. eisTrustedtrusted로 설정한다.

  10. ecomposed 를 true로 설정한다.

  11. 이벤트 etarget에 버블링되고 취소 가능한 이벤트로, ClipboardEvent 인터페이스로 디스패치한다.

    이벤트 디스패치 중 데이터 접근에 대한 구현 요구사항은 [HTML]에 정의되어 있다. 추가적인 클립보드 이벤트 전용 처리 규칙은 아래와 같다:

    왜 여기서 정의하는가? 왜 HTML 명세에 포함되지 않는가?

    1. 스크립트가 clearData() 또는 clear() 를 호출하고, DataTransfer 객체 내부 drag data store mode 플래그가 read/write이면,

      1. clear-was-called 플래그를 true로 설정한다. 인자가 주어지면 해당 인자를 types-to-clear 리스트에 추가한다.

    2. 스크립트가 setData()를 호출하거나 아이템을 수정하고, clear-was-called 플래그가 true이면,

      1. types-to-clear 리스트가 비어있으면,

        1. clear-was-called 플래그를 false로 한다.

      2. 그 외, setData()type 인자 또는 새 아이템의 drag data item type stringtypes-to-clear 리스트에 있다면,

        1. 리스트에서 해당 항목을 제거하고, 리스트가 비어있으면 clear-was-called 플래그를 false로 한다.

    3. 스크립트가 getData()를 호출하거나 DataTransferItemList 에 접근하고 clipboard-entry가 설정되어 있으면,

      1. 클립보드 데이터의 시퀀스 번호가 clipboard-entry와 일치하는지 확인한다. 클립보드가 더 이상 동일한 항목을 포함하지 않으면 DataTransferItemList 객체의 내부 drag data store modeprotected로 설정한다.

    경고! paste 이벤트를 감시하는 악성 스크립트가 사용자가 미래에 클립보드에 넣는 것을 무한 반복 루프를 통해 읽을 수 있습니다. 클립보드 시퀀스 번호를 지원하지 않는 플랫폼에서는 추가 제한이 필요합니다.

HTML 붙여넣기 이벤트 처리

입력

clipboard-part, 처리할 클립보드 파트

clipboard-event-data, 이 이벤트용 DataTransfer 객체

출력

없음

  1. new-data를 새로운 DataTransferItem 으로, drag data item kindPlain Unicode string, drag data item type stringtext/html 또는 application/xhtml+xml로 한다.

  2. clipboard-part에서 마크업을 추출하고, 관련 파서를 사용해 DOM 트리를 생성한다.

  3. 마크업의 소스 URL이 알려져 있다면, HREF와 SRC 속성의 상대 URL을 소스 URL을 기준으로 모두 절대 URL로 변환해 해당 속성에 설정한다.

  4. 마크업의 출처가 로컬 애플리케이션이라면, 로컬 파일이나 OS 클립보드의 다른 부분을 참조하는지 확인한다. 참조가 있다면, 서브파트 참조는 반드시 cid: URL 스킴([RFC2392])을 활용해 content-id 참조로 바꿔야 한다. 이를 위해 아래 단계를 따른다:

    이 단계가 필요한가? 내부 참조가 있는 다중 파트 지원 네이티브(플랫폼) 클립보드 구현이 존재하는가?

    이 기능은 꼭 필요한지, 그리고 크로스 플랫폼 테스트가 어렵기 때문에 위험에 처해있음.

    1. clipboard-event-dataitems 에 이미 참조된 파일 또는 클립보드 파트에 대한 항목이 있으면,

      1. itemNumber를 해당 항목의 인덱스로 설정한다.

    2. 그렇지 않으면,

      1. new-file-data를 새 DataTransferItem 객체로 하고, drag data item kind는 "file"로, drag data item type string은 파일 또는 클립보드 파트의 MIME 타입(알 수 없다면 application/octet-stream)으로 설정한다.

      2. file-info를 새 File 객체로 하며, name 은 HTML 속성 값의 이름 부분으로, lastModified 는 참조된 파일의 타임스탬프 또는 클립보드 파트라면 0으로 설정한다.

      3. new-file-data의 내부 File 객체를 file-info로 설정한다.

      4. new-file-dataclipboard-event-dataitems 에 추가하고, itemNumberDataTransferItemList에서 해당 항목의 인덱스로 한다.

    3. 로컬 파일 또는 클립보드 파트를 참조하는 DOM 속성을 'cid:'와 itemNumber로 갱신한다.

  5. 처리된 DOM을 직렬화하여 new-data에 생성된 HTML 코드로 갱신한다.

  6. new-dataclipboard-event-dataitems 에 추가한다.

적합성

문서 규약

적합성 요구사항은 설명적 단언과 RFC 2119 용어의 조합으로 표현됩니다. 본 문서의 규범적 부분에 등장하는 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL” 등의 주요 단어는 RFC 2119에서 정의된 대로 해석되어야 합니다. 다만 가독성을 위해 이 명세에서는 해당 단어들이 모두 대문자로 표기되지는 않습니다.

이 명세의 모든 텍스트는 명시적으로 비규범적으로 표시된 섹션, 예시, 노트를 제외하고는 규범적입니다. [RFC2119]

이 명세서에서 예시는 “예를 들어”라는 단어로 시작하거나, class="example"로 규범 텍스트와 구분되어 표시됩니다. 다음과 같이:

이것은 참고용 예시입니다.

참고 노트는 “Note”로 시작되며, class="note"로 규범 텍스트와 구분되어 표시됩니다. 다음과 같이:

참고, 이것은 참고용 노트입니다.

적합한 알고리즘

알고리즘의 일부로 명령문(예: "선행 공백 문자를 제거한다" 또는 "false를 반환하고 이 단계를 중단한다")로 표현된 요구사항은, 알고리즘 도입부에 사용된 주요 단어("must", "should", "may" 등)의 의미와 함께 해석되어야 합니다.

알고리즘이나 특정 단계로 표현된 적합성 요구사항은, 최종 결과가 동일하다면 어떤 방식으로도 구현할 수 있습니다. 특히 이 명세의 알고리즘은 이해하기 쉽도록 작성되었으며, 성능을 목적으로 한 것은 아닙니다. 구현자는 최적화를 권장합니다.

색인

이 명세에서 정의된 용어

참조로 정의된 용어

참고문헌

규범적 참고문헌

[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[ENCODING]
Anne van Kesteren. Encoding 표준. 현행 표준. URL: https://encoding.spec.whatwg.org/
[FileAPI]
Marijn Kruisselbrink. File API. 2024년 12월 4일. WD. URL: https://www.w3.org/TR/FileAPI/
[HTML]
Anne van Kesteren; 외. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[MIMESNIFF]
Gordon P. Hemsley. MIME Sniffing 표준. 현행 표준. URL: https://mimesniff.spec.whatwg.org/
[PERMISSIONS]
Marcos Caceres; Mike Taylor. Permissions. 2025년 10월 6일. WD. URL: https://www.w3.org/TR/permissions/
[RFC2119]
S. Bradner. 요구사항 수준을 표시하기 위한 RFC에서 사용하는 주요 단어. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC2392]
E. Levinson. Content-ID와 Message-ID 통합 리소스 위치자. 1998년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc2392
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/

참고용 참고문헌

[HTML5]
Ian Hickson; 외. HTML5. 2018년 3월 27일. REC. URL: https://www.w3.org/TR/html5/
[MICROSOFT-CLIP-OP]
About DHTML Data Transfer. Microsoft Developer Network.. URL: https://msdn.microsoft.com/en-us/ie/ms537658(v=vs.94)
[SVG11]
Erik Dahlström; 외. Scalable Vector Graphics (SVG) 1.1 (Second Edition). 2011년 8월 16일. REC. URL: https://www.w3.org/TR/SVG11/

IDL 색인

dictionary ClipboardEventInit : EventInit {
  DataTransfer? clipboardData = null;
};

[Exposed=Window]
interface ClipboardEvent : Event {
  constructor(DOMString type, optional ClipboardEventInit eventInitDict = {});
  readonly attribute DataTransfer? clipboardData;
};

dictionary ClipboardChangeEventInit : EventInit {
  sequence<DOMString> types = [];
  bigint changeId = 0;
};

[Exposed=Window]
interface ClipboardChangeEvent : Event {
  constructor(DOMString type, optional ClipboardChangeEventInit eventInitDict = {});
  readonly attribute FrozenArray<DOMString> types;
  readonly attribute bigint changeId;
};

partial interface Navigator {
  [SecureContext, SameObject] readonly attribute Clipboard clipboard;
};

typedef Promise<(DOMString or Blob)> ClipboardItemData;

[SecureContext, Exposed=Window]
interface ClipboardItem {
  constructor(record<DOMString, ClipboardItemData> items,
              optional ClipboardItemOptions options = {});

  readonly attribute PresentationStyle presentationStyle;
  readonly attribute FrozenArray<DOMString> types;

  Promise<Blob> getType(DOMString type);

  static boolean supports(DOMString type);
};

enum PresentationStyle { "unspecified", "inline", "attachment" };

dictionary ClipboardItemOptions {
  PresentationStyle presentationStyle = "unspecified";
};

typedef sequence<ClipboardItem> ClipboardItems;

[SecureContext, Exposed=Window]
interface Clipboard : EventTarget {
  Promise<ClipboardItems> read(optional ClipboardUnsanitizedFormats formats = {});
  Promise<DOMString> readText();
  Promise<undefined> write(ClipboardItems data);
  Promise<undefined> writeText(DOMString data);
};

dictionary ClipboardUnsanitizedFormats {
  sequence<DOMString> unsanitized;
};

dictionary ClipboardPermissionDescriptor : PermissionDescriptor {
  boolean allowWithoutGesture = false;
};

이슈 색인

웹 개발자는 내부적인 거부 사유에 관심을 가질 수 있습니다.
저자가 getType을 호출한 후 시스템 클립보드에서 데이터를 비동기로 읽을 수 있어야 하지만, 이 단계들은 읽는 시점에 데이터를 제공할 것임을 암시합니다.
일부 OS에서는 여러 클립보드가 존재합니다(예: Linux의 "primary", "secondary", "selection"). 어떤 클립보드에서 데이터를 읽는지 정의해야 합니다.
정제된 복사본(sanitized copy)의 정의를 추가해야 합니다.
clipboard-write는 https://github.com/w3c/clipboard-apis/pull/164에서 제거되었습니다.
data가 여러 아이템을 포함하고 운영체제가 여러 네이티브 클립보드 아이템을 지원할 경우, 현재 알고리즘은 아이템을 순차적으로 시스템 클립보드에 쓰지만, 집합적으로 쓰는 것이 아닙니다.
정제된 복사본(sanitized copy)의 정의를 추가해야 합니다.
clipboard-write는 https://github.com/w3c/clipboard-apis/pull/164에서 제거되었습니다.
구현체에 맡기는 것은 바람직하지 않음. 여기서 무엇을 해야 할까?
"클립보드에서 특정 타입 제거" 기능은 위험에 처해있음. 꼭 필요하지 않고, 모든 플랫폼에서 쉽게 구현할 수 있는지 불명확함.
일부 OS는 여러 클립보드를 가짐(Linux: "primary", "secondary", "selection" 등). 어느 클립보드에 데이터를 쓰는지 정의해야 함.
webCustomFormatMap을 읽는 과정 자세히 명시 필요.
왜 여기서 정의하는가? 왜 HTML 명세에서 정의하지 않는가?
이러한 단계가 필요한가? 내부 참조가 있는 여러 파트를 지원하는 네이티브(플랫폼) 클립보드 구현체가 실제로 존재하는가?
이 기능은 반드시 필요한지 불분명하고, 크로스 플랫폼 테스트가 어렵기 때문에 위험에 처해있음.
MDN

Clipboard/read

Firefox🔰 90+Safari13.1+Chrome?
Opera63+Edge?
Edge (Legacy)NoneIENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet12.0+Opera Mobile54+
MDN

Clipboard/readText

FirefoxNoneSafari13.1+Chrome66+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Clipboard/write

In all current engines.

Firefox87+Safari13.1+Chrome66+
Opera63+Edge79+
Edge (Legacy)NoneIENone
Firefox for Android?iOS Safari?Chrome for Android66+Android WebView?Samsung Internet12.0+Opera Mobile54+
MDN

Clipboard/writeText

In all current engines.

Firefox63+Safari13.1+Chrome66+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Clipboard

In all current engines.

Firefox63+Safari13.1+Chrome66+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardEvent/ClipboardEvent

In all current engines.

Firefox22+Safari10.1+Chrome58+
Opera?Edge79+
Edge (Legacy)17+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardEvent/clipboardData

In all current engines.

Firefox22+Safari10.1+Chrome41+
Opera?Edge79+
Edge (Legacy)12+IE5+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardEvent

In all current engines.

Firefox22+Safari10.1+Chrome41+
Opera?Edge79+
Edge (Legacy)12+IE4+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardItem/ClipboardItem

In all current engines.

Firefox🔰 87+Safari13.1+Chrome98+
Opera?Edge98+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android98+Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardItem/getType

In all current engines.

Firefox🔰 87+Safari13.1+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android84+Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardItem/presentationStyle

Firefox🔰 87+Safari13.1+ChromeNone
Opera?EdgeNone
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardItem/types

In all current engines.

Firefox🔰 87+Safari13.1+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android84+Android WebView?Samsung Internet?Opera Mobile?
MDN

ClipboardItem

In all current engines.

Firefox🔰 87+Safari13.1+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android84+Android WebView?Samsung Internet?Opera Mobile?
MDN

Element/copy_event

In all current engines.

Firefox22+Safari3+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+IE9+
Firefox for Android?iOS Safari3+Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

Element/cut_event

In all current engines.

Firefox22+Safari3+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+IE9+
Firefox for Android?iOS Safari3+Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
MDN

Element/paste_event

In all current engines.

Firefox22+Safari3+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+IE9+
Firefox for Android?iOS Safari3+Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile12.1+
MDN

Navigator/clipboard

In all current engines.

Firefox63+Safari13.1+Chrome66+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?