FrontEnd

[JavaScript] 텍스트 복사 붙여넣기 기능 구현하기

머털박사 2022. 8. 9. 10:54

들어가며

이 글은 텍스트 복사 붙여넣기 기능 구현을 위해 execCommand(), execCommand()를 사용하지 말아야하는 이유, Clipboard API사용법에 대해 다룹니다.

👎 기능 구현 방법1 document.execCommand()

문서의 편집 가능한 영역을 변경할 수 있습니다. 대부분의 명령어는 문서의 선택 영역에 영향(볼드, 이탤릭 등)을 미치고 나머지는 새 요소를 추가(링크 추가)하거나 전체 줄에 영향(들여쓰기)을 미칩니다.

Document.execCommand() - Web API | MDN

텍스트 복사 기능을 검색하면 가장 먼저뜨는 메서드다. 이 메서드를 사용하면 현재 활성화된(seletec) 요소의 영향을 미친다. 텍스트 배경색, 폰트 사이즈, 들여쓰기, 여백 바꿔주고 복사, 붙여넣기하는 명령어까지 포함되어 있다.

// <textarea>
const tbox = document.querySelector("#tbox");
// btn
const btn_copy = document.querySelector("#btn_copy");

btn_copy.onclick = () => {
  tbox.select();
  document.execCommand("copy");
};

만약 텍스트를 복사하고 싶다면 위와 같이 execCommand(”copy”) 명령어를 사용하면 된다. 텍스트를 붙여넣고 싶다면 execCommand(”paste”) 를 사용하면 된다.

document.execCommand()는 더 이상 사용하지 않나요?

이 메서드는 MDN문서에서 Deprecated(더 이상 사용하지 않음)으로 나온다. 기능을 지원하지만 호환성 목적으로 지원할 뿐 새로운 사이트를 만들 경우 사용하지 않기를 권장한다. 물론 기존의 코드도 업데이트 하는 것이 좋다.

권장되지 않는 이유는 이 메서드를 통해 만든 엘리먼트는 브라우저마다 일관성없이 생성되기 때문이다.

// 누르면 선택한 텍스트가 "bold"로 변하는 버튼
<input type="button" value="B" onclick="document.execCommand('bold')" />

execCommand()는 보통 블로그 글 같은 웹 포스트 작성 프로그램에 사용됐던 메서드다. 여러가지 명령어 중 선택한 텍스트에 스타일을 부여하는 것이 있다. 위의 코드또한 텍스트를 선택하고 누르면 텍스트를 두껍게 만들어주는 것이다.

만약 해당 버튼을 눌렀을 떄 텍스트를 볼드로 바꾸는 방식은 3가지다.

  1. <span>태그를 넣고 인라인 스타일로 font-weight: bold 적용
  2. <b> 태그 삽입
  3. <strong> 태그 삽입

1,2번은 별로고 3번이 가장 나은 방식이다. execCommand() 메서드를 사용할 경우 1번 아니면 2번 방식으로 스타일이 생성된다.

1번은 사이트 고유의 CSS 스타일을 망가뜨린다. 또 시맨틱하지 않다는 이유로 단지 스타일만 추가하기 위해서 <span> 태그를 사용하는 것은 권장되지 않는다.

2번은 웹 표준, 웹 접근성이 떨어진다. 시각 장애인이나 유사한 사람이 사용하는 스크린 리더에서 읽히지 않는 스타일을 생성한다. 시멘틱한 태그를 사용하지 않는 것이다.

태그명 스타일 의미 스크린리더
  텍스트가 굵어짐 안에 적힌 텍스트가 중요하다 읽힘
  텍스트가 굵어짐 X 안 읽힘

<strong>, <b> 모두 똑같이 텍스트가 굵어지는 스타일을 제공한다. 차이점은 <strong> 태그 안에 든 텍스트가 중요하다는 의미까지 포함되어있다. 이건 “bold” 메서드만의 문제가 아니다. <i>, <u> 같은 지금은 사용이 권장되지 않는 태그로 요소를 생성한다.

이러한 이유로 최신 웹브라우저에 적합하지 않은 API다. 근데 문제는 execCommand()에 대한 완전한 대체재가 존재하지 않는다. 하지만 다행스럽게도 구현하려고 했던 텍스트 복사기능은 지원하는 메서드가 있었다.

