본문 바로가기
C.W.K.
Stream
Lesson 02 of 06 · published

Service Worker 등록하기

~10 min · service-worker, manifest, background, clipdeck, hands-on

Level 0Extension 입덕
0 XP0/56 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"Track 1은 ClipDeck을 popup만 있는 순수 UI로 끝냈어. Track 2가 background를 부여하면서 시작. Manifest field 하나, 파일 하나, reload 한 번, ClipDeck이 service worker를 갖게 돼."

Manifest field 하나, 파일 하나

Manifest 변경은 작아: top-level background object 하나가 worker 파일 가리킴. 세 가지 주목:

  • service_worker는 단수. MV2 (배열의 scripts를 받았던)와 다르게, MV3는 파일 정확히 하나만 받아. Logic 분할 필요하면 ES module import 사용.
  • Path는 extension root 기준 상대, iconspopup과 동일.
  • persistent field 없어 — 모든 MV3 service worker는 정의상 event-driven. 옛 background page를 살려두던 MV2의 persistent: true 트릭은 그냥 사라졌어.

그게 background context의 manifest 계약 전부. clipdeck/manifest.json 옆에 새 파일 저장.

Skeleton background.js

listener 셋이 전부고, 파일 최상위에 들고 있는 state도 없고, setInterval도 없어. 맨 윗부분은 깨어날 때마다 다시 돌고, listener는 event가 올 때 돌아. 건강한 MV3 service worker는 딱 이렇게 생겼어 — event handler만 평평하게 늘어놓은 파일 하나, 그 밖엔 아무것도.

알아둘 등록 두 가지:

  • chrome.runtime.onInstalled — install 시 한 번, 매 extension update 시 한 번, Chrome update 시에도 fire. details.reason으로 분기.
  • chrome.runtime.onStartup — Chrome이 extension 이미 install 된 상태로 launch 할 때 fire. Browser session 당 한 번 일어나야 하는 daily-rollup 류 작업에 유용.

위 부분의 console.log가 eviction tracker야. DevTools에서 다시 찍힐 때마다 worker가 방금 cold start 한 거지.

Reload, 검증, 깨우기

Manifest 업데이트 + background.js 저장 후:

  1. chrome://extensions의 ClipDeck 카드 reload.
  2. chrome://serviceworker-internals 열고 ClipDeck 검색. Entry 하나 보여야 함: ClipDeck의 service worker, 상태 RUNNING, 신선한 registration timestamp.
  3. 대략 30 초 대기. Refresh. 상태가 STOPPED로 전환.
  4. ClipDeck toolbar icon 클릭 (event 면 뭐든 — message / alarm / tab change). Refresh. 상태 RUNNING으로 복귀.

그게 service worker의 전체 dev loop: edit → reload → worker 존재 확인 → 필요할 때 깨우기 → idle out 관찰.

Service worker 검사하기

chrome://extensions → ClipDeck 카드 → "Details" → "Inspect views: service worker". DevTools가 worker scope로 열림. Console 에는 background.js 맨 위가 돌면서 찍은 [ClipDeck SW] alive at ...이 보일 거야. Network 패널에는 fetch 요청이 있으면 뜨고, Application 탭에서 storage를 볼 수 있어 (lesson 4가 거기서 놀아). Sources 탭에서는 breakpoint를 걸고 listener를 한 줄씩 따라가면서 지역 변수도 들여다볼 수 있고.

알아둘 quirk 두 개:

  • Worker evict 돼도 DevTools window는 열린 채로 유지. 다음 wake가 같은 DevTools session에 재attach.
  • 디버깅 도중 DevTools 닫으면 breakpoint 잃음. 다시 열고 재설정.

ClipDeck이 이제 background를 가짐

이 lesson을 지나면 ClipDeck은 자리를 둘 갖게 돼. 필요할 때만 뜨는 popup과, 뒤에서 event를 기다리는 service worker. Lesson 3에서 한 살이를 깊게 보면서 state가 실제로 날아가는 걸 눈으로 확인하고, Lesson 4에서 chrome.storage를 살아남는 층으로 얹고, Lesson 5에서 popup과 SW 사이 메시지를 잇고, Lesson 6에서 방문 카운터로 그걸 다 묶어. CRUD의 R을 위한 몸풀기지.

Manifest field는 작아. 그 뒤의 mental model은 커. background.js에 쓸 매 줄이 worker가 event 사이에 사라질 수 있다는 걸 가정해.
background.js의 모든 console.log[SW] prefix 박아. popup / content script / worker 모두 같은 DevTools session에 로그 찍게 될 때 (Track 3부터), prefix가 어느 surface가 말했는지 즉시 알려줘. Track 1-2에 습관 싸게 들여놔, 헷갈릴 게 생기기 전에.

Code

clipdeck/manifest.json — background.service_worker 추가 + version bump·json
{
  "manifest_version": 3,
  "name": "ClipDeck",
  "version": "0.2.0",
  "description": "Selected-text clipboard you can CRUD from any page.",
  "icons": {
    "16": "icons/icon-16.png",
    "48": "icons/icon-48.png",
    "128": "icons/icon-128.png"
  },
  "action": {
    "default_popup": "popup.html",
    "default_title": "ClipDeck"
  },
  "background": {
    "service_worker": "background.js"
  }
}
clipdeck/background.js — 최소 service worker·javascript
// clipdeck/background.js — ClipDeck v0.2 (Track 2 lesson 2)
// Service worker top-level — runs on every wake-up.

console.log("[ClipDeck SW] alive at", new Date().toISOString());

chrome.runtime.onInstalled.addListener((details) => {
  console.log(
    "[ClipDeck SW] onInstalled — reason:",
    details.reason,
    "previousVersion:",
    details.previousVersion
  );
});

chrome.runtime.onStartup.addListener(() => {
  console.log("[ClipDeck SW] onStartup — Chrome launched");
});

// No module-level state. No setInterval. No fetch loops.
// Every event handler is the entire unit of work.

External links

Exercise

clipdeck/manifest.json 업데이트해서 background.service_worker field 추가 + version을 "0.2.0" 으로 bump. clipdeck/background.js를 위 skeleton으로 생성. chrome://extensions에서 ClipDeck 카드 reload. 그 다음 checkpoint 따라가: (1) chrome://serviceworker-internals — ClipDeck 찾고 status 메모 (reload 직후 RUNNING). (2) 30 초 대기, refresh — STOPPED로 전환. (3) ClipDeck toolbar icon 클릭. chrome://serviceworker-internals refresh — RUNNING으로 복귀. (4) ClipDeck 카드의 Inspect views: service worker 열어서 Console에 [ClipDeck SW] alive at ... 로그 보이는지 확인.
Hint
chrome://serviceworker-internals에 ClipDeck entry 안 보이면 manifest 업데이트 안 적용 — JSON syntax 확인 (trailing comma가 보통 원인) 후 reload 재클릭. background.js에 syntax error 있으면 ClipDeck extension 카드의 Errors panel이 line 보여줘. background.service_worker 없는 extension 에는 Inspect views가 안 나타나니까, 그 항목 존재가 manifest 적용 두 번째 확인.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.