Developer Brief
클립보드 히스토리 매니저
Electron + React + better-sqlite3 로 만든 클립보드 히스토리 데스크탑 앱입니다. 메인 프로세스가 클립보드 변경을 감지해 로컬 SQLite에 영구 저장하고, 전역 단축키로 토글하는 frameless 오버레이 창에서 지난 항목을 검색·고정·재복사합니다. macOS·Windows를 지원합니다.
메인 프로세스 · preload · 렌더러 세 계층으로 분리하고, 렌더러는 오직 preload가 contextBridge로 노출한 window.clipboardAPI를 통해서만 메인과 통신합니다. 네이티브 모듈(better-sqlite3·koffi)과 클립보드 접근은 메인 프로세스에만 두어 렌더러를 격리했습니다.

문제
이미지를 한 번 복사해 두면 아무 조작을 하지 않아도 CPU 점유율이 계속 높게 유지됨. 클립보드가 바뀌었는지 판단하려고 매 tick 이미지를 PNG로 재인코딩해 비교했는데, 1440x1080 기준 한 번에 약 200ms라 500ms 주기의 절반 가까이를 변화가 없는 동안에도 태우고 있었음
해결
우선 비교 기준을 PNG 대신 원시 비트맵의 sha1 해시로 바꿔 tick당 200ms → 4ms로 줄이고, 최종적으로는 koffi(FFI)로 OS의 클립보드 변경 카운터(Windows GetClipboardSequenceNumber, macOS NSPasteboard.changeCount)를 직접 읽어 카운터가 그대로면 클립보드를 아예 읽지 않도록 변경(호출당 0.55µs). FFI 로드에 실패해도 해시 비교로 폴백해 동작은 동일
문제
이미지가 쌓인 뒤로 이미지 탭 전환이 초 단위로 느려짐. 목록 조회가 수 MB짜리 base64 원본을 그대로 렌더러로 보내, 80px 미리보기를 그리려고 원본 전체를 디코딩하고 있었음
해결
캡처 시점에 축소본을 만들어 thumbnail 컬럼에 저장하고 목록은 COALESCE(thumbnail, content)로 썸네일만 전송. 렌더러에 원본이 없어지므로 재복사는 id로 요청해 메인이 DB에서 읽도록 조정
문제
설정에서 전역 단축키를 새로 녹화할 때, 사용자가 누른 조합이 globalShortcut에 걸려 오버레이 창만 뜨고 정작 입력이 렌더러까지 도달하지 못함
해결
녹화 중에는 settings:setRecording으로 전역 단축키를 잠시 해제해, 입력한 키 조합이 오버레이를 띄우지 않고 렌더러 입력으로 그대로 도달하도록 처리
아직 개발하지 않았지만, 현재 한계를 인지하고 다음 단계로 고려하는 항목입니다.
변경 카운터 폴링 → OS 푸시 이벤트 구독
카운터 도입으로 유휴 CPU 비용은 거의 사라졌지만, 여전히 500ms~1초 주기로 깨어나 카운터를 확인하는 폴링 구조라 최대 1초의 반영 지연이 남음. Windows의 AddClipboardFormatListener처럼 OS가 변경을 알려주는 푸시 방식으로 바꾸면 지연을 없앨 수 있지만, 숨김 윈도우와 네이티브 메시지 루프가 필요해 복잡도가 올라가는 트레이드오프가 있음


