클립보드 API 및 이벤트

W3C 작업 초안,

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2026/WD-clipboard-apis-20260624/
최신 공개 버전:
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. eventInit을 사용하여, ClipboardChangeEvent를 사용해 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을 사용하여, ClipboardChangeEvent를 사용해 global에서 clipboardchange라는 이름의 이벤트를 발화한다.

중첩된 브라우징 컨텍스트의 문서의 경우, 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

이벤트가 발화되었을 때 시스템 클립보드에서 사용할 수 있는 필수 데이터 타입을 나타내는 DOMString 객체들의 FrozenArray를 반환한다. 핑거프린팅 표면을 제한하기 위해 선택적 데이터 타입과 사용자 정의 형식은 제외된다.

changeId

이 특정 클립보드 변경 작업의 고유 식별자를 나타내는 bigint를 반환한다. 이 식별자는 동일한 클립보드 변경에 대해 같은 저장소 키를 가진 모든 창과 탭에서 일관되며, 여러 창이 같은 클립보드 변경 알림을 받을 때 애플리케이션이 이벤트 중복을 제거할 수 있게 한다.

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 카운터가 재설정되기 때문이다. 마찬가지로, 사용자가 사이트 데이터를 지우면 영향을 받는 탭은 새로고침되어야 하며, 이로 인해 이벤트 리스너가 다시 연결되고 새 change ID를 가진 향후 이벤트만 수신하게 된다.

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

clipboardchange 이벤트는 웹 애플리케이션이 클립보드 변경을 효율적으로 모니터링하고 사용 가능한 데이터 형식에 기반해 동적인 사용자 인터페이스를 제공할 수 있게 한다:
// 여러 창이 있는 애플리케이션의 경우, 중복을 피하기 위해 처리된 change ID를 추적한다
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;

  // 원격 데스크톱 앱의 경우, 변경당 한 번만 클립보드를 원격과 동기화한다
  if (hasText || hasHTML || hasImage) {
    syncClipboardToRemote(e.changeId);
  }
});

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

이 이벤트 기반 접근 방식은 read() 또는 readText() 같은 메서드로 클립보드를 폴링하는 것보다 더 효율적이며, 클립보드 접근에 사용자 활성화를 요구하는 브라우저에서도 작동한다. UI가 타이머가 실행되기를 기다리지 않고 클립보드 변경에 즉시 반응할 수 있기 때문이다. changeId는 여러 창이 있는 애플리케이션에 특히 유용하며, 같은 저장소 키를 가진 모든 창에 걸쳐 각 클립보드 변경이 한 번만 처리되도록 보장한다.

5.2.2. copy 이벤트

사용자가 복사 동작을 시작하면, 사용자 에이전트는 클립보드 이벤트를 발화한다. 그 이름은 copy이다.

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

copy 이벤트는 버블링되고, 취소 가능하며, 합성된다.

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

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

5.2.3. cut 이벤트

사용자가 잘라내기 동작을 시작하면, 사용자 에이전트는 클립보드 이벤트를 발화한다. 그 이름은 cut이다.

편집 가능 컨텍스트에서는, 이벤트가 취소되지 않으면 이 동작은 현재 선택된 데이터를 시스템 클립보드에 놓고 문서에서 선택 영역을 제거한다. cut 이벤트는 선택된 데이터가 제거되기 전에 발화된다. 잘라내기 작업이 완료되면, 선택 영역은 접힌다.

비-편집 가능 컨텍스트에서는, clipboardData가 빈 목록이 된다. 이 경우에도 cut 이벤트는 여전히 발화된다는 점에 유의하라.

cut 이벤트는 버블링되고, 취소 가능하며, 합성된다.

이 이벤트의 처리 모델에 대한 자세한 설명은 § 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를 반환합니다.

클립보드 항목은 개념적으로 사용자가 "cut" 또는 "copy" 명령을 호출하여 공유 가능하게 만들고자 하는 의사를 나타낸 데이터이다. 클립보드 항목은 두 가지 목적을 수행한다. 첫째, 웹사이트가 사용자가 시스템 클립보드에 복사한 데이터를 읽을 수 있게 한다. 둘째, 웹사이트가 시스템 클립보드에 데이터를 쓸 수 있게 한다.

