커넥트립

사파리에서 안 되는 클립보드 복사 — 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는 사용자 제스처 컨텍스트가 핵심이다. "비동기 작업 후 복사"가 아니라 "미리 준비 → 클릭 시 즉시 복사"로 바꾸면 브라우저별 차이를 줄일 수 있다.