기존에 서비스를 사용하는 유저는 60-70명인데, 기존엔 사용자가 답변 가이드 이미지를 따로 저장해서 직접 버튼을 눌러서 첨부해야했기 때문에 번거로웠음
그래서 이미지 복사 후 붙여넣기 기능을 제공하여 유저에게 편의성을 제공하고자 함
해당 기능을 구현하기 위해 clipboardData.getData()
와 Clipboard API(navigator.clipboard)
을 활용하는 방법을 활용해보았다.
핸들러 함수 관련하여 추가된 로직은 아래와 같다.
붙여넣기 이벤트의 클립보드 api는 사용자가 붙여넣기 동작을 할때 발생한다.
clipboardData
속성에서 getData()를 호출하여 클립보드 내용에 액세스 한다.files
배열 0번째 인덱스에서 현재 붙여넣기된 DataTransfer 객체의 값을 변수에 할당한다.// clipboardData.getData()를 사용한 방식
const handlePasteInput = (e: ClipboardEvent<HTMLTextAreaElement>) => {
...
const clipboardFile = e.clipboardData.files[0] || null;
if (clipboardFile) {
setChatState(prev => ({
...prev,
files: prev.files ? [...prev.files, clipboardFile] : [clipboardFile],
}));
}
...
};
// Clipboard API(navigator.clipboard)를 사용한 방식
const readClipboardFiles = async () => {
try {
// 클립보드에서 데이터 읽기
const clipboardItems = await navigator.clipboard.read();
for (const item of clipboardItems) {
let result = null;
// 각 ClipboardItem의 MIME 타입 확인
for (const type of item.types) {
// Blob 또는 File로 변환
const blob = await item.getType(type);
// 파일로 처리하기 위해 File 객체로 변환 가능
if (blob.type.startsWith("image/")) {
result = new File([blob], blob.type, {
type: blob.type,
lastModified: Date.now(), // 현재 시간 설정
});
}
}
return result;
}
} catch (err) {
console.error("클립보드에서 파일을 읽는 데 실패했습니다:", err);
}
};
const handlePasteInput = async (e: ClipboardEvent<HTMLTextAreaElement>) => {
...
const clipboardFile = await readClipboardFiles();
if (clipboardFile) {
setChatState(prev => ({
...prev,
files: prev.files ? [...prev.files, clipboardFile] : [clipboardFile],
}));
}
...
};
두 가지 방식의 차이점이다. 아래는 Clipboard API를 사용하는 이점이다.
비동기 방식 (Promise 기반)
보안 강화를 위한 HTTPS 제한
직접적인 클립보드 제어