예를 들어, 사용자가 네이티브 애플리케이션의 스프레드시트에서 셀 범위를 복사하면, 하나의 클립보드 항목이 생성된다. 사용자가 데스크톱에서 파일 집합을 복사하면, 그 파일 목록은 여러 클립보드 항목으로 표현된다.

일부 플랫폼은 클립보드에 한 번에 둘 이상의 클립보드 항목을 둘 수 있도록 지원할 수 있지만, 다른 플랫폼은 이전 클립보드 항목을 새 항목으로 대체한다.

클립보드 항목표현의 목록을 가지며, 각 표현에는 연결된 MIME 타입(MIME 타입), 초깃값이 falseisCustom 플래그가 있다. 이 플래그는 이 표현웹 사용자 정의 형식으로 취급되어야 하는지 (시스템 클립보드의 잘 알려진 형식과 반대로)를 나타내며, 데이터(ClipboardItemData)를 가진다.

웹 사용자 정의 형식isCustomtrue로 설정되어 있다.

사용자가 스프레드시트에서 셀 범위를 복사하는 예에서는, 이미지 (image/png), HTML 표(text/html), 일반 텍스트(text/plain), 또는 웹 사용자 정의 형식(web text/csv)으로 표현될 수 있다.

이러한 각 MIME 타입은 같은 클립보드 항목의 서로 다른 충실도 수준의 표현을 설명하며, 붙여넣기 중 대상 애플리케이션이 클립보드 항목을 더 쉽게 소비할 수 있게 한다.

셀 범위를 이미지로 사용할 수 있게 하면 사용자는 셀을 사진 편집 앱에 붙여넣을 수 있으며, text/plain 형식은 텍스트 편집기 앱에서 사용할 수 있다.

클립보드 항목표현 스타일 (PresentationStyle)을 가진다. 이는 클립보드 항목을 "붙여넣는" 앱이 적절한 표현의 내용을 붙여넣기 지점에 인라인으로 삽입해야 하는지, 또는 첨부 파일로 취급해야 하는지를 구분하는 데 도움을 준다.

단일 클립보드 항목만 붙여넣는 것을 지원하는 웹 앱은 첫 번째 클립보드 항목을 사용해야 한다.

write()는 마지막 클립보드 항목을 선택한다.

둘 이상의 클립보드 항목을 붙여넣는 것을 지원하는 웹 앱은, 예를 들어 각 클립보드 항목의 내용을 미리 보여주고 사용자가 붙여넣을 항목을 선택할 수 있게 하는 사용자 인터페이스를 제공할 수 있다. 또한 앱은 붙여넣는 클립보드 항목MIME 타입을 열거하고, 앱별 알고리즘에 따라 앱에 가장 적합한 것을 선택할 것으로 기대된다. 또는 앱은 사용자에게 클립보드 항목을 붙여넣는 방법에 대한 옵션, 예컨대 "이미지로 붙여넣기" 또는 "서식 있는 텍스트 붙여넣기" 등을 제시할 수 있다.

ClipboardItem 객체는 관련된 클립보드 항목을 가지며, 이는 클립보드 항목이다.

ClipboardItem 객체는 관련된 types 배열을 가지며, 이는 FrozenArray<DOMString>이다.

ClipboardItem 객체는 관련된 읽기 시점의 클립보드 변경 횟수를 가지며, 이는 처음에는 null이다.

ClipboardItem 객체는 관련된 원본 시스템 클립보드 항목을 가지며, 이는 시스템 클립보드 항목 또는 null이고, 처음에는 null이다.

ClipboardItem 객체는 관련된 비정제 MIME 타입을 가지며, 이는 sequence<DOMString>이고, 처음에는 비어 있다.

ClipboardItem 객체는 관련된 해결자를 가진 표현을 가지며, 이는 문자열(getType()에 전달된 MIME 타입, 존재하는 경우 `"web "` 접두사를 포함함)에서 Promise<Blob>로의 이며, 처음에는 비어 있다. 각 항목은 해당 타입에 대한 OS 클립보드 읽기를 나타내며, 이는 완료되었거나 현재 진행 중이다.

