"같은 panel, 다른 content — per-tab. 같은 panel, 같은 content, 모든 tab — global. ClipDeck 은 둘 다 동시에 원하고, 어느 호출이 이기는지 이해하면 API 가 깔끔히 그걸 허용."
두 scoping 층
chrome.sidePanel.setOptions 의 매 호출이 두 scope 중 하나로 state 설정:
- Per-tab —
{ tabId: T, ... }로 호출. Settings (path, enabled) 가 tab T 가 active 일 때만 적용. 각 tab 이 자기 독립 state 가짐. - Global —
tabId없이 호출. Settings 가 명시적 per-tab override 없는 모든 tab 의 default 됨.
Per-tab 이 global 보다 이김. Tab T 가 setOptions({ tabId: T, enabled: false }) 가지고 global 이 enabled: true 면, panel 은 T 에서 disabled, 다른 모든 곳 enabled.
ClipDeck 이 쓰는 것
ClipDeck 은 clip library 하나 (global storage) 가져, panel content 는 근본적으로 tab 간 같음. 그러나 두 per-tab behavior 가 중요:
- Site 별 filtered view. User 가 github.com 에 있을 때, panel 이 github.com 에서 저장된 clip 만 보이게 pre-filter 가능. SW 의 tab-update handler 에서
tab.urlread 하고 panel path 에 다른 query string write:panel.html?host=github.com. - 민감 site 에서 disable. Banking, password manager, 또는 specific user-blocklisted URL 에서 그 tab 의
enabled: false설정해 panel chooser 가 ClipDeck 숨김. User 의 privacy 기대 인정.
Default (global) state 는 enabled: true, path: 'panel.html' 유지, panel 이 per-tab work 없이 다른 모든 tab 에서 가능.
setOptions 가 합성되는 법
Path field 는 tab 별 다를 수 있음 — 위의 site-filtered view 에 유용. Chrome 이 panel.html?host=github.com 를 navigation 으로 다뤄; panel JS 가 mount 시 new URLSearchParams(location.search) read 하면, 렌더된 list 그에 맞춰 filter 가능. Path 바뀔 때 panel reload.
Enabled field 는 chooser 의 visibility 만 제어 — tab 의 panel disable 한다고 다른 tab 의 이미 열린 panel 안 닫음. Panel 이 disabled 된 tab 으로 전환하면 chooser 에서 ClipDeck 숨겨짐; 다시 돌아오면 다시 노출.
Activation lifecycle
setOptions 호출 trigger 해야 할 tab event:
chrome.tabs.onActivated— user 가 이 tab 으로 전환.chrome.tabs.onUpdatedwithstatus === 'complete'— page load 끝남; URL 이 이제 안정적으로 read 가능.chrome.tabs.onCreated— 새 tab 열림, 명시적으로 global default 상속 원할 수도.
chrome.runtime.onInstalled 에서 모든 기존 tab 에 setOptions 호출할 필요 없음 — global setOptions 가 cover. 하지만 global 호출 한 번은 필요 — 아직 구체적으로 처리 안 한 tab 에 panel 이 합리적 default 가지게.
Race-free 패턴
결합된 onActivated + onUpdated 패턴이 실용에서 race-free:
- Install/startup 시 global
setOptions({ path: 'panel.html', enabled: true })호출. - 매 onActivated 와 매 onUpdated(complete) 마다
tab.url에서 원하는 per-tab state 계산하고setOptions({ tabId, path, enabled })호출. - 어떤 tab 이든 첫 event 가 global default 를 per-tab specific 으로 "upgrade". 이후 event 가 idempotent 하게 재적용.
Idempotency 가 중요 — 두 event 가 가까이 fire 가능 (새 tab 열고 navigate, 다른 tab click 후 돌아오기 — SW 가 빠른 sequence 받음). 같은 값으로 setOptions 재적용 저렴.