Tips & Tricks

API Usage Guide: Claude Code 활용 가이드

api usage guide: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.

クリップボードAPIで사용자体験を向上

ワン클릭でコードをコピーしたり、リッチテキストをペーストしたり、クリップボードAPIはWeb앱の使い勝手を大きく向上させます。Claude Code를 활용하면 브라우저互換性や보안を考慮した구현を빠르게구축할 수 있습니다。

コードブロックのコピー버튼

> コードブロックにコピー버튼를 추가해줘。
> 클릭後に「コピー済み」フィードバックを표시して。
// components/CopyButton.tsx
import { useState, useCallback } from 'react';

interface CopyButtonProps {
  text: string;
}

export function CopyButton({ text }: CopyButtonProps) {
  const [copied, setCopied] = useState(false);

  const handleCopy = useCallback(async () => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (err) {
      // フォールバック
      fallbackCopy(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  }, [text]);

  return (
    <button
      onClick={handleCopy}
      className="absolute right-2 top-2 rounded bg-gray-700 px-2 py-1 text-xs text-white
        transition-colors hover:bg-gray-600"
      aria-label={copied ? 'コピー済み' : 'コードをコピー'}
    >
      {copied ? '✓ コピー済み' : 'コピー'}
    </button>
  );
}

function fallbackCopy(text: string): void {
  const textarea = document.createElement('textarea');
  textarea.value = text;
  textarea.style.position = 'fixed';
  textarea.style.opacity = '0';
  document.body.appendChild(textarea);
  textarea.select();
  document.execCommand('copy');
  document.body.removeChild(textarea);
}

リッチテキストのコピー

// utils/clipboard.ts
export async function copyRichText(html: string, plainText: string): Promise<void> {
  if (!navigator.clipboard?.write) {
    fallbackCopy(plainText);
    return;
  }

  const htmlBlob = new Blob([html], { type: 'text/html' });
  const textBlob = new Blob([plainText], { type: 'text/plain' });

  const item = new ClipboardItem({
    'text/html': htmlBlob,
    'text/plain': textBlob,
  });

  await navigator.clipboard.write([item]);
}

// Usage example:테이블데이터のコピー
async function copyTableAsHtml(data: string[][]) {
  const html = `<table>${data.map(row =>
    `<tr>${row.map(cell => `<td>${cell}</td>`).join('')}</tr>`
  ).join('')}</table>`;
  
  const text = data.map(row => row.join('\t')).join('\n');
  await copyRichText(html, text);
}

クリップボードからの読み取り

// ペースト時の이미지処理
async function handlePaste(e: ClipboardEvent): Promise<void> {
  const items = e.clipboardData?.items;
  if (!items) return;

  for (const item of items) {
    if (item.type.startsWith('image/')) {
      e.preventDefault();
      const blob = item.getAsFile();
      if (blob) {
        const url = URL.createObjectURL(blob);
        insertImage(url);
      }
    }
  }
}

// Permissions APIで権限チェック
async function checkClipboardPermission(): Promise<boolean> {
  try {
    const result = await navigator.permissions.query({
      name: 'clipboard-read' as PermissionName,
    });
    return result.state === 'granted' || result.state === 'prompt';
  } catch {
    return false;
  }
}

共有用URLのコピー機能

function ShareUrl({ url, title }: { url: string; title: string }) {
  const [copied, setCopied] = useState(false);

  const handleCopy = async () => {
    await navigator.clipboard.writeText(url);
    setCopied(true);
    setTimeout(() => setCopied(false), 3000);
  };

  return (
    <div className="flex items-center gap-2 rounded-lg border p-3">
      <input
        type="text"
        value={url}
        readOnly
        className="flex-1 bg-transparent text-sm outline-none"
      />
      <button
        onClick={handleCopy}
        className="rounded bg-blue-600 px-3 py-1 text-sm text-white hover:bg-blue-700"
      >
        {copied ? 'コピー済み!' : 'URLをコピー'}
      </button>
    </div>
  );
}

보안の考慮事項

// サニタイズ処理付きペースト
function sanitizePastedContent(html: string): string {
  const div = document.createElement('div');
  div.innerHTML = html;
  
  // スクリプトタグを除去
  div.querySelectorAll('script, iframe, object, embed').forEach(el => el.remove());
  
  // 이벤트핸들러属性を除去
  div.querySelectorAll('*').forEach(el => {
    Array.from(el.attributes)
      .filter(attr => attr.name.startsWith('on'))
      .forEach(attr => el.removeAttribute(attr.name));
  });
  
  return div.innerHTML;
}

정리

クリップボードAPIの활용で、コードブロックのコピーや共有機能などのUXを大幅に改善할 수 있습니다。Claude Code를 활용하면 フォールバック処理や보안対策まで含めた堅牢な구현が가능합니다。Web Share APIと組み合わせれば、더 나아가柔軟な共有機能を提供할 수 있습니다。성능최적화の観点も忘れずに考慮합시다。詳しい仕様はMDN Web Docs를 참고하세요.

#Claude Code #Clipboard API #JavaScript #UX #Web API