Skip to main content

Command Palette

Search for a command to run...

Clipboard API가 왜 안될까...

Published
2 min readView as Markdown
Clipboard API가 왜 안될까...

오늘도 평소와 같이 회사에 출근해서 진행 중인 프로젝트 UI 테스트를 진행하였다. 뭐 거창한 건 아니고 기능 하나씩 구현하면서 버그가 있나 확인하는 작업이라고 할 수 있다.

화면 정의서와 다르게 구현되거나 기능이 빠진 부분에 대한 코드 훑어보고 후딱 처리하며 문제를 해결해 나가고 있는데, 어떤 기능 하나가 동작을 안하는데 도통 이유를 알 수 없었다.

오늘은 이 문제가 일어난 원인과 해결 방법에 대해 공유하려고 한다.

💣 클립보드 복사가 안된다

회사 코드를 공개할 수 없어서 바닐라 자바스크립트 코드를 예시로 들어보자.

<body>
  <button type="button">Click Here!</button>
  <script>
    const button = document.querySelector('button')

    const copyText = () => {
    navigator.clipboard.writeText(button.innerText)
    }

    button.addEventListener('click', copyText)
  </script>
</body>

button을 클릭하면 'Click Here!'라는 텍스트가 클립보드에 복사하는 기능을 구현하였다. 개발 작업 환경인 로컬에서는 해당 클립보드 기능이 제대로 동작하는 것을 확인할 수 있다.

이러한 기능은 자바스크립트에서 제공하는 Clipboard API를 통하여 사용되어 웹 페이지의 텍스트나 이미지 같은 데이터를 클립보드에 복사 및 붙여넣을 수 있도록 한다.

그러나 테스트용 배포를 하고 http 환경에서 해당 기능을 시도해보면 클립보드 복사가 되지 않는다. 원인이 무엇일까?

🧶 Clipboard API가 제공이 안되네...

안타깝게도 Clipboard API는 브라우저 보안 프로토콜로 인하여 Safari 13.1 버전부터 https 환경에서만 지원한다고 한다.

일반적으로 보안 상의 이유로 로컬 파일 시스템에 접근하거나 클립보드 같은 작업을 수행할 때 동일 출처 정책을 따른다. 이는 웹 페이지가 자신의 출처에서만 리소스에 접근하도록 하는 것이다. 따라서 http에서는 보안 정책에 위반되어 브라우저에서 차단되었을 가능성이 높다.

보안을 강화하기 위해서 https를 권장한다. https를 통한 통신은 데이터의 암호화를 제공하고, 브라우저는 https 환경에서 동작하는 페이지에 대해 더 높은 신뢰를 가진다.

그럼 로컬 환경에서는 왜 동작하는 것일까? 정확한 이유는 잘 모르겠지만 추측으로, 로컬에서는 보안 정책이 상대적으로 덜 엄격하거나 특정한 보안 규칙이 적용되지 않을 수 있다.

💊 그래도 해결책은 있다

Clipboard API 이전에 execCommand 메서드가 존재하였다.

안타깝게도 이 메서드는 더 이상 지원되지 않아 점점 도태되어 사라질 것이다.

하지만 이런 썩은 밤이라도 주워 먹어야 하는 불쌍한 다람쥐 신세.. 🌰🐿

<body>
    <button type="button">Click Here!</button>
    <script>
      const button = document.querySelector('button')

      const copyText = () => {
        if (navigator.clipboard) {
          navigator.clipboard.writeText(button.innerText)
        } else {
          const textArea = document.createElement('textarea')
          textArea.value = button.innerText
          document.body.appendChild(textArea)
          textArea.select()
          document.execCommand('copy')
          document.body.removeChild(textArea)
        }
      }

      button.addEventListener('click', copyText)
    </script>
  </body>