Note: 이 맵은 getType() 으로부터 얻은 read() ClipboardItem에서 같은 MIME 타입에 대한 동시 호출들이 단일 OS 클립보드 읽기를 공유하도록 보장한다. 첫 번째 호출은 보류 중인 Promise를 맵에 삽입하고 읽기를 시작한다. 같은 MIME 타입에 대한 이후 호출들은 시스템 클립보드를 다시 읽지 않고 기존 Promise를 반환한다.

read()ClipboardItem이 생성되면, 이는 데이터 스냅샷이 아니라 지연 fetcher로 동작한다. 그 types 배열read() 호출 시점에 시스템 클립보드에서 사용할 수 있는 형식을 반영하지만, 실제 페이로드 바이트는 getType()이 호출될 때까지 읽히지 않는다. read() 호출과 이후의 getType() 호출 사이에 시스템 클립보드 내용이 변경되면, getType() 호출은 거부된다. ClipboardItem(items, options) 생성자를 통해 직접 구성된 ClipboardItem은 이 동작의 대상이 아니다.

클립보드 항목 clipboardItem과 Realm realm이 주어졌을 때 ClipboardItem 객체를 생성하려면, 다음 단계를 실행한다:

  1. clipboardItemObjectrealm으로 새로운 ClipboardItem으로 둔다.

  2. clipboardItemObject클립보드 항목clipboardItem으로 설정한다.

new ClipboardItem(items, options) 생성자 단계는 다음과 같다:

  1. items가 비어 있으면, TypeError를 던진다.

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

  3. this클립보드 항목을 새 클립보드 항목으로 설정한다.

  4. this클립보드 항목표현 스타일options["presentationStyle"]로 설정한다.

  5. typesDOMString의 목록으로 둔다.

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

    1. representation을 새 표현으로 둔다.

    2. isCustomfalse로 둔다.

    3. key가 `"web "` 접두사로 시작하면, 다음을 수행한다

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

      2. isCustomtrue로 설정한다

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

    5. mimeTypekey가 주어졌을 때 MIME 타입 파싱의 결과로 둔다.

    6. mimeType이 failure이면, TypeError를 던진다.

    7. this클립보드 항목표현 목록mimeTypeMIME 타입isCustom인 [representation/isCustom]을 가진 표현포함하면, TypeError를 던진다.

    위 단계는 사용자 에이전트가 잘 알고 있는 mime-types와, 작성자가 사용자 정의 타입으로 취급하려고 의도한 mime-types 사이의 충돌을 방지한다. 예를 들어, 작성자의 items 목록이 "text/html"에 대한 표현과 "web text/html"에 대한 표현을 모두 포함하는 것이 가능할 수 있다.

    1. representationMIME 타입mimeType으로 설정한다.

    2. representation데이터value로 설정한다.

    3. representationthis클립보드 항목표현 목록에 추가한다.

    4. mimeTypeStringmimeType으로 MIME 타입 직렬화를 실행한 결과로 둔다.

    5. isCustomtrue이면, mimeTypeString 앞에 `"web "`를 붙인다.

    6. mimeTypeStringtypes에 추가한다.

  7. thistypes 배열types에서 동결 배열 생성을 실행한 결과로 설정한다.

7.2.1. presentationStyle

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

7.2.2. types

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

