사파리에서 안 되는 클립보드 복사 — QR 공유 호환
크롬에서는 잘 되던 QR 코드 클립보드 복사가 사파리에서만 실패했다. 버그가 아니라 Safari의 클립보드 정책이었고, 정책과 싸우는 대신 복사 흐름을 그 규칙에 맞춰 다시 짰다.
문제
URL 공유 모달에서 QR 코드를 클립보드에 복사하는 기능이 크롬은 정상, 사파리는 실패했다.
원인: Safari의 클립보드 정책
Safari는 navigator.clipboard.write를 사용자 제스처(클릭) 컨텍스트 안에서, 쓰기 대상이 이미
준비된 상태일 때만 허용한다. QR 이미지를 클릭 후 비동기로 만들어서 복사하면, 그 사이에 제스처
컨텍스트가 끊겨 Safari가 거부했다.
해결: blob 미리 생성 + 클릭 시 즉시 복사
QR 이미지(blob)를 모달이 열릴 때 미리 만들어 두고, 클릭 핸들러에서는 ClipboardItem으로
즉시 복사만 하도록 분리했다.
// 모달이 열릴 때 미리 QR blob 생성
const generateQRCodeBlob = async () => {
const canvas = await html2canvas(qrCodeRef.current);
canvas.toBlob((blob) => blob && setQrCodeBlob(blob));
};
// 클릭 시에는 준비된 blob을 즉시 복사
const handleCopyQRCode = async () => {
if (!qrCodeBlob) return;
try {
await navigator.clipboard.write([new ClipboardItem({ "image/png": qrCodeBlob })]);
showSuccess("QR 코드가 클립보드에 복사되었습니다!");
} catch {
showWarning("Safari가 클립보드 복사를 지원하지 않습니다. Chrome을 사용해주세요.");
}
};배운 점
클립보드처럼 권한이 필요한 API는 사용자 제스처 컨텍스트가 핵심이다. "비동기 작업 후 복사"가 아니라 "미리 준비 → 클릭 시 즉시 복사"로 바꾸면 브라우저별 차이를 줄일 수 있다.