Safari - Clipboard 이슈

dev_hyun·2023년 8월 25일
1

IE가 없어지더니 Safari가 문제다 🤬🤬🤬🤬
비동기로직을 통해 클립보드에 복사할 상황이 생겨 개발하던 도중 겪은 이슈이다.

비동기 객체를 복사하기

단순히 텍스트를 복사할 때는 Clipboard api를 사용하면 브라우저에 관계없이 쉽게 복사가 가능하다.
그러나 구현해야하는 기능이 비동기로 받아오는 값을 복사해야 했다.
크롬은 문제없이 잘되었지만 Safari 에서 이슈가 발생했다.

비동기 로직없이 복사하기

const btnCopy = document.querySelector('#btnCopy');
 
// 복사 전 비동기 로직 없을 때 (사파리도 가능)
btnCopy.addEventListener('click', function(e) {
     const url = location.href;
     navigator.clipboard.writeText(url).then(
         // success
         () => {
            navigator.clipboard.readText().then(clipText => document.querySelector("#text").innerText += clipText);
         },
         // fail
         () => {
             alert('복사에 실패했습니다');
         }
     );
});

비동기로 text를 가져오는 것이 아닌 그냥 dom의 text를 복사하고 싶을때에는 위의 코드도 잘 동작한다.

비동기 로직있을때 복사하기

그러나 비동기로 객체를 복사해야 할때 같은 코드의 경우 사파리에서 동작을 하지 않는다.

const testPromiseFunc = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(location.href);
        }, 1000);
    });
};
 
// 복사 전 비동기 로직 있을 때
btnCopy.addEventListener('click', function(e) {
  	 const clipText = await testPromiseFunc();
     navigator.clipboard.writeText(url).then(
         // success
         () => {
            navigator.clipboard.readText().then(() => document.querySelector("#text").innerText += clipText);
         },
         // fail
         () => {
             alert('복사에 실패했습니다');
         }
     );
});

이렇게 처리할 경우 사파리는 동작을 하지 않는다.
사파리에서 복사를 할 경우 다음과 같은 오류를 내게 된다.

"On iOS this results in the error: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission."

이를 해결하기 위해 다른 방법을 사용해야 한다.

해결 방법

아래는 같은 이슈에 대한 글과 해결 방법이다.

(같은 이슈 및 해결 방안)

const testPromiseFunc = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(window.location.href);
        }, 1000);
    });
};
 
// 복사 전 비동기 로직 있을 때
btnCopy.addEventListener('click', function (e) {
    const clipboardItem = new ClipboardItem({
        'text/plain': testPromiseFunc().then((result) => {
            return new Promise(async (resolve) => {
                resolve(new Blob([result]))
            })
        }),
    });
    navigator.clipboard.write([clipboardItem]);
});

이렇게 사용을 하게 되면 Clipboard 객체 내에서 프로미스 작업을 처리해서 비동기 텍스트도 복사할 수 있게 된다.
근데 이 코드는 오로지 "사파리" 에서만 동작을 하기 때문에 사파리에서만 분기처리를 해줘야 해서 코드가 더러워진다.

진짜 Safari is the new IE...🥶

profile
하다보면 안되는 것이 없다고 생각하는 3년차 프론트엔드 개발자입니다.

0개의 댓글