🎈 Document.execCommand
예전에는 Document.execCommand 메서드를 사용해서 복사 및 붙여넣기 기능을 사용하였다.
아래는 복사 버튼을 클릭 시, id가 email인 태그의 값을 복사하는 기능이다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p id="email">email@email.com</p>
<button id="copy">복사</button>
</body>
</html>
Document.execCommand 메서드를 활용해서 다음과 같이 복사 기능을 사용할 수 있다. 복사 버튼 클릭 후 붙여넣기 기능을 수행하면 email@email.com가 클립보드에 정상적으로 복사된 것을 확인할 수 있다.
<script>
document.getElementById('copy').addEventListener('click', function() {
const emailElement = document.getElementById('email');
const range = document.createRange();
range.selectNodeContents(emailElement);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
});
</script>
📯 Document.execCommand의 문제점
첫번째, Dom을 대상으로만 사용이 가능하다. 위의 코드를 보면 알 수 있듯이, Dom이 선택 된 상태에서만 가능하기 때문에 강제로 선택상태로 만든 후 복사가 완료되면 선택상태를 해제하는 방식을 사용한다. 위의 코드만 실행하게 되면 선택영역이 그대로 남아있는 것을 확인할 수 있다. 이로인해 정확한 복사를 수행하기 위한 선택 영역을 설정해야하는 문제가 존재한다.
두번째, execCommand는 동적으로 작동하게 된다. 간단한 텍스트를 복사하는 것에는 크게 성능적으로 문제가 되지 않을 수 있지만 용량이 큰 이미지를 복사하는 경우 등 클립보드 작업을 위해 페이지를 차단하기 때문에 좋지 않다.
이러한 이유 때문에 지원이 중단되었기 때문에 이 기능을 사용하는 것은 더 이상 권장되지 않는다.
🛒 Clipboard API 사용하기
Clipboard API는 document.execCommand를 대체하기 위해서 등장하였다. 기존의 문제 중 하나인 동기방식에서 비동기 방식으로 변경되었다. 클립보드 API를 사용할 때는 Navigator.clipboard 를 통해서 사용하면 된다.
1️⃣ 복사하기
텍스트를 복사하기 위해서는 writeText 메서드를 사용하면 된다. 위의 코드를 execCommand 대신 클립보드 API를 통해 복사하는 코드로 변경해 보았다. 훨씐 간결하고 직관적인 코드로 바뀌게 되었다. 비동기 방식으로 변경되었기 때문에 Dom을 차단하는 것도 막을 수 있다.
<script>
document.getElementById('copy').addEventListener('click', function() {
const email = document.getElementById('email');
navigator.clipboard
.writeText(email.textContent)
.then(() => {
console.log('복사완료')
})
});
</script>
writeText 메서드는 오직 텍스트만 복사가 가능하다. HTML 문서 또는 이미지 등을 복사하기 위해서는 write 메서드를 사용하면 된다. write 메서드는 ClipboardItem 데이터를 저장한다. ClipboardItem 에 텍스트나 이미지를 저장하여 클립보드로 전달하게 된다.
아래는 이미지를 클립보드에 저장하는 코드이다.
<script>
try {
const image = './image.png';
const data = await fetch(image);
const blob = await data.blob();
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
} catch (err) {
console.error('Failed to copy: ', err);
}
</script>
✨ 이미지를 저장하기 위해서는 blob 이어야 한다.
현재 클립보드에서 지원 가능한 타입은 다음과 같다,
- text/plain
- text/html
- image/png
일부 브라우저에서 지원하는 타입은 다음과 같다.
- image/svg+xml
✨ Text 또한 blob 타입으로 전달하여야 한다.
2️⃣ 다중 타입 클립보드 복사
한번에 다중 타입의 데이터를 복사하고 싶을 수 있다. 위의 코드를 보면 배열에 추가하면 될 것 같지만, 아래와 같은 에러를 만나게 된다.
Failed to copy: NotAllowedError: Failed to execute 'write' on 'Clipboard': Support for multiple ClipboardItems is not implemented.
아래와 같이 ClipboardItem에 한번에 다중 타입을 저장할 수 있다.
const image = './image.png';
const data = await fetch(image);
const blob = await data.blob();
const textData = "복사할 텍스트";
const textBlob = new Blob([textData], { type: 'text/plain' });
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob,
'text/plain': textBlob,
}),
]);
3️⃣ 붙여넣기
붙여넣기는 read 메서드를 사용하면 된다. 아래는 복사된 이미지를 붙여넣기 하는 코드이다. 한번에 여러개의 타입을 복사할 수 있기 때문에 read시에도 반복문을 통해서 처리하면 된다.
try {
const clipboardItems = await navigator.clipboard.read();
for (const clipboardItem of clipboardItems) {
const types = clipboardItem.types;
for (const type of types) {
const blob = await clipboardItem.getType(type);
if (blob.type.startsWith('text/')) {
const text = await blob.text();
document.getElementById('result').innerText += text;
} else if (blob.type.startsWith('image/')) {
const url = URL.createObjectURL(blob);
document.getElementById('result').innerHTML += `<img src="${url}" alt="image" />`;
}
}
}
} catch (err) {
console.error('Failed to paste: ', err);
}
만약 ctrl + v와 같은 단축키를 사용한다면 아래와 같이 paste 이벤트를 활용하면 된다.
document.addEventListener("paste", async e => {
// 여기에 위의 코드와 동일하게 작성하면 된다.
});
4️⃣ 주의 사항
클립보드 API는 HTTPS를 제공하는 페이지에서만 지원한다. 페이지에서 사용자의 민감한 정보를 복사해놓고 이를 탈취하는 등의 보안상 문제를 발생시킬 수 있기 때문에 HTTPS에서만 사용할 수 있도록 제한하고 있다.
'Javascript' 카테고리의 다른 글
[Node] 이메일 전송 (0) | 2025.04.13 |
---|---|
[Javascript] 소수점 표현 (0) | 2025.04.11 |
[Javascript] EyeDropper API (0) | 2025.03.15 |
비동기함수 순차 실행 (0) | 2025.01.21 |
[자바스크립트 - Canvas] 1. 시작하기 - 도형 그리기 (0) | 2023.03.20 |