navigator.clipboard가 존재하는, 즉 https에서는 기존과 동일하게 동작한다. 그렇지 않은 http에서는 다소 코드가 길고 복잡한 과정을 거치게 된다.

  1. 값을 저장할 textarea라는 요소를 하나 만들어주고

  2. 복사할 값을 해당 요소의 value 속성에 할당한다.

  3. 해당 요소를 html 문서에 더하고 선택한다. 이는 클립보드에 복사할 내용을 선택하는 것과 같은 기능을 한다.

  4. execCommand 메서드를 사용해 클립보드에 복사 명령을 한다.

  5. 더이상 필요 없어진 요소를 문서에서 삭제한다.

마치며

이런 썩은 밤 덕분에 야무지게 문제를 해결할 수 있었다. 그냥 회사에서 http 환경을 사용하지 않는다면.

More from this blog

시맨틱하게 다이얼로그 만들기

웹에서 양식을 제출하기 위한 다이얼로그를 작성할 때 시맨틱 태그를 무시하고 div 태그를 활용해 css로 스타일링을 하는 경우가 많다. 이렇게 작성할 경우, 동작에는 전혀 무리가 없지만 하지 않아도 될 스타일링 작업을 하는 데 시간을 쏟을 수 있고 웹접근성 측면에도 좋지 않다. 웹에서 다이얼로그는 모달, 대화상자, 알림창, 검사기와 같은 상호작용 가능한 컴포넌트를 말한다. HTML에서는 dialog 라는 태그를 사용하면 핵심적인 다이얼로그의 기...

Jan 13, 20262 min read

[JavaScript] 이미지 사이즈 압축해서 용량 줄이기

이미지를 받아서 저장하는 기능을 구현하고 며칠이 지난 후 한 가지 이슈를 발견하였다. 바로 이미지 업로드가 되지 않는 아주 치명적인 문제였다! 분명 테스트도 수 없이 진행하고 배포한 후에도 잘만 동작했는데 갑자기 이런 일이 왜 벌어진걸까? 문제 해결의 원인을 찾기 위해 다양한 방법을 시도하였다: 갤럭시의 갤러리에 있는 이미지 업로드 갤럭시의 카메라로 직접 찍어서 업로드 아이폰의 갤러리에 있는 이미지 업로드 아이폰의 카메라로 직접 찍어서 ...

Nov 16, 20242 min read
[JavaScript] 이미지 사이즈 압축해서 용량 줄이기

[JavaScript] 이미지 수정 시 브라우저 캐싱 방지하기

웹 개발을 하면서 한 번쯤 겪어볼 수 있는 이슈가 있다. A 사용자가 이미지를 업로드하면 B 사용자가 그 이미지를 확인하고, 재업로드를 요청하는 플로우다. A 사용자가 새로운 이미지를 업로드 했는데도 B 사용자는 여전히 처음 이미지를 볼 수 있다. 이 문제는 서버 측에서 "이미지 경로는 그대로 유지하고 이미지를 덮어씌운다"는 구조와 관련이 있다. 브라우저는 URL이 동일하면 캐싱된 이미지를 가져와 네트워크 요청을 줄인다. 따라서 새로운 이미지가...

Oct 3, 20242 min read
[JavaScript] 이미지 수정 시 브라우저 캐싱 방지하기

[React] 렌더링 관점에서 보는 react-hook-form (feat. useRef)

평소 한땀한땀 기능을 만들어나가는 걸 좋아해서 유명한 라이브러리들을 사용해보지 않았는데, 회사에서 프로젝트를 진행하며 다양한 라이브러리를 사용해보았다. 그 중 React-Hook-Form을 사용하며 평소에 리액트로 폼을 작성하며 겪은 불편한 점을 많이 해소했다. 코드 길이, 예외 처리, 렌더링 등 다양한 관점에서 개선할 수 있게 되었다. 오늘은 다양한 폼 상태 관리 방법을 비교하여 React-Hook-Form의 장점을 알아보자. useState...

Sep 5, 20243 min read
[React] 렌더링 관점에서 보는 react-hook-form (feat. useRef)

Untitled Publication

53 posts