7.2.3. getType(type)

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

  1. realmthis관련 Realm으로 둔다.

  2. isCustomfalse로 둔다.

  3. type이 `"web "` 접두사로 시작하면:

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

    2. isCustomtrue로 설정한다.

  4. mimeTypetype이 주어졌을 때 MIME 타입 파싱의 결과로 둔다.

  5. mimeType이 failure이면, TypeError를 던진다.

  6. itemTypeListthis클립보드 항목표현 목록으로 둔다.

  7. prealm 안의 새 Promise로 둔다.

  8. itemTypeList 안의 각 representation에 대해:

    1. representationMIME 타입mimeType이고 representationisCustomisCustom이면:

      1. this읽기 시점의 클립보드 변경 횟수가 null이 아니고, 현재 클립보드 변경 횟수this읽기 시점의 클립보드 변경 횟수와 같지 않으면, realm에서 "InvalidStateError" DOMException으로 p거부하고, p를 반환한다.

        Note: 이는 오래된 데이터가 절대 반환되지 않도록 보장한다. read()가 호출된 이후 시스템 클립보드 내용이 변경된 경우, 현재 시스템 클립보드 상태에 해당하지 않는 데이터를 반환하는 대신 반드시 실패해야 한다.

        Note: null인 읽기 시점의 클립보드 변경 횟수는 이 ClipboardItemread()에서 얻어진 것이 아니라 작성자가 직접 구성한 것임을 나타낸다(예: ClipboardItem(items, options)를 통해). 이 경우 데이터가 시스템 클립보드에서 비롯된 것이 아니므로 오래된 데이터 검사가 필요하지 않다.

      2. this읽기 시점의 클립보드 변경 횟수가 null이 아니면:

        Note: 이 분기는 read()에서 얻은 ClipboardItem들을 다루며, 이 경우 OS 클립보드 읽기는 이 지점까지 지연된다. 같은 MIME 타입에 대해 getType()이 동시에 여러 번 호출되더라도 타입당 읽기가 최대 한 번만 발생하도록, 결과 Promise는 정규화된 타입 문자열을 키로 하여 thisresolver를 가진 표현 맵에 캐시된다. 따라서 `"text/html"`과 `"web text/html"`은 독립적으로 추적되는 반면, 같은 타입의 대소문자만 다른 표기 (예: `"text/HTML"`과 `"text/html"`)는 하나의 항목으로 합쳐진다.

        1. keymimeTypeessence로 둔다. isCustom이 true이면, key 앞에 `"web "`를 붙인다.

        2. thisresolver를 가진 표현[key]가 존재하면, thisresolver를 가진 표현[key]를 반환한다.

        3. thisresolver를 가진 표현[key]를 p설정한다.

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

          1. clipboardItemthis원본 시스템 클립보드 항목으로 둔다.

          2. clipboardItem이 null이면, realm전역 객체가 주어졌을 때 클립보드 태스크 소스전역 태스크를 큐에 넣어, realm에서 "InvalidStateError" DOMException으로 p거부한 다음, 이 단계를 중단한다.

          3. isCustom이 true이면:

            1. mapNameOS별 사용자 정의 맵 이름으로 둔다.

            2. mapRepresentationclipboardItem시스템 클립보드 표현 목록 중 그 이름mapName시스템 클립보드 표현으로 둔다. 그러한 시스템 클립보드 표현이 없으면, realm전역 객체가 주어졌을 때 클립보드 태스크 소스전역 태스크를 큐에 넣어, realm에서 "NotFoundError" DOMException으로 p거부한 다음, 이 단계를 중단한다.

            3. webCustomFormatMapStringmapRepresentation데이터에서 역직렬화된 JSON 문자열로 둔다.

            4. osFormatNamewebCustomFormatMapString 안에서 mimeType직렬화된 값과 일치하는 키의 값으로 둔다.

            5. osFormatName을 찾을 수 없으면, realm전역 객체가 주어졌을 때 클립보드 태스크 소스전역 태스크를 큐에 넣어, realm에서 "NotFoundError" DOMException으로 p거부한 다음, 이 단계를 중단한다.

          4. 그렇지 않으면, osFormatNamemimeType이 주어졌을 때 OS별 잘 알려진 형식을 실행한 결과로 둔다.

          5. clipboardRepresentationclipboardItem시스템 클립보드 표현 목록 중 그 이름osFormatName시스템 클립보드 표현으로 둔다. 그러한 시스템 클립보드 표현이 없으면, realm전역 객체가 주어졌을 때 클립보드 태스크 소스전역 태스크를 큐에 넣어, realm에서 "NotFoundError" DOMException으로 p거부한 다음, 이 단계를 중단한다.

          6. rawDataclipboardRepresentation데이터로 둔다.

          7. cleanDatarawData의 복사본으로 둔다.

          8. mimeTypeessencethis비정제 MIME 타입 안에 있고, mimeTypeessence선택적 비정제 데이터 타입 목록 안에 있으면, 아무것도 하지 않는다.

          9. 그렇지 않고 mimeTypeessence가 "image/png"가 아니면, 사용자 에이전트는 cleanData를 정제해도 된다.

          10. blobBlob으로 둔다. 그 typemimeType직렬화된 값이고, 그 기반 바이트 시퀀스는 cleanData이다.

          11. realm전역 객체가 주어졌을 때, 클립보드 태스크 소스전역 태스크를 큐에 넣어 pblob으로 resolve한다.

        Note: p가 settled되면, 이는 thisresolver를 가진 표현 맵 안에 남는다. 같은 MIME 타입에 대한 이후 getType() 호출은 시스템 클립보드를 다시 읽지 않고 캐시된 settled Promise를 반환한다. 그러나 위의 오래된 데이터 검사는 모든 호출에 여전히 적용된다. 즉, read()가 호출된 이후 시스템 클립보드가 변경되었다면, 이 ClipboardItem에 대한 모든 getType() 호출은 이전에 캐시된 데이터에 대해서도 "InvalidStateError"로 거부된다.

        1. p를 반환한다.

      3. representationDataPromiserepresentation데이터로 둔다.

      4. representationDataPromise반응한다:

        1. representationDataPromise가 값 v로 fulfilled되었다면:

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

            1. dataAsBytesvUTF-8 인코딩 결과로 둔다.

            2. blobDatadataAsBytes를 사용하여 생성된 Blob으로 둔다. 그 typemimeType직렬화된 값으로 설정된다.

            3. pblobData로 resolve한다.

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

            1. pv로 resolve한다.

        2. representationDataPromise가 rejected되었다면:

          1. realm에서 "NotFoundError" DOMException으로 p거부한다.

            웹 개발자들은 기반 거부 이유에 관심을 가질 수 있다.

      5. p를 반환한다.

  9. realm에서 "NotFoundError" DOMException으로 p거부한다.

  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에서 하나의 클립보드 항목만 가져온다.

