Clipboard API

김동현·2026년 3월 22일

Clipboard API

Clipboard API는 클립보드 명령(잘라내기, 복사, 붙여넣기)에 응답하고, 시스템 클립보드에서 비동기적으로 읽고 쓸 수 있는 기능을 제공해요.

참고:
클립보드에 접근하기 위해서는 더 이상 사용되지 않는 document.execCommand() 메서드보다 이 API를 우선적으로 사용하세요.

참고:
이 API는 Web Workers에서 사용할 수 없어요 (WorkerNavigator를 통해 노출되지 않아요).

클립보드 API 개념 및 사용법 (Concepts and usage)

안녕하세요, 예비 프론트엔드 개발자 여러분! 오늘 다뤄볼 주제는 실무에서 정말 유용하게 쓰이는 클립보드 API(Clipboard API)입니다. 사용자들에게 "복사하기" 버튼을 제공하거나, 붙여넣기 한 데이터를 가로채서 처리할 때 반드시 알아야 하는 아주 중요한 API죠. 원본 문서를 하나도 빠짐없이 꼼꼼하게 번역해 드리고, 실무 꿀팁도 팍팍 얹어드릴 테니 잘 따라와 주세요!


시스템 클립보드(system clipboard)는 브라우저를 실행하고 있는 운영체제(OS)에 속한 데이터 버퍼(임시 저장 공간)입니다. 문서 간이나 애플리케이션 간에 데이터를 단기적으로 저장하거나 전송할 때 사용되죠.
보통 이 공간은 환경 내의 대부분 혹은 모든 프로그램에서 정해진 프로그래밍 인터페이스를 통해 접근할 수 있는 익명의 임시 데이터 버퍼(때로는 붙여넣기 버퍼(paste buffer)라고도 부름)로 구현됩니다.

클립보드 API를 사용하면, 사용자가 보안 컨텍스트(Secure contexts, HTTPS 환경) 내에서 (그리고 뒤에 나올 보안 고려사항의 기준을 충족한 경우에 한해) 시스템 클립보드에서 텍스트나 기타 데이터를 프로그래밍 방식으로 읽고 쓸 수 있습니다.

클립보드를 수정하는 작업인 cut (잘라내기), copy (복사하기), paste (붙여넣기) 작업의 결과로 이벤트가 발생(fire)하게 됩니다.
이 이벤트들은 기본 동작(default action)을 가지고 있습니다. 예를 들어, copy 동작은 기본적으로 현재 선택된 텍스트나 요소를 시스템 클립보드에 복사합니다.
물론 이벤트 핸들러를 사용하면 이러한 기본 동작을 재정의(override)하여 막을 수 있습니다. 자세한 내용은 각 이벤트 문서를 참고하세요.

또한, 시스템 클립보드의 내용이 변경될 때마다 Clipboard 객체에서 직접 발생하는 clipboardchange 이벤트도 있습니다. 이 이벤트는 앱 자체적으로 내장된 클립보드를 시스템 클립보드와 동기화된 상태로 유지해야 할 때, 시스템 클립보드의 변경 사항을 앱에 알리는 용도로 아주 유용합니다.

💡 강사의 팁: 요즘 웹사이트에서 '초대 링크 복사하기'나 '할인 코드 복사' 버튼을 흔히 볼 수 있죠? 과거에는 document.execCommand('copy')라는 다소 투박하고 구식인 방법을 사용했지만, 이제는 이 클립보드 API가 그 자리를 완벽하게 대체했습니다. 비동기적으로 동작하기 때문에 브라우저가 멈추지도 않고 훨씬 안전하답니다!


인터페이스 (Interfaces)

클립보드 API를 구성하는 주요 객체(인터페이스)들을 살펴봅시다.

Clipboard 보안 컨텍스트 (Secure context)

시스템 클립보드에 텍스트와 데이터를 읽고 쓰기 위한 핵심 인터페이스를 제공합니다. 명세서(specification)에서는 이를 '비동기 클립보드 API(Async Clipboard API)'라고 부릅니다.

ClipboardChangeEvent

시스템 클립보드의 내용이 변경될 때마다 발생하는 이벤트를 나타냅니다.

ClipboardEvent