👍기능 구현 방법2 Clipboard API 이용하기

Clipboard API는 클립보드 명령(잘라내기, 복사, 붙여넣기)에 응답하거나 시스템 클립보드에 비동기적으로 접근하고 쓸 수 있는 기능을 제공합니다.

Clipboard API - Web API | MDN

execCommand()를 대체하기 위해 나온 API로 전역으로 선언된 Navigator 인터페이스 안에서 가져올 수 있다. 메서드는 총 네가지가 존재한다.

  • read()
  • readText()
  • write()
  • writeText()

readText()writeText()는 텍스트만 복사, 붙여넣기한다. read(), write() 는 이미지를 복사할 때 사용한다.

Clipboard API를 브라우저에서 지원하나요?

2022년 7월 6월 현재 실험적인 기술로 브라우저에서 완전히 지원하지 않는다. 크롬과 엣지에서는 대부분 정상 작동한다. 하지만 파이어 폭스 같은 경우는 사용하기 위해서는 사용자가 권한을 따로 설정해줘야한다.

💡 파이어폭스에서 ClipboradAPI를 사용하기 위해 설정해야하는 부분

  • read()
    dom.events.asyncClipboard.read를 True로 설정하기
    → 브라우저 확장 프로그램에서 “clipboardRead” 권한 허용
  • readText()
    → 브라우저 확장 프로그램에서 “clipboardRead” 권한을 사용해야한다.
  • write()
    dom.events.asyncClipboard.clipboardItem를 True로 설정하기
    → 브라우저 확장 프로그램에서 “clipboardWrite” 권한을 사용해야한다.
  • writeText()
    → 브라우저 확장 프로그램에서 “clipboardWrite” 권한을 사용해야한다.

텍스트 붙여넣기 Clipboard.readText()

navigator.clipboard.readText().then(
  clipText => document.getElementById("outbox").innerText = clipText);

매개변수는 없고, 반환 값은 Promise 형태로 돌아오며 문자열을 반환한다. 클립보드의 텍스트가 비어있는 경우 빈 문자열을 반환한다. 클립보드 안에 든 내용물이 텍스트가 아닌 경우에는 반환하지 않는다. 텍스트가 아닌 경우에는 read() 메서드를 사용하면 된다.

텍스트 복사하기 Clipboard.writeText()

navigator.clipboard.writeText("<empty clipboard>").then(function() {
  /* clipboard successfully set */
}, function() {
  /* clipboard write failed */
});

위는 예시코드이다. 클립보드에 붙여넣을 매개변수가 필요하고, 반환값은 Promise형태로 넘어온다. then에서 첫번째 콜백함수 인자는 성공시 실행되고, 두 번째 콜백함수 인자는 실패시 실행된다.

실제로 구현 예시

<body>
    <textarea id="tbox"></textarea>
    <button>전체복사</button>
<body/>

텍스트를 입력할 <textarea>와 저장하기 위한 저장용 <button>을 생성해준다.

<body>
    <textarea id="tbox"></textarea>
    <button>전체복사</button>
<body/>
<script>

const tbox = document.getElementById("tbox");
const btn_copy = document.getElementById("btn_copy");

btn_copy.addEventListener("click", () => {
});
<script/>

스크립트로 UI 선언하고 버튼 클릭시 함수가 실행되는 코드를 짠다.

<body>
    <textarea id="tbox"></textarea>
    <button>전체복사</button>
<body/>
<script>

const tbox = document.getElementById("tbox");
const btn_copy = document.getElementById("btn_copy");

btn_copy.addEventListener("click", () => {
    const text = tbox.value;
    navigator.clipboard.writeText(text).then(
        () => {
            tbox.select();
        },
        () => {
            console.log("복사 실패");
        }
    );
});
<script/>

textarea에 값을 변수로 선언하고 clipboard API를 호출한다. 사용자가 복사 성공 여부를 알아차기리 위해서 성공하면 textarea의 모든 텍스트를 선택한다. 간단한 글자수를 셀 때는 딱히 실패할 일 없으니 콘솔창에 로그만 띄운다.


참고 출처

execCommand() is now obsolete, what's the alternative?