클립보드 항목들 객체는 sequence클립보드 항목들이다.

웹 작성자는 write(data) 메서드를 사용하여 시스템 클립보드에 콘텐츠를 쓰기 위해, ClipboardItem들의 배열인 data를 생성해야 한다. read()시스템 클립보드 데이터의 내용을 나타내는 클립보드 항목들 객체에 대한 Promise를 반환한다.

unsanitized는 작성자가 선택적 비정제 데이터 타입으로 취급되기를 원하는 MIME 타입에 대응하는 DOMString들의 sequence이다.

unsanitized 옵션은 사용자 에이전트에서 지원되지 않을 수도 있다. 이 옵션이 허용되지 않을 수 있는 프라이버시 모드가 있을 수 있으므로, 웹 작성자는 unsanitized에 나열된 MIME 타입의 콘텐츠가 비정제 상태일 것이라고 가정해서는 안 된다.

클립보드 태스크 소스시스템 클립보드 데이터의 읽기 또는 쓰기에 대한 응답으로 트리거된다.

7.3.1. read(formats)

read(formats) 메서드는 다음 단계를 실행해야 한다:
  1. realmthis관련 Realm으로 둔다.

  2. prealm 안의 새 promise로 둔다.

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

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

      1. format선택적 비정제 데이터 타입 안에 없으면, realm에서 format "NotAllowedError" DOMException으로 p거부한다.

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

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

    2. r이 false이면:

      1. realm전역 객체가 주어졌을 때, 권한 태스크 소스전역 태스크를 큐에 넣어, realm에서 "NotAllowedError" DOMException으로 p거부한다.

      2. 이 단계를 중단한다.

    3. data시스템 클립보드 데이터로 둔다.

    4. snapshotChangeCount를 현재 클립보드 변경 횟수로 둔다.

      Note: 이 시점에서는 data이름(형식 식별자)만 열거된다. 각 표현의 기반 페이로드 바이트는 getType()이 호출될 때까지 읽히지 않는다.

    5. itemssequenceordered map들로 둔다. 각 항목은 "item"(클립보드 항목)과 "originating"(시스템 클립보드 항목 또는 null) 키를 가진다.

    6. data 안의 각 systemClipboardItem에 대해:

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

      2. systemClipboardItem 안의 각 systemClipboardRepresentation에 대해:

        1. mimeTypesystemClipboardRepresentation이름이 주어졌을 때 OS별 형식으로부터의 잘 알려진 MIME 타입 알고리즘을 실행한 결과로 둔다.

        2. mimeType이 null이면, 이 루프를 계속한다.

        3. representation을 새 표현으로 둔다.

        4. representationMIME 타입mimeType으로 설정한다.

        5. representation데이터realm 안의 새 promise로 설정한다.

          Note:표현에 대한 OS 클립보드 데이터는 작성자가 결과 ClipboardItem 객체에서 getType()을 호출할 때까지 가져오지 않는다.

        6. representationitem표현 목록에 추가한다.

      3. item표현 목록 크기가 0보다 크면, ordered map «[ "item" → item, "originating" → systemClipboardItem ]»을 items에 추가한다.

    7. items의 크기가 > 0이면:

      1. firstItemitems[0]["item"]으로 둔다

      2. firstItem이 주어졌을 때 웹 사용자 정의 형식 읽기 알고리즘을 실행한다.

    8. 그렇지 않으면:

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

      2. customItem이 주어졌을 때 웹 사용자 정의 형식 읽기 알고리즘을 실행한다.

      3. customItem표현 목록 크기가 0보다 크면, ordered map «[ "item" → customItem, "originating" → null ]»을 items에 추가한다.

    9. realm전역 객체가 주어졌을 때, 클립보드 태스크 소스전역 태스크를 큐에 넣어, 아래 단계를 수행한다:

      1. clipboardItemssequence<ClipboardItem>로 둔다.

      2. items의 각 ordered map entry에 대해:

        1. clipboardItementry["item"]과 realm이 주어졌을 때 ClipboardItem 객체 생성의 단계를 실행한 결과로 둔다.

        2. clipboardItem읽기 시점의 클립보드 변경 횟수snapshotChangeCount로 설정한다.

        3. clipboardItem원본 시스템 클립보드 항목entry["originating"]으로 설정한다.

        4. formats가 비어 있지 않으면, clipboardItem비정제 MIME 타입formats["unsanitized"]로 설정한다.

        5. clipboardItemclipboardItems에 추가한다.

      3. pclipboardItems로 resolve한다.

  5. p를 반환한다.