클립보드 수정과 관련된 정보, 즉 cut, copy, paste 이벤트에 대한 정보를 제공하는 이벤트 객체입니다. 명세서에서는 이를 '클립보드 이벤트 API(Clipboard Event API)'라고 부릅니다.

ClipboardItem 보안 컨텍스트 (Secure context)

데이터를 읽거나 쓸 때 사용되는 단일 항목의 형식(format)을 나타냅니다. (예: 텍스트인지, 이미지인지 등을 구분)


다른 인터페이스로의 확장 (Extensions to other interfaces)

클립보드 API는 다음 API들에 기능을 확장하여 다음과 같은 요소들을 추가합니다.

Navigator.clipboard 읽기 전용 (Read only) 보안 컨텍스트 (Secure context)

시스템 클립보드에 읽기 및 쓰기 접근 권한을 제공하는 Clipboard 객체를 반환합니다. (가장 많이 쓰게 될 진입점입니다!)

Element copy 이벤트

사용자가 복사(copy) 동작을 시작할 때마다 발생하는 이벤트입니다.

Element cut 이벤트

사용자가 잘라내기(cut) 동작을 시작할 때마다 발생하는 이벤트입니다.

Element paste 이벤트

사용자가 붙여넣기(paste) 동작을 시작할 때마다 발생하는 이벤트입니다.


보안 고려사항 (Security considerations)

클립보드 API를 사용하면 보안 컨텍스트(HTTPS) 내에서 프로그래밍 방식으로 텍스트나 데이터를 클립보드에 읽고 쓸 수 있습니다. 클립보드에는 비밀번호나 개인정보 같은 아주 민감한 내용이 들어있을 수 있기 때문에, 브라우저는 이 API의 사용을 굉장히 엄격하게 통제합니다.

클립보드에서 데이터를 읽을 때(reading), 명세서에서는 사용자가 최근에 페이지와 상호작용했어야 하며(일시적인 사용자 활성화, transient user activation), 이 호출이 브라우저나 OS의 "붙여넣기 요소"(예: 마우스 우클릭 메뉴에서 "붙여넣기" 선택)와 상호작용한 결과로 발생해야 한다고 요구합니다. 하지만 실제 환경에서 브라우저들은 이 요구사항을 완벽하게 따르기보다는, 권한 승인 창을 띄우거나 작업별로 알림(prompt)을 띄우는 등 다른 형태의 제약을 두어 읽기 작업을 허용하는 경우가 많습니다.

클립보드에 데이터를 쓸 때(writing), 명세서에서는 해당 페이지가 Permissions APIclipboard-write 권한을 부여받았을 것을 기대하며, 브라우저는 추가로 일시적인 사용자 활성화(클릭 등)를 요구할 수도 있습니다. 브라우저 제조사들은 클립보드에 접근하는 메서드 사용에 대해 추가적인 자체 제한을 둘 수 있습니다.

clipboardchange 이벤트는 오직 지속적인 사용자 활성화(sticky activation) 상태이거나 clipboard-read 권한이 부여된 후에만 발생합니다.

실제 브라우저들의 구현 방식은 공식 명세서와 조금씩 다르게 발전해 왔습니다. 그 차이점은 아래 요약되어 있으며, 자세한 내용은 호환성 표에서 확인할 수 있습니다.

크로미움(Chromium) 계열 브라우저 (Chrome, Edge 등):

  • 명세서상으로 읽기가 허용되지 않는 상황이더라도 해당 문서가 포커스(focus)를 가지고 있다면, clipboard-read 권한을 요청하는 팝업을 띄웁니다. 사용자가 수락하거나 이미 권한이 부여되어 있다면 읽기에 성공합니다.
  • 쓰기 작업을 하려면 clipboard-write 권한이 있거나 일시적인 사용자 활성화(클릭 이벤트 등)가 필요합니다. 한 번 권한이 부여되면 그 상태가 지속되므로, 이후에는 클릭 없이도 쓸 수 있습니다.
  • 클립보드에 접근하는 <iframe> 요소의 경우, HTTP의 Permissions-Policy 헤더에서 clipboard-readclipboard-write 권한을 명시적으로 허용해주어야 합니다.

