내가 직접 솔루션을 만들게 만든 클립보드 문제
Source: Dev.to
클립보드를 또 잃어버렸어요. 복잡한 SQL 쿼리를 복사하고 다른 탭으로 전환한 뒤 다른 것을 복사했더니 그 쿼리가 사라졌습니다. 기억을 되살려 다시 작성해야 했죠.
이런 일이 계속되었습니다. 원격 근무자로서 노트북과 데스크톱을 계속 오가며 작업했는데, 한 장치에서 무언가를 복사하고 다른 장치로 전환하면 사라졌습니다. 몇 가지 클립보드 관리자를 시도했지만 내 작업 흐름에 맞지 않았습니다.
그래서 직접 만들었습니다. 아래에는 제가 배운 점, 마주친 도전 과제, 그리고 다르게 할 점을 정리했습니다.
고충
- 기기 간 손실 – 노트북에서 코드 스니펫을 복사하고 데스크톱으로 전환하면 사라짐.
- 우연한 덮어쓰기 – 이메일 템플릿을 복사하고 탭을 바꾼 뒤 다른 것을 복사하면 템플릿을 잃음.
- 히스토리 스크롤 – 매일 사용하는 항목을 찾기 위해 50개의 클립보드 항목을 스크롤해야 함.
시도해 본 도구
| 도구 | 부족했던 이유 |
|---|---|
| 기본 OS 클립보드 관리자 | 기기 간 동기화가 없음. |
| 클라우드 클립보드 도구 | 너무 느리거나 번거롭고 단계가 많음. |
| 브라우저 확장 프로그램 | 모든 것을 저장하지만 실제로 사용하는 것을 우선순위에 두지 않음. |
대부분의 확장 프로그램은 히스토리만 저장했습니다. 매일 붙여넣는 이메일 서명을 찾기 위해 수십 개의 항목을 스크롤해야 했습니다. 목적에 맞지 않았습니다.
나의 솔루션: 맞춤형 브라우저 확장 프로그램
특징
- Chrome과 Edge 브라우저 간에 클립보드 기록을 동기화합니다.
- 내가 가장 많이 붙여넣는 내용을 학습하고 해당 항목을 우선순위에 둡니다.
- 빠른 접근을 위한 오른쪽 클릭 컨텍스트 메뉴를 제공합니다.
- Google Docs, Reddit, Notion 등 복잡한 사이트에서도 작동합니다.
핵심 차이점 – 클릭한 것만이 아니라 실제로 붙여넣은 것을 추적합니다. 자주 붙여넣는 항목은 자동으로 상단으로 이동합니다.
Source: …
기술 심층 분석
Clipboard API의 특이점
// This works in some contexts, not others
navigator.clipboard.readText().then(text => {
// But what if the page doesn't have focus?
// What if it's a content script?
});
문제점
- HTTPS 또는
localhost가 필요합니다. - 콘텐츠 스크립트가 클립보드에 직접 접근하지 못할 때가 있습니다.
- 권한 처리 방식이 상황에 따라 다릅니다.
해결책 – 콘텐츠 스크립트와 백그라운드 서비스 워커 간에 메시지 전달을 사용하고, 대체 방안을 마련합니다.
서비스 워커 수명 주기
// This state gets lost when the service worker dies
let clipboardHistory = [];
// Had to persist everything
chrome.storage.local.set({ clipboardHistory });
도전 과제
- 서비스 워커는 언제든지 종료될 수 있습니다.
- 콘텐츠‑스크립트 주입 시점 문제가 발생합니다.
- CSP 제한으로 일부 접근 방식이 차단됩니다.
해결책 – 상태를 chrome.storage.local에 저장하고, 시작 시 재초기화를 처리합니다.
복잡한 사이트에 붙여넣기
| 방법 | 설명 | 신뢰도 |
|---|---|---|
| Modern | element.dispatchEvent(new ClipboardEvent('paste')) | 일부 상황에서 동작하지만, 모든 상황에서는 아닙니다. |
| Deprecated | document.execCommand('paste') | 때때로 유일한 옵션이 됩니다. |
| Direct DOM | element.textContent = clipboardText | 간단한 사이트에서 동작합니다. |
통합 접근 방식
async function pasteText(element, text) {
// Try modern approach first
try {
element.focus();
await navigator.clipboard.writeText(text);
element.dispatchEvent(new ClipboardEvent('paste'));
return true;
} catch (e) {
// Fallback to execCommand
try {
element.focus();
document.execCommand('insertText', false, text);
return true;
} catch (e2) {
// Last resort: direct manipulation
element.textContent = text;
return true;
}
}
}
실시간 동기화 vs. 폴링
폴링 (피하고 싶었던 방식)
setInterval(async () => {
const latest = await fetchLatestClipboard();
// Check for changes...
}, 5000); // Too slow, or too resource‑intensive
해결책: 실시간 구독 (Supabase 예시)
const subscription = supabase
.channel('clipboard-changes')
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'clipboard_items'
}, payload => {
// Handle new item instantly
updateLocalClipboard(payload.new);
})
.subscribe();
도전 과제
- 연결 끊김을 처리해야 합니다.
- 여러 기기에서 동일한 항목이 업데이트될 때 충돌을 해결해야 합니다.
- 구독 수명 주기를 관리해야 합니다.
브라우저 간 호환성
| 브라우저 | API 네임스페이스 |
|---|---|
| Chrome | chrome.* |
| Firefox | browser.* |
| Edge | chrome.* (조금 다르게 동작) |
추상화 레이어
const browserAPI = {
storage: {
local: {
get: key => {
if (typeof chrome !== 'undefined' && chrome.storage) {
return new Promise(resolve => {
chrome.storage.local.get(key, resolve);
});
} else if (typeof browser !== 'undefined') {
return browser.storage.local.get(key);
}
},
set: items => {
if (typeof chrome !== 'undefined' && chrome.storage) {
return new Promise(resolve => {
chrome.storage.local.set(items, resolve);
});
} else if (typeof browser !== 'undefined') {
return browser.storage.local.set(items);
}
},
// ...similar for remove, clear, etc.
}
}
};
배운 교훈
- 모든 것을 지속하세요 – 서비스 워커가 언제든 죽을 수 있다고 가정하세요.
- 단순하게 시작하세요 – 로컬 전용 저장소로 MVP를 만들고, 이후 동기화를 추가하세요.
- 실제 사용량을 추적하세요 – 클릭만이 아니라 붙여넣기 이벤트도 모니터링하세요.
- 모든 대상 브라우저에서 테스트하세요 – Chrome, Firefox, Edge는 각각 다르게 동작합니다.
- 충돌 해결을 일찍 계획하세요 – 나중에 큰 고통 포인트가 됩니다.
- 시작부터 견고한 오류 처리를 추가하세요 – 재시도, 대체 로직 등을 포함합니다.
- 테스트 인프라를 일찍 구축하세요 – 단위 + 통합 테스트가 시간을 절약합니다.
- 사용자 피드백을 빨리 받으세요 – 너무 오래 고립된 상태로 개발하는 것을 피하세요.
아직 풀고 있는 열린 질문들
- 클립보드 권한 – 브라우저 간 확장 프로그램에서 이를 어떻게 신뢰성 있게 처리하나요?
- 붙여넣기 호환성 – 복잡한 사이트(Google Docs, Notion, CodePen 등)에서 더 나은 접근법은?
- 실시간 동기화 아키텍처 – 최소 지연 및 충돌로 클립보드 데이터를 동기화하는 가장 견고한 방법은?
- Manifest V3 서비스 워커 수명 주기 – 상태를 지속하고 재시작을 처리하기 위한 모범 사례는?
이러한 문제들을 해결한 경험이 있다면, 여러분의 생각을 듣고 싶습니다!
모범 사례?
브라우저 간 확장 프로그램을 효율적으로 테스트하는 방법은?
비슷한 것을 만들었거나 아이디어가 있다면, 알려 주세요.
몇 달 동안 사용해 본 결과, 잘 작동하고 있습니다. 클립보드 내용을 거의 잃지 않으며, 자주 사용하는 항목이 빠르게 나타납니다. 완벽하진 않지만 제 워크플로에 맞습니다.
사용해 보고 싶다면 Chrome과 Edge에서 사용할 수 있습니다. 더 중요한 것은, 여러분이:
- 비슷한 문제를 어떻게 해결했는지
- 브라우저 확장 프로그램에서 겪은 도전 과제는 무엇인지
- 어떤 기능이 이 도구를 실제로 유용하게 만들지
알려 주시면 좋겠습니다.
아직 진행 중이며, 진행하면서 배우고 있습니다.
작성자: Anurag G.
LinkedIn: