C.W.K.
Stream
Lesson 01 of 05 · published

Permission 모델 개관 — 세 카테고리, 하나의 신뢰 계약

~11 min · permissions, manifest, mv3, trust

Level 0Extension 입덕
0 XP0/54 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"선언하는 모든 permission 이 user 가 읽는 install prompt 의 한 문장. Lesson 1 이 모델 — 세 카테고리, 두 grant 순간, manifest 그대로에서 경고 텍스트 계산하는 하나의 Chrome."

세 카테고리

  • API permissionpermissions 배열에 선언. 각자 chrome.* namespace 해금: "storage"chrome.storage.* 활성화, "scripting"chrome.scripting.* 활성화, "contextMenus" 가 menu 활성화 등.
  • Host permissionhost_permissions 배열에 선언. 각자 URL match pattern (https://*.github.com/*, <all_urls>). 그 origin 에 script inject, DOM read, request intercept 권한 부여.
  • Optional permissionoptional_permissions AND/OR optional_host_permissions 배열에 선언. 위 둘과 같은 shape, 하지만 install 시 user 한테 prompt 안 함. 코드가 runtime 에 chrome.permissions.request 통해 요청.

MV3 가 host permission 을 API permission 에서 분리한 이유는 Chrome 이 더 깔끔한 install 경고 표시할 수 있게. User 가 "This extension can: read your data on github.com AND use storage AND use tabs" 가 아닌 "This extension can: read your data on github.com" 봄 — 구별된 줄, 구별된 시각 무게.

두 grant 순간

  • Install-time: permissionshost_permissions 의 모든 것이 user 가 extension install 시 grant. Install dialog 가 선언한 모든 것 요약; user 가 Add click 하면 영구 (uninstall 까지) 가짐.
  • Runtime: optional_permissionsoptional_host_permissions 의 모든 것은 user-gesture handler 에서 chrome.permissions.request 호출할 때만 grant. 작은 dialog 나타남; user 가 Allow 나 Deny click. Deny 면 API 가 unavailable 유지; Allow 면 session 나머지 동작하고 browser restart 너머 persist.

Chrome 이 install 경고 계산하는 법

각 permission 이 몇 가지 경고 카테고리 중 하나로 매핑. Permission 결합이 경고 collapse (예: 'tabs' 가 일부 약한 permission 흡수) 하거나 무서운 거 추가 가능 (<all_urls> 가진 어떤 것이든 'Read and change all your data on all websites' 아래로). 정확한 매핑은 Chrome Developers docs 에 있지만, rule of thumb:

  • storage, activeTab, contextMenus, sidePanel, commands, omnibox — 조용, 자체 install 경고 없음.
  • tabs — moderate, "Read your browsing history."
  • scripting, <all_urls> 보다 좁은 host permission — "Read and change your data on specific site."
  • host_permissions 나 content_scripts.matches 의 <all_urls> — 시끄러운 "Read and change all your data on all websites."
  • downloads, notifications, identity, history, geolocation, cookies — 각자 자체 dedicated 경고 줄 추가.

최소 권한 원칙

Chrome Web Store review (와 informed user) 가 extension 을 install 경고로 판단. 제거할 수 있는 모든 줄이 거부할 이유 하나 덜 줌. ClipDeck 의 실제 니즈:

  • storage — essential, 항상 선언, 무서운 경고 없음.
  • tabs — SW 에서 tab.url read 위해. Mildly 무서운 경고지만 방문 카운터와 per-site clip filter 에 필요.
  • scripting + activeTab — toolbar click 시 programmatic injection 위해. activeTab 이 on-demand 경로에 host_permissions: [<all_urls>] 건너뛰게 해 줌.
  • sidePanel, contextMenus — 조용.
  • matches: [<all_urls>] 로 선언된 content script — ClipDeck 한테 'all websites' 경고 주는 것. Track 6 Lesson 3 이 이걸 좁히는 거 논의.
  • Export 위한 downloadsoptional_permissions 로 가서 user 가 Export click 할 때만 요청해야.
세 카테고리: API, host, optional. 두 grant 순간: install 이나 on-demand. Install 경고가 trust 예산 — 신중히 써.
MV2 permissions-array 호환성 함정. Chrome 이 API 와 host permission 이 한 배열에 사는 옛 MV2 shape 도 여전히 받음. Load 되지만, 경고 요약 더 읽기 어렵고 Chrome Web Store reviewer 가 smell 로 다룸. 항상 MV3 shape 으로 split — API 엔 `permissions`, URL 엔 `host_permissions`, lazy 버전엔 optional_*.

Code

manifest.json — 네 배열 explicit 한 MV3 shape·json
{
  "manifest_version": 3,
  "name": "ClipDeck",
  "version": "0.9.0",
  "permissions": [
    "storage",
    "tabs",
    "scripting",
    "activeTab",
    "sidePanel",
    "contextMenus"
  ],
  "host_permissions": [],
  "optional_permissions": [
    "downloads"
  ],
  "optional_host_permissions": [
    "https://*/*",
    "http://*/*"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "exclude_matches": ["https://accounts.google.com/*", "https://*.bank.com/*"],
      "js": ["content.js"],
      "run_at": "document_idle"
    }
  ]
}
background.js — 선언 vs grant permission 의 진단 dump·javascript
// background.js — 선언된 / grant 된 permission 검사
async function dumpPermissions() {
  const declared = chrome.runtime.getManifest().permissions ?? [];
  const declaredHosts = chrome.runtime.getManifest().host_permissions ?? [];
  const optional = chrome.runtime.getManifest().optional_permissions ?? [];
  const optionalHosts = chrome.runtime.getManifest().optional_host_permissions ?? [];

  const granted = await chrome.permissions.getAll();
  console.group("[ClipDeck SW] permissions");
  console.log("declared API:", declared);
  console.log("declared hosts:", declaredHosts);
  console.log("optional API:", optional);
  console.log("optional hosts:", optionalHosts);
  console.log("granted now (API):", granted.permissions);
  console.log("granted now (hosts):", granted.origins);
  console.groupEnd();
}

chrome.runtime.onInstalled.addListener(dumpPermissions);

External links

Exercise

clipdeck/manifest.json 을 첫 번째 code block 매칭하도록 update (version 0.9.0, permissions / host_permissions / optional_permissions / optional_host_permissions 로 split 된 MV3-shape). chrome://extensions 에서 extension reload. ClipDeck → Details click. 'Permissions' section 봄 — API permission 들이 list 보여야 하고, Site access section 이 content-script match pattern 따로 표시해야 함. 다음 두 번째 code block (dumpPermissions) 추가하고 reload. SW DevTools console 열기 — 네 줄 봄: 선언된 API permission, 선언된 host (optional_host_permissions 로 옮겼으니 빈 배열), optional set, 그리고 이 순간 실제로 grant 된 것. optional_host_permissions 가 선언됐지만 아직 grant 안 됨; Lesson 5 에서 요청.
Hint
Console 이 optional_host_permissions undefined 보이면, Chrome 이 105 보다 옛 거 (field 도착 시점); upgrade 하든 host 를 직접 선언으로 fallback. 배열 split 후 install 경고가 나빠지면 (가끔 Chrome 이 재계산해서 그럼), 보통 host 를 content_scripts 에서 host_permissions 로 옮기는 게 더 visible 하게 한 것 — 정말 persistent grant 필요한지, activeTab + on-demand injection 이 cover 하는지 확인. 진단 dump 는 일회성 도구; Chrome Web Store 에 ship 전 제거.

Progress

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

댓글 0

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

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