파이어폭스(Firefox) & 사파리(Safari):

  • 명세서상 읽기가 허용되지 않지만 일시적인 사용자 활성화 조건은 충족된 경우, 브라우저가 직접 일회용(ephemeral) 컨텍스트 메뉴를 띄워 "붙여넣기" 옵션 하나만 사용자에게 보여줍니다 (1초 후 활성화됨). 사용자가 이걸 직접 클릭해야만 읽기에 성공합니다.
  • 쓰기 작업은 반드시 일시적인 사용자 활성화(클릭 등)가 필요합니다.
  • 같은 출처(same-origin)의 클립보드 내용을 읽을 때는 붙여넣기 확인 팝업이 생략되지만, 교차 출처(cross-origin, 다른 사이트에서 복사한 내용)일 때는 팝업이 뜹니다.
  • 파이어폭스와 사파리에서는 아예 clipboard-readclipboard-write 같은 명시적인 권한 승인 기능 자체를 지원하지 않으며, 지원할 계획도 없습니다. (즉, 매번 액션이 필요합니다.)

파이어폭스 웹 익스텐션(Web Extensions):

  • 익스텐션 권한 매니페스트에 clipboardRead 권한이 있는 경우, 사용자의 활성화 제스처나 붙여넣기 팝업 없이도 자유롭게 읽을 수 있습니다. (Firefox 147부터는 보안 컨텍스트 내에서 사용자 활성화가 있고 붙여넣기 팝업을 클릭하면 권한 명시 없이도 읽기가 가능해졌습니다.)
  • 쓰기는 보안 컨텍스트 내에서 사용자 활성화가 있을 때 가능합니다. 단, 매니페스트에 clipboardWrite 권한이 명시되어 있다면 사용자 활성화(클릭) 없이도 맘대로 쓸 수 있습니다.

💡 강사의 팁: 실무에서 클립보드 API를 쓸 때 가장 많이 겪는 에러가 바로 NotAllowedError입니다. "왜 버튼을 안 누르고 setTimeout 안에서 복사를 시도하면 실패하나요?"라고 많이 물어보시는데요, 브라우저는 악성 사이트가 마음대로 클립보드를 오염시키거나 훔쳐보는 것을 막기 위해 "사용자가 버튼을 클릭하는 바로 그 찰나의 순간(Transient user activation)"에만 클립보드 쓰기/읽기를 허락하기 때문입니다! 따라서 클립보드 코드는 반드시 버튼의 onClick 핸들러 안에 동기적으로 묶어두는 것이 정신 건강에 좋습니다.


예제 (Examples)

클립보드 접근하기 (Accessing the clipboard)

시스템 클립보드는 전역 객체인 Navigator.clipboard를 통해 접근합니다.

아래 코드 스니펫은 클립보드에서 텍스트를 가져와(fetch) editor라는 클래스를 가진 첫 번째 DOM 요소에 그 텍스트를 갖다 붙이는(append) 예제입니다.
만약 클립보드에 복사된 내용이 텍스트가 아니라면(예: 이미지 파일), readText() 메서드는 빈 문자열을 반환하기 때문에 이 코드는 안전하게 동작합니다.

navigator.clipboard
  .readText()
  .then(
    (clipText) => (document.querySelector(".editor").innerText += clipText),
  );

💡 강사의 팁: 원본 코드는 .then()을 사용한 프로미스(Promise) 체이닝 방식으로 작성되어 있네요. 최신 자바스크립트 트렌드인 async/await를 사용하면 아래처럼 훨씬 직관적이고 깔끔하게 작성할 수 있습니다!

button.addEventListener("click", async () => {
  try {
    const clipText = await navigator.clipboard.readText();
    document.querySelector(".editor").innerText += clipText;
  } catch (err) {
    console.error("클립보드 읽기 실패!", err);
  }
});

수고하셨습니다! 클립보드 API를 통해 사용자와 더 편리하게 데이터를 주고받을 수 있는 기반을 다지셨네요. 보안 제약(클릭 이벤트 안에서 실행하기, HTTPS 적용하기)만 잊지 않으신다면 실무에서 아주 유용하게 쓰일 겁니다.

profile
프론트에_가까운_풀스택_개발자

0개의 댓글