"Popup은 HTML 이야 — 그게 트릭. 'Chrome 만의 뭔가' 라고 생각하지 말고 chrome.* 접근권 가진 작은 webpage 라고 생각하기 시작하면, 나머지 extension API도 더 이상 이질감 없어."
Manifest에서 동작하는 popup까지
Lesson 2의 manifest가 action block을 선언했어:
"action": {
"default_popup": "popup.html",
"default_title": "ClipDeck"
}
그 default_popup field가 약속이야 — toolbar icon 클릭하면 Chrome이 그 이름의 HTML 파일을 popup window 안에 렌더. Chrome은 그 파일 내용에 무관심해, 유효한 HTML page 이기만 하면 — "Hello world" 정적 문자열도 가능, React bundle도 가능, 또는 — 여기서 만들 — active tab 읽어서 title 보여주는 얇은 shell.
이 lesson은 clipdeck/에 두 새 파일을 저장해: popup.html / popup.js. 테스트 전에 manifest의 permissions에 "activeTab"을 넣어. 그러면 action 클릭이 현재 tab title 같은 민감한 field를 잠깐 읽을 권한을 열어. Reload, 클릭, ClipDeck이 처음으로 뭔가 해.
popup.html — 최소 skeleton
Popup은 평범한 HTML 문서야, 알아둘 두 가지만:
- Popup window는 content에 자동 크기 조정, 약 800×600까지.
body에 명시적width박아서 안정화. - MV3는 inline JavaScript 금지 (Content Security Policy 통해). Script는 별도 파일에 두고
<script src="popup.js">로 참조.<script>alert()</script>같은 inline script 안 돼, inlineonclickhandler도 안 돼. 모든 MV2-시대 튜토리얼 reader가 딱 한 번씩 이걸로 걸려.
popup.js — Active tab 읽기
chrome.tabs.query가 "지금 user가 보고 있는 tab이 뭐야?" 물어보는 API. MV3 에선 Promise 반환 (또는 callback — 둘 다 됨). Filter property 셋이 중요:
active: true— 자기 window 안에서 focus 가짐currentWindow: true— 지금 이 window, background window 아님- 결과는 항상 배열 — 보통 length 1, 근데 MV3가 보장하지는 않아.
tabs[0]?.title같은 식 또는 default 값 있는 array destructuring으로 방어.
Popup script가 하는 일은 작아: query / title 읽기 / 렌더. 그게 popup.js 본문 전체.
첫 클릭
popup.html과 popup.js를 clipdeck/에 저장한 다음:
chrome://extensions열기.- ClipDeck 카드의 reload (↻) 버튼 클릭.
- Toolbar의 ClipDeck 아이콘 클릭.
작은 popup window가 열려. Script가 돌아. 그 tab의 page title이 popup에 떠. Tab 바꾸고 아이콘 다시 클릭 — 새 tab의 title 표시. chrome.tabs.query가 popup 열릴 때마다 상태 read — 캐싱 없음, stale data 없음, 그 순간 Chrome UI가 아는 거 그대로.
이 작은 데모가 왜 중요해
이게 모든 미래 ClipDeck 기능이 따를 형태:
- Manifest가 surface 선언 (popup / side panel / content script / options page).
- 그 surface의 HTML load.
- 그 surface 안의 JavaScript가
chrome.*API 호출 — Chrome 상태 read 또는 변경. - UI update.
Track 2가 background service worker 추가 (UI 없는 surface). Track 3가 content script 추가 (host page 안의 UI 존재). Track 4가 popup을 더 풍부한 side panel로 교체. Track 5가 popup에 selection capture + storage save를 wire. 다 위 4 단계 패턴 위에 쌓는 거.
alert() 봤을 때랑 똑같아 — "잠깐, 브라우저가 진짜 내 말 듣네?" 그 느낌 잡고 있어. browser extension이 존재하는 이유 전부. Pippa Chrome Embed v0.1이 그 같은 놀라움을 household scale로 늘린 거 — 같은 surprise, 그저 hardcoded query 대신 cwkPippa의 brain 통과해서 흐를 뿐.Track 1의 조기 회고
Popup이 동작하면, ClipDeck은 "disk 위의 파일" 에서 "동작하는 Chrome extension" 으로 선을 넘은 거야. Lesson 5와 6이 security model과 gotchas 다루지만 — ClipDeck 자체는 이 시점부터 살아 있어. 매 미래 track이 한 조각씩 더해. 이 데모의 작음에 속지 마: 여기서 dev loop가 닫혀.