// clipboard.read()는 타입 메타데이터만 있는 ClipboardItems를 반환한다.
// 이 시점에서는 OS 클립보드 데이터를 읽지 않는다.
const items = await navigator.clipboard.read();

// getType()이 호출될 때, 여기서 OS 클립보드 읽기가 지연 수행된다.
const textBlob = await items[0].getType("text/plain");
const text = await (new Response(textBlob)).text();

7.3.2. readText()

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

  2. prealm 안의 새 promise로 둔다.

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

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

    2. r이 false이면:

      1. realm전역 객체가 주어졌을 때, 권한 태스크 소스전역 태스크를 큐에 넣어, realm에서 "NotAllowedError" DOMException으로 p거부한다.

      2. 이 단계를 중단한다.

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

      일부 OS는 여러 클립보드를 포함한다(예: Linux, "primary", "secondary", "selection"). 이들 중 어느 데이터에서 읽는지 정의하라.

      정제된 복사본의 정의를 추가하라.

    4. realm전역 객체가 주어졌을 때, 클립보드 태스크 소스전역 태스크를 큐에 넣어, 아래 단계를 수행한다:

      1. data 안의 각 systemClipboardItem에 대해:

        1. systemClipboardItem 안의 각 systemClipboardRepresentation에 대해:

          1. mimeTypesystemClipboardRepresentation이름이 주어졌을 때 OS별 형식으로부터의 잘 알려진 MIME 타입 알고리즘을 실행한 결과로 둔다.

          2. mimeType이 null이면, 이 루프를 계속한다.

          3. representation을 새 표현으로 둔다.

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

            1. representationMIME 타입mimeType으로 설정한다.

            2. representationDataPromiserepresentation데이터로 둔다.

            3. 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가 rejected되었다면:

                1. realm에서 "NotFoundError" DOMException으로 p거부한다.

                2. p를 반환한다.

      2. realm에서 "NotFoundError" DOMException으로 p거부한다.

      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 안의 새 promise로 둔다.

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

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

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

    2. r이 false이면:

      1. realm전역 객체가 주어졌을 때, 권한 태스크 소스전역 태스크를 큐에 넣어, realm에서 "NotAllowedError" DOMException으로 p거부한다.

      2. 이 단계를 중단한다.

    3. realm전역 객체가 주어졌을 때, 클립보드 태스크 소스전역 태스크를 큐에 넣어, 아래 단계를 수행한다:

      1. itemListcleanItemList를 빈 sequence<Blob>로 둔다.

      2. dataListsequence<ClipboardItem>로 둔다.

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

        data가 여러 항목을 포함하고 운영 체제가 여러 네이티브 클립보드 항목을 지원하는 경우, 현재 알고리즘은 해당 항목들을 한꺼번에 쓰는 대신 순서대로 시스템 클립보드에 쓴다.

      4. dataList 안의 각 clipboardItem에 대해:

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

          1. representationDataPromiserepresentation데이터로 둔다.

          2. representationDataPromise반응한다:

            1. representationDataPromise가 값 v로 fulfilled되었다면:

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

                1. dataAsBytesvUTF-8 인코딩 결과로 둔다.

                2. blobDatadataAsBytes를 사용하여 생성된 Blob으로 둔다. 그 typerepresentationMIME 타입으로 설정된다.

                3. blobDataitemList에 추가한다.

              2. vBlob이면, vitemList에 추가한다.

            2. representationDataPromise가 rejected되었다면:

              1. realm에서 "NotAllowedError" DOMException으로 p거부한다.

              2. 이 단계를 중단한다.

        2. itemList 안의 각 blob에 대해:

          1. typeblobtype으로 둔다.

          2. type필수 데이터 타입 또는 선택적 데이터 타입 목록 안에 없으면, realm에서 "NotAllowedError" DOMException으로 p거부하고 이 단계를 중단한다.

          3. cleanItemblob의 선택적으로 정제된 복사본으로 둔다.

            정제된 복사본의 정의를 추가하라.

          4. 정제가 시도되었으나 성공적으로 완료되지 않았다면, 아래 단계를 따른다:

            1. realm에서 "NotAllowedError" DOMException으로 p거부한다.

            2. 이 단계를 중단한다.

          5. cleanItemcleanItemList에 추가한다.

        3. optionclipboardItem클립보드 항목표현 스타일로 둔다.

        4. cleanItemListoption으로 blob 및 옵션을 클립보드에 쓰기를 실행한다.

      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 안의 새 promise로 둔다.

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

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

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

    2. r이 false이면:

      1. realm전역 객체가 주어졌을 때, 권한 태스크 소스전역 태스크를 큐에 넣어, realm에서 "NotAllowedError" DOMException으로 p거부한다.

      2. 이 단계를 중단한다.

    3. realm전역 객체가 주어졌을 때, 클립보드 태스크 소스전역 태스크를 큐에 넣어, 아래 단계를 수행한다:

      1. itemList를 빈 sequence<Blob>로 둔다.

      2. textBlob를 다음과 같이 생성된 새 Blob으로 둔다: type 속성은 "text/plain;charset=utf-8"로 설정되고, 그 기반 바이트 시퀀스는 dataUTF-8 인코딩으로 설정된다.

        Note: Windows에서는 textBlob를 생성하기 전에 data 안의 `\n` 문자를 `\r\n`으로 바꾼다.

      3. textBlobitemList에 추가한다.

      4. option을 "unspecified"로 설정한다.

      5. itemListoption으로 blob 및 옵션을 클립보드에 쓰기를 실행한다.

      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, sequence<Blob>

