"manifest.json은 extension의 출생증명서야. Chrome이 가장 먼저 읽는 파일이고, 가장 먼저 거절하는 파일이야."
세 필드짜리 manifest
Chrome은 정확히 세 개 필드만 있는 manifest를 받아 줘. 쓸 만한 건 안 되지만 — load는 돼.
저게 바닥이야. 다른 모든 거 — popup / side panel / background worker / content script — 다 이 세 필수 field 위에 쌓는 거. 이 바닥을 알아야 안 쓸 15 개 필드를 cargo-cult 안 해.
Field의 세 단계
manifest field를 세 층으로 생각해:
- 필수 — Chrome이 이게 없으면 load 자체를 거부해. 딱 셋:
manifest_version/name/version. - 강력 추천 — 없으면 load는 되는데 user experience 망가져.
description/icons/default_locale. - Surface 조건부 — 그 surface를 쓸 때만 의미 있음.
action(toolbar icon + popup) /background(service worker) /content_scripts/side_panel/permissions/host_permissions/content_security_policy/options_ui/commands/web_accessible_resources등 십여 개.
안 쓰는 surface의 조건부 field를 넣어 두는 건 해롭진 않아. 그냥 군더더기야. 반대로 쓰는 surface의 field를 빠뜨리면 조용히 죽어. extension은 멀쩡히 load 되는데 아무 일도 안 일어나지. MV3 디버깅 이야기의 절반이 그 부류 버그야.
필수 3 인방 세부
manifest_version: 2024 이후로 반드시3. 문자열 아닌 숫자.name: 1-75 자,chrome://extensions와 toolbar hover에 표시.version: 1-4 개의 점-구분 정수."0.1.0"/"1.2"/"3"다 valid. Chrome이 update 비교할 때 숫자로 비교.
강력 추천 그룹
description: 1-132 자, name 아래 한 줄 설명.icons: size (16, 32, 48, 128)를 PNG path로 매핑하는 object. 몇 개 빼먹어도 Chrome이 알아서 다른 size로 대신하지만, 16 + 48 + 128만 채워도 UI surface는 다 덮여.default_locale:_locales/*/messages.jsoni18n 활성화. 필요할 때까지 미뤄.
Surface 조건부 — 큰 것들
action— toolbar icon + popup 설정.default_popup이 클릭 시 렌더할 HTML 파일 가리킴.background— service worker 파일 선언. MV3 형태:{ "service_worker": "background.js" }.content_scripts— injection 규칙 배열.matches(URL pattern) /js(script 파일 list) /run_at(document_start|document_end|document_idle) /all_frames(boolean).side_panel— Chrome side panel surface (Chrome 114+)에 load 할 HTML.permissions— API capability (storage/tabs/activeTab/scripting/sidePanel등).host_permissions— extension이 read/inject 할 수 있는 URL pattern. API permissions와 분리.content_security_policy— extension page가 뭘 load 가능한지 fine-tune. Default 이미 빡빡함. 풀거나 조이는 거 명확히 알 때만 건드려.
ClipDeck의 hello-world manifest
Track 1의 ClipDeck 한테 필요한 건 다섯 개야. name / version / manifest version / toolbar icon / popup. 그게 끝이야. Service worker도, content script도, side panel도, permissions도 없어 — Track 1은 hello-world 니까.
아래 manifest를 clipdeck/manifest.json으로 저장. Popup HTML과 JS는 lesson 4 (hello-clipdeck)에서. icon은 16×16 / 48×48 / 128×128 PNG 아무거나. 단색 사각형도 OK.
"service_worker"에 오타가 나도 load는 돼. content script의 matches를 빠뜨려도 load는 돼. Chrome은 필수 field 에는 바로 깐깐하게 굴지만 optional field 에는 관대하거든. 디버깅은 결국 어느 침묵이 수상한지 알아보는 일이야.