"Track 3 가 CRUD 의 첫 글자 찍히면서 끝나. Content script 가 user 의 selection 잡고, service worker 로 ship, SW 가 storage 에 write, popup 이 re-render. 한 loop, 실제 work 의 한 조각. ClipDeck 의 나머지는 이 template 의 변형들."
Clip schema
코드 전에 shape 합의. Clip 은:
id— string. 저장 시점 생성, 가장 단순하고 올바른 generator 는crypto.randomUUID()(Chrome 92+). Id 가 Track 7 의 U / D 작업 primary key.text— string. 선택 텍스트, trim.url— string. 저장 시점location.href.title— string. 저장 시점document.title. Popup 이 raw URL 대신 "From Wikipedia — Service Worker" 같이 표시 가능.savedAt— number.Date.now()밀리초. Newest-first 정렬과 상대 시간 표시에 사용.
chrome.storage.local 의 clips 아래 plain array 로 저장. 다섯 field, nested shape 없음, 다 JSON-clonable. Track 7 의 update flow 가 text mutate; delete 는 id 로 제거. Track 4 의 side panel 이 같은 배열 sort/filter.
세 trigger
저장 시작 합리적 방법 세 가지, 각자 나중 track 에서 추진력 얻어:
- Floating button — Lesson 4 가 이미 wire. 매 page 에서 visible; 발견 저렴.
- Keyboard shortcut — 이 lesson 의 primary trigger. Manifest 의
commands아래 선언; SW 가 command 받아, active tab 의 content script 로 메시지, content script 가 selection read 하고 ship. - Context menu — Track 5 가 다룸. Selection 위 right-click → "Save to ClipDeck."
실제 ClipDeck user 들은 아마 keyboard shortcut (default Ctrl+Shift+K; user-rebindable) primary 로 유지하고 context menu 는 discoverability fallback. Floating button 은 나중 per-site opt-in toggle 로 졸업.
End-to-end flow
- User 가 page 에서 텍스트 select 하고
Ctrl+Shift+K. - Chrome 이 SW 에서
chrome.commands.onCommand를 command 이름save-clip으로 fire. - SW 가 active tab 의 content script 에 질문:
chrome.tabs.sendMessage(activeTab.id, { type: 'captureSelection' }). - Content script 가
window.getSelection().toString()read, URL 과 title 모음, payload 로 응답. - SW 가 응답 받아, clip object 만들고, 기존
clips를 storage 에서 read, append, write back. chrome.storage.onChangedfire; popup (열려 있으면) 과 side panel (Track 4) 이 re-render.
각 hop 이 작고 테스트 가능. Popup 에 clip 안 보이면 chain 거꾸로 walk: DevTools 에서 storage 확인, 다음 SW 로그, 다음 content script 로그.
뭐가 잘못돼
- Toolbar 상호작용 시 selection 손실. Toolbar click 이 popup 접고 가끔 selection clear. Hotkey + content-script capture 는 이걸 피해; popup-driven "Save current selection" 버튼은 popup 열리기 전에 content script 가 capture 해야 함.
- Restricted page.
chrome://, Chrome Web Store,view-source:URL 은 content-script injection 거부. SW 의 send-to-content-script 호출을 try/catch 로 감싸고 친절한 "이 page 는 ClipDeck 허용 안 함" 메시지 표면화. - Empty selection. Content script 는 명확한 empty payload (
{ ok: false, reason: 'no-selection' }) 로 응답하고 SW 가 toast 띄울지 silent drop 할지 결정하게.
한 clip, 한 loop. Content script 에서 selection, SW 로 메시지, storage 에 write, onChanged 통해 re-render. 이후 모든 ClipDeck feature 가 이 loop 에 다른 동사.
Wikipedia 에서 먼저 테스트. Wikipedia 가 가장 친절한 content-script 대상 — SPA reshuffle 없음, 공격적 CSP 없음, selection-steal handler 없음. SPA (Gmail, Twitter/X) 나 민감 content (banking, password manager — 그건 exclude 유지) 만지기 전에 Wikipedia article 에서 전체 Ctrl+Shift+K → popup-에-clip-표시 loop 동작 확인.