presentationStyle, 클립보드 항목표현 스타일

출력

없음

  1. webCustomFormatssequence<Blob>로 둔다.

  2. items 안의 각 item에 대해:

    1. formatStringitemtype이 주어졌을 때 OS별 잘 알려진 형식을 실행한 결과로 둔다.

    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. formatString을 네이티브 클립보드 형식으로 사용하여 payloadpresentationStyle시스템 클립보드에 삽입한다.

    일부 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. CF_UNICODETEXT를 wellKnownFormat에 할당한다.

    MacOS에서는 아래에 설명된 규칙을 따른다:

    1. NSPasteboardTypeString을 wellKnownFormat에 할당한다.

    Linux, ChromeOS 및 Android에서는 아래에 설명된 규칙을 따른다:

    1. "text/plain"을 wellKnownFormat에 할당한다.

  3. 그렇지 않고, mimeTypeessence가 "text/html"이면,

    Windows에서는 아래에 설명된 규칙을 따른다:

    1. CF_HTML을 wellKnownFormat에 할당한다.

    MacOS에서는 아래에 설명된 규칙을 따른다:

    1. NSPasteboardTypeHTML을 wellKnownFormat에 할당한다.

    Linux, ChromeOS 및 Android에서는 아래에 설명된 규칙을 따른다:

    1. "text/html"을 wellKnownFormat에 할당한다.

  4. 그렇지 않고, mimeTypeessence가 "image/png"이면,

    Windows에서는 아래에 설명된 규칙을 따른다:

    1. "PNG"를 wellKnownFormat에 할당한다.

    MacOS에서는 아래에 설명된 규칙을 따른다:

    1. NSPasteboardTypePNG를 wellKnownFormat에 할당한다.

    Linux, ChromeOS 및 Android에서는 아래에 설명된 규칙을 따른다:

    1. "image/png"를 wellKnownFormat에 할당한다.

  5. 그렇지 않고, mimeTypeessence가 "image/svg+xml"이면,

    Windows에서는 아래에 설명된 규칙을 따른다:

    1. CFSTR_MIME_SVG_XML을 wellKnownFormat에 할당한다.

    MacOS에서는 아래에 설명된 규칙을 따른다:

    1. UTTypeSVG를 wellKnownFormat에 할당한다.

    Linux, ChromeOS 및 Android에서는 아래에 설명된 규칙을 따른다:

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

  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 문자열로 둔다.

    Note: webCustomFormatMap에서 콘텐츠를 역직렬화하려면 JSON 리더가 필요하다.

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

    1. mimeTypekey가 주어졌을 때 MIME 타입 파싱의 결과로 둔다.

    2. mimeType이 failure이면, 루프를 계속한다.

    3. representation을 새 표현으로 둔다.

    4. representationMIME 타입mimeType으로 설정한다.

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

    6. representation데이터새 promise로 설정한다.

      Note: 이 웹 사용자 정의 형식에 대한 OS 클립보드 데이터는 작성자가 결과 getType()ClipboardItem 객체에서 호출할 때까지 가져오지 않는다.

    7. representationitem표현 목록에 추가한다.

