-
복사 버튼은 눌렀는데 클립보드가 안 바뀌는 이유Programming 2026. 10. 4. 00:48728x90반응형

writeText의 완료를 기다린 뒤 성공을 표시하고, 실패하면 원문을 선택할 수 있게 합니다. 버튼을 누르면 ‘복사했습니다’가 뜨는데, 붙여넣으면 이전 문구가 나옵니다. 이런 버튼의 코드를 보면
writeText()를 호출한 직후 성공 안내를 띄우는 경우가 있습니다. 호출했다는 사실과 쓰기가 끝났다는 사실 사이에 실패할 수 있는 구간이 빠진 것입니다.Clipboard API의 성공 응답을 확인한 뒤 복사 완료를 표시하고, 보안 컨텍스트·사용자 동작·브라우저별 권한을 구분하세요. 화면에는 복사할 원문을 남겨 두면 자동 복사가 거부돼도 사용자가 작업을 이어갈 수 있습니다.
2026년 9월 28일 확인한 MDN을 바탕으로, 일반 웹페이지의 텍스트 쓰기 버튼을 다룹니다. 아래 예제는 화면에 준비된 문구를 복사하는 구현 예시입니다. 사용자의 실제 클립보드를 읽거나 브라우저별 성공률을 측정한 결과는 아닙니다.
성공 안내가 기다려야 하는 것은 Promise입니다
navigator.clipboard.writeText(text)는 시스템 클립보드에 문자열을 쓰는 비동기 메서드입니다. 반환된 Promise는 쓰기가 끝나면 성공하고, 허용되지 않으면NotAllowedError등으로 실패할 수 있습니다. 성공 안내는 이 Promise가 이행된 뒤에 둡니다. writeText의 반환값과 오류다음 코드는 완료 순서를 보장하지 않습니다.
navigator.clipboard .writeText(text); status.textContent = "복사했습니다.";상태 문구를 바꾸는 코드는 쓰기 결과를 기다리지 않습니다. 권한 문제로 나중에 Promise가 거부돼도 사용자는 이미 성공 문구를 보게 됩니다.
await와 오류 처리를 넣으면 화면 상태를 요청 결과에 맞출 수 있습니다.여기서 성공을 확인하려고
readText()까지 호출할 필요는 없습니다. 읽기는 별도의 권한·사용자 동작 조건이 있는 기능입니다. 복사 버튼을 구현하면서 사용자가 다른 앱에서 복사한 자료까지 읽는 흐름을 만들 이유는 없습니다.HTTPS, 클릭, 권한은 서로 다른 조건입니다
비동기 Clipboard API는 보안 컨텍스트에서 제공됩니다.
window.isSecureContext와navigator.clipboard의 존재 여부는 첫 확인 지점입니다. 일반 HTTP 페이지에서 API 자체가 없으면 Promise 오류 처리까지 도달하지 못할 수 있습니다. Clipboard API 보안 조건API가 존재해도 호출이 반드시 허용되지는 않습니다. MDN은 Chromium의 쓰기에
clipboard-write권한 또는 일시적 사용자 활성화가 관련되고, Firefox·Safari에서는 일시적 활성화가 필요하다고 설명합니다. Firefox·Safari는 같은 이름의 Permissions API 권한 조회를 지원하지 않는 차이도 있습니다. 모든 브라우저에서 먼저 권한 조회를 해야 한다고 가정하면 복사 기능보다 권한 코드가 먼저 실패할 수 있습니다.일시적 활성화는 사용자가 최근에 클릭하거나 키보드로 조작했다는 제한된 신호입니다. 한 번 버튼을 눌렀다고 그 페이지의 이후 모든 복사가 허가되는 것은 아닙니다. 시간이 지나거나 다른 API에서 활성화를 소비하면 상태가 달라질 수 있습니다. 사용자 활성화의 수명
가령 버튼 클릭 → 서버에 공유 문구 요청 → 응답을 기다림 → 클립보드 쓰기 순서라면, 마지막 단계까지 활성화가 유지되지 않을 수 있습니다. 그렇다고
await가 한 번만 있어도 반드시 실패한다는 규칙은 아닙니다. 중요한 것은 쓰기를 요청한 시점의 조건입니다. 문구 생성이 오래 걸린다면 결과를 먼저 보여 주고, 별도 복사 버튼에서 바로 쓰는 방식이 이해하기 쉽습니다.문구를 미리 준비한 버튼의 최소 구현
다음은 HTML 요소가 준비된 뒤 한 번 연결하는 예제입니다. 복사할 값은 클릭할 때 textarea에서 읽습니다. 화면의 원문과 복사 대상이 같은 요소를 사용하도록 만든 것입니다.
<textarea id="share-text" readonly >회의 시간: 오후 3시</textarea> <button id="copy-button" type="button">문구 복사</button> <p id="copy-status" role="status" aria-live="polite"></p> <script> const field = document .querySelector("#share-text"); const button = document .querySelector("#copy-button"); const status = document .querySelector("#copy-status"); const copy = async () => { const text = field.value; button.disabled = true; status.textContent = "복사 중입니다."; try { if ( !window.isSecureContext || !navigator.clipboard ?.writeText ) { throw new Error( "Clipboard API unavailable" ); } await navigator.clipboard .writeText(text); status.textContent = "복사했습니다."; } catch { status.textContent = "자동 복사가 안 됩니다. " + "선택된 문구를 " + "직접 복사해 주세요."; field.focus(); field.select(); } finally { button.disabled = false; } }; button.addEventListener( "click", copy ); </script>성공 경로에서는
await뒤에만 완료 문구가 나옵니다. 실패 경로에서는 선택 가능한 원문으로 초점을 옮깁니다. 선택만으로 복사가 끝나는 것은 아니므로 직접 복사하라는 안내를 남겼습니다. 상태 영역에는 보조 기술이 변경을 알 수 있는 속성도 붙였습니다.버튼을 잠시 비활성화한 이유는 클릭이 겹쳐 이전 요청의 성공 문구가 새 요청의 실패를 덮는 상황을 줄이기 위해서입니다. 화면을 다시 만드는 앱에서는 이벤트 중복 연결과 해제도 컴포넌트 수명에 맞춰 처리해야 합니다.
iframe 안에서만 안 되면 바깥 문서도 봅니다
같은 페이지가 독립적으로 열릴 때는 되는데 다른 사이트 안에 삽입하면 실패할 수 있습니다. Chromium에서는 iframe의 Clipboard API 접근에 Permissions Policy도 관련됩니다. 포함하는 문서가 허용하는 정책과 iframe의
allow설정을 함께 확인해야 합니다. MDN의 브라우저별 차이자식 페이지의 JavaScript만 반복해서 고쳐서는 상위 문서의 제한이 풀리지 않습니다. 반대로 모든 iframe에 광범위한 권한을 주는 것도 복사 버튼 하나를 위한 적절한 수정이라고 단정할 수 없습니다. 실제로 이 기능이 필요한 출처와 동작을 정해 해당 범위를 확인합니다.
이 단계에서 기록할 것은 최상위 페이지인지 iframe인지, 브라우저와 버전, 보안 컨텍스트 여부, 쓰기 요청에서 발생한 오류 이름입니다. 복사한 문구 전체나 기존 클립보드를 로그에 모을 필요는 없습니다. 권한 문제를 좁히는 정보와 사용자의 자료는 구분할 수 있습니다.
붙여넣은 문자열까지 맞아야 버튼이 완성됩니다
Promise가 성공한 것은 함수에 넘긴 문자열을 썼다는 뜻입니다. 화면은 오후 4시로 바뀌었는데 핸들러가 예전 오후 3시를 기억한다면 API는 성공하고 기능은 틀릴 수 있습니다. 클릭 직전에 원문이 바뀌는 경우를 검수에 넣어야 하는 이유입니다.
비민감 문구로 직접 클릭, 키보드 조작, 권한 거부, API가 없는 환경을 확인합니다. 한글과 줄바꿈이 있는 문구를 붙여넣어 원문과 비교하고, 실패 때 성공 안내가 남지 않는지도 봅니다. 서버에서 문구를 생성하는 기능이라면 생성 직후 복사하는 경로와 나중에 다시 누르는 경로를 나눠 확인하면 됩니다.
클립보드는 이후 다른 앱이 바꿀 수 있습니다. 따라서 완료 문구는 그 요청의 쓰기 완료를 뜻해야 하며, 나중에도 같은 내용이 남는다는 약속을 할 수는 없습니다. 자동 복사가 안 되는 환경에서는 선택 가능한 원문과 정확한 실패 안내가 사용자의 다음 행동을 이어 줍니다.
728x90반응형'Programming' 카테고리의 다른 글
다른 탭에 변경을 알렸는데 새로 연 탭은 모르는 이유 (0) 2026.10.04 탭 두 개가 같은 작업을 동시에 할 때: Web Locks의 범위 (0) 2026.10.04 자동재생을 켰는데 비디오가 멈춰 있는 이유 (0) 2026.10.04 같은 SVG인데 img로 넣을 때와 직접 열 때가 다른 이유 (0) 2026.10.02 이미지는 보이는데 캔버스 PNG 저장은 왜 실패할까 (0) 2026.10.02