웹 커스텀 포맷 쓰기

입력

items, sequence<Blob>

  1. idx를 0으로 초기화된 숫자로 둔다.

  2. webCustomFormatMapOS별 사용자 정의 맵 이름으로 둔다.

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

  4. items 안의 각 item에 대해:

    1. webCustomFormatOS별 사용자 정의 이름으로 둔다.

    2. webCustomFormatIdxidxwebCustomFormat에 추가한 결과로 둔다.

    3. itemtype을 키로, webCustomFormatIdx를 값으로 하여 JSON serializer를 사용해 webCustomFormatMapString에 삽입한다.

      Note: 콘텐츠를 webCustomFormatMapString으로 직렬화하려면 JSON writer가 필요하다.

    4. webCustomFormatIdx를 형식으로 사용하여 item시스템 클립보드에 삽입한다.

    5. idx를 증가시킨다.

    6. idx가 100보다 크면, 이 루프에서 빠져나온다.

  5. webCustomFormatMap을 형식으로 사용하여 webCustomFormatMapString시스템 클립보드에 삽입한다.

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 표준. Living Standard. URL: https://dom.spec.whatwg.org/
[ENCODING]
Anne van Kesteren. Encoding 표준. Living Standard. URL: https://encoding.spec.whatwg.org/
[FileAPI]
Marijn Kruisselbrink. File API. 2026년 6월 4일. WD. URL: https://www.w3.org/TR/FileAPI/
[HTML]
Anne van Kesteren; et al. HTML 표준. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. Living Standard. URL: https://infra.spec.whatwg.org/
[MIMESNIFF]
Gordon P. Hemsley. MIME Sniffing 표준. Living Standard. 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 Uniform Resource Locators. 1998년 8월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc2392
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. Living Standard. 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;
};

이슈 색인

웹 개발자는 내부적인 거부 사유에 관심을 가질 수 있습니다.
일부 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?