Manifest V3μ μλ°μ€ν¬λ¦½νΈ APIλ₯Ό μ¬μ©ν λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ κ°λ° μ¬μΈ΅ λΆμ. μ΅μ λΈλΌμ°μ λ₯Ό μν κ°λ ₯νκ³ μμ ν νμ₯ νλ‘κ·Έλ¨μ λ§λλ λ°©λ²μ λ°°μ보μΈμ.
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ κ°λ°: Manifest V3μ μλ°μ€ν¬λ¦½νΈ API
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ λΈλΌμ°μ§ κ²½νμ λ§μΆ€ μ€μ νλ μμ μννΈμ¨μ΄ νλ‘κ·Έλ¨μ λλ€. μλ‘μ΄ κΈ°λ₯μ μΆκ°νκ³ , μΉμ¬μ΄νΈ μ½ν μΈ λ₯Ό μμ νλ©°, κ΄κ³ λ₯Ό μ°¨λ¨νλ λ± λ€μν μμ μ μνν μ μμ΅λλ€. Manifest V3μ λ±μ₯μΌλ‘ νμ₯ νλ‘κ·Έλ¨μ ꡬμΆνκ³ μλνλ λ°©μμ μλΉν λ³νκ° μμμ΅λλ€. μ΄ μ’ ν© κ°μ΄λμμλ Manifest V3μ μλ°μ€ν¬λ¦½νΈ APIλ₯Ό μ¬μ©ν λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ κ°λ°μ νꡬνλ©°, μ΅μ λΈλΌμ°μ λ₯Ό μν κ°λ ₯νκ³ μμ ν νμ₯ νλ‘κ·Έλ¨μ λ§λλ λ° νμν μ§μμ μ 곡ν©λλ€.
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ΄λ?
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ λ³Έμ§μ μΌλ‘ μΉ λΈλΌμ°μ λ΄μμ μ€νλλ λ―Έλ μ ν리μΌμ΄μ μ λλ€. λΈλΌμ°μ μ κΈ°λ₯μ νμ₯νκ³ μΉ νμ΄μ§μ μννκ² ν΅ν©λ©λλ€. νμ₯ νλ‘κ·Έλ¨μ HTML, CSS, μλ°μ€ν¬λ¦½νΈμ κ°μ νμ€ μΉ κΈ°μ μ μ¬μ©νμ¬ μμ±λλ―λ‘ μΉ κ°λ°μλ€μ΄ λΉκ΅μ μ½κ² μ κ·Όν μ μμ΅λλ€.
μΈκΈ° μλ λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ μμλ λ€μκ³Ό κ°μ΅λλ€:
- κ΄κ³ μ°¨λ¨κΈ°: μΉ νμ΄μ§μ κ΄κ³ λ₯Ό μ°¨λ¨νμ¬ λΈλΌμ°μ§ μλλ₯Ό κ°μ νκ³ λ°©ν΄ μμλ₯Ό μ€μ λλ€.
- λΉλ°λ²νΈ κ΄λ¦¬μ: λΉλ°λ²νΈλ₯Ό μμ νκ² μ μ₯νκ³ κ΄λ¦¬νλ©°, μΉμ¬μ΄νΈμμ μλμΌλ‘ μ±μμ€λλ€.
- λ©λͺ¨ νμ₯ νλ‘κ·Έλ¨: μ¬μ©μκ° μΉ νμ΄μ§μμ μ§μ λ©λͺ¨λ₯Ό μμ±νκ³ μ μ₯ν μ μμ΅λλ€.
- μμ°μ± λꡬ: μμ κ΄λ¦¬, μκ° μΆμ , μ§μ€ λͺ¨λμ κ°μ κΈ°λ₯μ μ 곡νμ¬ μμ°μ±μ ν₯μμν΅λλ€.
- μΈμ΄ λ²μ λꡬ: ν λ²μ ν΄λ¦μΌλ‘ μΉ νμ΄μ§λ₯Ό λ€λ₯Έ μΈμ΄λ‘ λ²μν©λλ€. μ: κ΅¬κΈ λ²μ νμ₯ νλ‘κ·Έλ¨.
- VPN νμ₯ νλ‘κ·Έλ¨: μΈν°λ· νΈλν½μ νλ‘μνμ¬ μ§λ¦¬μ μ νμ μ°ννκ³ κ°μΈμ 보 보νΈλ₯Ό κ°νν©λλ€.
Manifest V3μ μ€μμ±
Manifest V3λ νμ₯ νλ‘κ·Έλ¨μ λΈλΌμ°μ μ μ€λͺ νλ JSON νμΌμΈ λ§€λνμ€νΈ νμΌμ μ΅μ λ²μ μ λλ€. νμ₯ νλ‘κ·Έλ¨μ μ΄λ¦, λ²μ , κΆν, λ°±κ·ΈλΌμ΄λ μ€ν¬λ¦½νΈ λ° κΈ°ν νμ λ©νλ°μ΄ν°λ₯Ό κ°κ΄μ μΌλ‘ μ€λͺ ν©λλ€. Manifest V3λ μ΄μ λ²μ μΈ Manifest V2μ λΉν΄ μ£Όλ‘ λ³΄μκ³Ό μ±λ₯μ μ΄μ μ λ§μΆ λͺ κ°μ§ μ£Όμ λ³κ²½ μ¬νμ λμ νμ΅λλ€.
Manifest V3μ μ£Όμ λ³κ²½ μ¬ν:
- μλΉμ€ μ컀(Service Workers): Manifest V3λ λ°±κ·ΈλΌμ΄λ νμ΄μ§λ₯Ό μλΉμ€ μμ»€λ‘ λ체ν©λλ€. μλΉμ€ μ컀λ μꡬμ μΈ νμ΄μ§ μμ΄ λ°±κ·ΈλΌμ΄λμμ μ€νλλ μ΄λ²€νΈ κΈ°λ° μ€ν¬λ¦½νΈμ λλ€. λ°±κ·ΈλΌμ΄λ νμ΄μ§λ³΄λ€ λ ν¨μ¨μ μ΄κ³ 리μμ€λ₯Ό μ κ² μλͺ¨ν©λλ€.
- μ μΈμ Net Request API (Declarative Net Request API): μ΄ APIλ₯Ό μ¬μ©νλ©΄ νμ₯ νλ‘κ·Έλ¨μ΄ λ€νΈμν¬ μμ²μ μ§μ κ°λ‘μ±μ§ μκ³ λ μμ ν μ μμ΅λλ€. νν°λ§ λ‘μ§μ λΈλΌμ°μ μ μ€νλ‘λνμ¬ λ³΄μκ³Ό μ±λ₯μ ν₯μμν΅λλ€.
- λ μ격ν μ½ν μΈ λ³΄μ μ μ± (CSP): Manifest V3λ μμμ μ½λ μ€νμ λ°©μ§νκΈ° μν΄ λ μ격ν CSP κ·μΉμ μ μ©νμ¬ λ³΄μμ λμ± κ°νν©λλ€.
- Promise κΈ°λ° API: λ§μ APIκ° μ΄μ Promise κΈ°λ°μΌλ‘ λμ΄ μμ΄ λΉλκΈ° μμ μ λ μ½κ² κ΄λ¦¬ν μ μμ΅λλ€.
μ Manifest V3λ‘ μ νλμλκ°?
- ν₯μλ 보μ: Manifest V3λ λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ 보μμ κ°μ νκ³ μ¬μ©μλ₯Ό μ μ± μ½λλ‘λΆν° 보νΈνλλ‘ μ€κ³λμμ΅λλ€.
- κ°μ λ μ±λ₯: μλΉμ€ μ컀μ μ μΈμ Net Request APIλ λ λμ μ±λ₯κ³Ό 리μμ€ μλΉ κ°μμ κΈ°μ¬ν©λλ€.
- κ°νλ κ°μΈμ 보 보νΈ: Manifest V3λ μ¬μ©μμκ² μμ μ λ°μ΄ν°μ κ°μΈμ 보μ λν λ λ§μ ν΅μ κΆμ λΆμ¬νλ κ²μ λͺ©νλ‘ ν©λλ€.
κ°λ° νκ²½ μ€μ νκΈ°
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ κ°λ°μ μμνκΈ° μ μ κ°λ° νκ²½μ μ€μ ν΄μΌ ν©λλ€. μ¬κΈ°μλ μ½λ μλν° μ€μΉ, ν μ€νΈμ© λΈλΌμ°μ μ ν, νμ₯ νλ‘κ·Έλ¨μ κΈ°λ³Έ νμΌ κ΅¬μ‘° μ΄ν΄κ° ν¬ν¨λ©λλ€.
1. μ½λ μλν°
νΈνκ² μ¬μ©ν μ μλ μ½λ μλν°λ₯Ό μ ννμΈμ. μΈκΈ° μλ μ΅μ μ λ€μκ³Ό κ°μ΅λλ€:
- Visual Studio Code (VS Code): μλ°μ€ν¬λ¦½νΈ λ° κΈ°ν μΉ κΈ°μ μ νλ₯νκ² μ§μνλ 무λ£μ΄λ©° κ°λ ₯ν μ½λ μλν°μ λλ€.
- Sublime Text: λ€μν νλ¬κ·ΈμΈμ κ°μΆ λΉ λ₯΄κ³ μ¬μ©μ μ μκ° κ°λ₯ν μ½λ μλν°μ λλ€.
- Atom: GitHubμμ κ°λ°ν λ¬΄λ£ μ€νμμ€ μ½λ μλν°μ λλ€.
2. ν μ€νΈμ© λΈλΌμ°μ
νμ₯ νλ‘κ·Έλ¨μ ν μ€νΈν λΈλΌμ°μ λ₯Ό μ ννμΈμ. Chromeκ³Ό Firefoxλ κ°λ ₯ν κ°λ°μ λꡬμ νμ₯ νλ‘κ·Έλ¨ κ°λ° μ§μμ μ 곡νλ―λ‘ κ°μ₯ μΈκΈ° μλ μ νμ§μ λλ€.
3. κΈ°λ³Έ νμΌ κ΅¬μ‘°
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ μΌλ°μ μΌλ‘ λ€μ νμΌλ€λ‘ ꡬμ±λ©λλ€:
- manifest.json: μ΄λ¦, λ²μ , κΆν, λ°±κ·ΈλΌμ΄λ μ€ν¬λ¦½νΈ λ± νμ₯ νλ‘κ·Έλ¨μ λ©νλ°μ΄ν°λ₯Ό λ΄κ³ μλ νμΌμ λλ€.
- background.js (λλ μλΉμ€ μ컀 μ€ν¬λ¦½νΈ): λ°±κ·ΈλΌμ΄λμμ μ€νλλ©° λΈλΌμ°μ μ‘μ λ° μ»¨ν μ€νΈ λ©λ΄ ν΄λ¦κ³Ό κ°μ μ΄λ²€νΈλ₯Ό μ²λ¦¬νλ μ€ν¬λ¦½νΈμ λλ€.
- content.js: μΉ νμ΄μ§μ 컨ν μ€νΈμμ μ€νλλ©° ν΄λΉ νμ΄μ§μ μ½ν μΈ λ₯Ό μμ ν μ μλ μ€ν¬λ¦½νΈμ λλ€.
- popup.html: νμ₯ νλ‘κ·Έλ¨ νμ μ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό μ μνλ νμΌμ λλ€.
- popup.js: νμ₯ νλ‘κ·Έλ¨ νμ μ λ‘μ§μ μ²λ¦¬νλ μ€ν¬λ¦½νΈμ λλ€.
- options.html: νμ₯ νλ‘κ·Έλ¨ μ΅μ νμ΄μ§μ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό μ μνλ νμΌμ λλ€.
- options.js: νμ₯ νλ‘κ·Έλ¨ μ΅μ νμ΄μ§μ λ‘μ§μ μ²λ¦¬νλ μ€ν¬λ¦½νΈμ λλ€.
- icons: λΈλΌμ°μ ν΄λ° λ° νμ₯ νλ‘κ·Έλ¨ κ΄λ¦¬ νμ΄μ§μμ νμ₯ νλ‘κ·Έλ¨μ λνλ΄λ λ° μ¬μ©λλ μμ΄μ½λ€μ λλ€.
첫 νμ₯ νλ‘κ·Έλ¨ λ§λ€κΈ°: "Hello, World!"
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ κ°λ°μ κΈ°λ³Έ μ리λ₯Ό 보μ¬μ£ΌκΈ° μν΄ κ°λ¨ν "Hello, World!" νμ₯ νλ‘κ·Έλ¨μ λ§λ€μ΄ λ΄ μλ€.
1. λ§€λνμ€νΈ νμΌ λ§λ€κΈ° (manifest.json)
μ λλ ν 리μ `manifest.json`μ΄λΌλ νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μΆκ°νμΈμ:
{
"manifest_version": 3,
"name": "Hello, World!",
"version": "1.0",
"description": "A simple Hello, World! extension",
"permissions": [
"storage"
],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
},
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
}
μ€λͺ :
- `manifest_version`: λ§€λνμ€νΈ νμΌμ λ²μ μ μ§μ ν©λλ€ (Manifest V3μ κ²½μ° 3).
- `name`: νμ₯ νλ‘κ·Έλ¨μ μ΄λ¦μ λλ€.
- `version`: νμ₯ νλ‘κ·Έλ¨μ λ²μ λ²νΈμ λλ€.
- `description`: νμ₯ νλ‘κ·Έλ¨μ λν κ°λ΅ν μ€λͺ μ λλ€.
- `permissions`: νμ₯ νλ‘κ·Έλ¨μ΄ νμλ‘ νλ κΆνμ λ°°μ΄μ λλ€ (μ: "storage").
- `action`: κΈ°λ³Έ νμ νμΌ λ° μμ΄μ½μ ν¬ν¨νμ¬ νμ₯ νλ‘κ·Έλ¨ νμ μ μμ±μ μ μν©λλ€.
- `icons`: νμ₯ νλ‘κ·Έλ¨ μμ΄μ½μ κ²½λ‘λ₯Ό μ§μ ν©λλ€.
2. νμ νμΌ λ§λ€κΈ° (popup.html)
κ°μ λλ ν 리μ `popup.html`μ΄λΌλ νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μΆκ°νμΈμ:
Hello, World!
Hello, World!
This is a simple browser extension.
μ΄ νμΌμ "Hello, World!" λ©μμ§λ₯Ό νμν νμ₯ νλ‘κ·Έλ¨ νμ μ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό μ μν©λλ€.
3. μμ΄μ½ μ΄λ―Έμ§ λ§λ€κΈ°
λ€μ ν¬κΈ°μ μμ΄μ½ μ΄λ―Έμ§ μΈ κ°λ₯Ό λ§λμΈμ: 16x16, 48x48, 128x128 ν½μ . νμ₯ νλ‘κ·Έλ¨ λλ ν 리 λ΄μ `images` λλ ν 리μ `icon16.png`, `icon48.png`, `icon128.png`λ‘ μ μ₯νμΈμ.
4. λΈλΌμ°μ μ νμ₯ νλ‘κ·Έλ¨ λ‘λνκΈ°
Chrome:
- Chromeμ μ΄κ³ `chrome://extensions`λ‘ μ΄λν©λλ€.
- μ€λ₯Έμͺ½ μλ¨μμ "κ°λ°μ λͺ¨λ"λ₯Ό νμ±νν©λλ€.
- "μμΆ ν΄μ λ νμ₯ νλ‘κ·Έλ¨μ λ‘λν©λλ€."λ₯Ό ν΄λ¦νκ³ νμ₯ νλ‘κ·Έλ¨ νμΌμ΄ μλ λλ ν 리λ₯Ό μ νν©λλ€.
Firefox:
- Firefoxλ₯Ό μ΄κ³ `about:debugging#/runtime/this-firefox`λ‘ μ΄λν©λλ€.
- "μμ λΆκ° κΈ°λ₯ λ‘λ..."λ₯Ό ν΄λ¦νκ³ `manifest.json` νμΌμ μ νν©λλ€.
μ΄μ "Hello, World!" νμ₯ νλ‘κ·Έλ¨μ΄ μ€μΉλμ΄ λΈλΌμ°μ ν΄λ°μ νμλ κ²μ λλ€. νμ₯ νλ‘κ·Έλ¨ μμ΄μ½μ ν΄λ¦νμ¬ νμ μ μ΄κ³ "Hello, World!" λ©μμ§λ₯Ό νμΈνμΈμ.
μλ°μ€ν¬λ¦½νΈ API μμ νκΈ°
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ μλ°μ€ν¬λ¦½νΈ APIλ₯Ό μ¬μ©νμ¬ λΈλΌμ°μ λ° μΉ νμ΄μ§μ μνΈ μμ©ν μ μμ΅λλ€. μ΄λ¬ν APIλ λ€μκ³Ό κ°μ λ€μν κΈ°λ₯μ λν μ‘μΈμ€λ₯Ό μ 곡ν©λλ€:
- Tabs API: ν μμ±, μ λ°μ΄νΈ, 쿼리 λ± λΈλΌμ°μ νμ κ΄λ¦¬ν μ μμ΅λλ€.
- Storage API: νμ₯ νλ‘κ·Έλ¨ λ΄μμ λ°μ΄ν°λ₯Ό μꡬμ μΌλ‘ μ μ₯νκ³ κ²μνλ λ°©λ²μ μ 곡ν©λλ€.
- Alarms API: νΉμ μκ°μ μ€νλ μμ μ μμ½ν μ μμ΅λλ€.
- Notifications API: μ¬μ©μμκ² μλ¦Όμ νμν μ μμ΅λλ€.
- Context Menus API: λΈλΌμ°μ μ 컨ν μ€νΈ λ©λ΄(μ€λ₯Έμͺ½ ν΄λ¦ λ©λ΄)μ μ¬μ©μ μ μ νλͺ©μ μΆκ°ν μ μμ΅λλ€.
- Web Request API (Manifest V3μμλ Declarative Net Request): λ€νΈμν¬ μμ²μ κ°λ‘μ±κ³ μμ ν μ μμ΅λλ€.
- Scripting API: μΉ νμ΄μ§μ μ€ν¬λ¦½νΈλ₯Ό μ£Όμ ν μ μμ΅λλ€.
μμ : Storage API μ¬μ©νκΈ°
Storage APIλ₯Ό μ¬μ©νμ¬ μ¬μ©μ μ΄λ¦μ μ μ₯νκ³ κ²μνλ νμ₯ νλ‘κ·Έλ¨μ λ§λ€μ΄ λ΄ μλ€.
1. λ§€λνμ€νΈ νμΌ μ λ°μ΄νΈνκΈ° (manifest.json)
`manifest.json`μ `permissions` λ°°μ΄μ `"storage"`κ° ν¬ν¨λμ΄ μλμ§ νμΈνμΈμ:
{
"manifest_version": 3,
"name": "Storage Example",
"version": "1.0",
"description": "An extension that uses the Storage API",
"permissions": [
"storage"
],
"action": {
"default_popup": "popup.html"
},
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
}
2. νμ νμΌ λ§λ€κΈ° (popup.html)
`popup.html`μ λ€μ λ΄μ©μΌλ‘ λ§λ€κ±°λ μ λ°μ΄νΈνμΈμ:
Storage Example
Storage Example
3. νμ μ€ν¬λ¦½νΈ λ§λ€κΈ° (popup.js)
`popup.js`λΌλ νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μΆκ°νμΈμ:
document.addEventListener('DOMContentLoaded', () => {
const nameInput = document.getElementById('name');
const saveButton = document.getElementById('save');
const greeting = document.getElementById('greeting');
// μ μ₯μμμ μ μ₯λ μ΄λ¦ λ‘λ
chrome.storage.sync.get('name', (data) => {
if (data.name) {
nameInput.value = data.name;
greeting.textContent = `Hello, ${data.name}!`;
}
});
// λ²νΌ ν΄λ¦ μ μ΄λ¦μ μ μ₯μμ μ μ₯
saveButton.addEventListener('click', () => {
const name = nameInput.value;
chrome.storage.sync.set({ name: name }, () => {
greeting.textContent = `Hello, ${name}!`;
});
});
});
μ€λͺ :
- μ€ν¬λ¦½νΈλ μ½λλ₯Ό μ€ννκΈ° μ μ DOMμ΄ μμ ν λ‘λλμλμ§ νμΈνκΈ° μν΄ `DOMContentLoaded` μ΄λ²€νΈλ₯Ό μμ ν©λλ€.
- μ λ ₯ νλ, μ μ₯ λ²νΌ, μΈμ¬λ§ λ¨λ½μ λν μ°Έμ‘°λ₯Ό κ°μ Έμ΅λλ€.
- `chrome.storage.sync.get()`μ μ¬μ©νμ¬ μ μ₯μμμ μ μ₯λ μ΄λ¦μ λ‘λν©λλ€.
- μ μ₯ λ²νΌμ ν΄λ¦νλ©΄ `chrome.storage.sync.set()`μ μ¬μ©νμ¬ μ΄λ¦μ μ μ₯μμ μ μ₯ν©λλ€.
- μ μ₯λκ±°λ μ λ ₯λ μ΄λ¦μΌλ‘ μΈμ¬λ§ λ¨λ½μ μ λ°μ΄νΈν©λλ€.
λΈλΌμ°μ μμ νμ₯ νλ‘κ·Έλ¨μ λ€μ λ‘λνμΈμ. μ΄μ νμ μ μ΄λ©΄ μ΄λ¦μ μ λ ₯νκ³ μ μ₯ν ν μΈμ¬λ§ λ©μμ§λ₯Ό λ³Ό μ μμ΅λλ€. μ΄λ¦μ νμ₯ νλ‘κ·Έλ¨μ μ μ₯μμ μ μ₯λλ©° λ€μμ νμ μ μ΄ λ λ‘λλ©λλ€.
μμ : Tabs API μ¬μ©νκΈ°
νμ¬ νμ URLμ νμ μ νμνλ νμ₯ νλ‘κ·Έλ¨μ λ§λ€μ΄ λ΄ μλ€.
1. λ§€λνμ€νΈ νμΌ μ λ°μ΄νΈνκΈ° (manifest.json)
`manifest.json`μ `permissions` λ°°μ΄μ `"tabs"` κΆνμ μΆκ°νμΈμ:
{
"manifest_version": 3,
"name": "Tabs Example",
"version": "1.0",
"description": "An extension that uses the Tabs API",
"permissions": [
"tabs"
],
"action": {
"default_popup": "popup.html"
},
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
}
2. νμ νμΌ λ§λ€κΈ° (popup.html)
`popup.html`μ λ€μ λ΄μ©μΌλ‘ λ§λ€κ±°λ μ λ°μ΄νΈνμΈμ:
Tabs Example
Tabs Example
Current Tab URL:
3. νμ μ€ν¬λ¦½νΈ λ§λ€κΈ° (popup.js)
`popup.js`λΌλ νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μΆκ°νμΈμ:
document.addEventListener('DOMContentLoaded', () => {
const urlDisplay = document.getElementById('url');
// νμ¬ νμ URL κ°μ Έμ€κΈ°
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const tab = tabs[0];
urlDisplay.textContent = tab.url;
});
});
μ€λͺ :
- μ€ν¬λ¦½νΈλ `DOMContentLoaded` μ΄λ²€νΈλ₯Ό μμ ν©λλ€.
- `chrome.tabs.query()`λ₯Ό μ¬μ©νμ¬ νμ¬ μ°½μ νμ± νμ κ°μ Έμ΅λλ€.
- νμ URLμ κ²μνμ¬ `url` λ¨λ½μ νμν©λλ€.
λΈλΌμ°μ μμ νμ₯ νλ‘κ·Έλ¨μ λ€μ λ‘λνμΈμ. μ΄μ νμ μ μ΄λ©΄ νμ¬ νμ URLμ΄ νμλ©λλ€.
λ°±κ·ΈλΌμ΄λ μ€ν¬λ¦½νΈμ μλΉμ€ μ컀
Manifest V3μμλ λ°±κ·ΈλΌμ΄λ μ€ν¬λ¦½νΈκ° μλΉμ€ μμ»€λ‘ λ체λ©λλ€. μλΉμ€ μ컀λ μꡬμ μΈ νμ΄μ§ μμ΄ λ°±κ·ΈλΌμ΄λμμ μ€νλλ μ΄λ²€νΈ κΈ°λ° μ€ν¬λ¦½νΈμ λλ€. λ°±κ·ΈλΌμ΄λ νμ΄μ§λ³΄λ€ λ ν¨μ¨μ μ΄κ³ 리μμ€λ₯Ό μ κ² μλͺ¨ν©λλ€.
μλΉμ€ μ컀μ μ£Όμ νΉμ§:
- μ΄λ²€νΈ κΈ°λ°: μλΉμ€ μ컀λ λΈλΌμ°μ μ‘μ , μλ, μ½ν μΈ μ€ν¬λ¦½νΈλ‘λΆν°μ λ©μμ§μ κ°μ μ΄λ²€νΈμ μλ΅ν©λλ€.
- λΉλκΈ°: μλΉμ€ μ컀λ λ©μΈ μ€λ λλ₯Ό μ°¨λ¨νμ§ μκΈ° μν΄ λΉλκΈ° APIλ₯Ό μ¬μ©ν©λλ€.
- μ ν΄ μνμΌ λ μ’ λ£: μλΉμ€ μ컀λ μ΄λ²€νΈλ₯Ό μ κ·Ήμ μΌλ‘ μ²λ¦¬νμ§ μμ λ μ’ λ£λμ΄ λ¦¬μμ€λ₯Ό μ μ½ν©λλ€.
μμ : μλΉμ€ μ컀 μ¬μ©νκΈ°
λΈλΌμ°μ κ° μμλ λ μλ¦Όμ νμνλ νμ₯ νλ‘κ·Έλ¨μ λ§λ€μ΄ λ΄ μλ€.
1. λ§€λνμ€νΈ νμΌ μ λ°μ΄νΈνκΈ° (manifest.json)
`manifest.json`μ λ€μ λ΄μ©μΌλ‘ μ λ°μ΄νΈνμΈμ:
{
"manifest_version": 3,
"name": "Service Worker Example",
"version": "1.0",
"description": "An extension that uses a service worker",
"permissions": [
"notifications"
],
"background": {
"service_worker": "background.js"
},
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
}
μ€λͺ :
- `"background"` μμ±μ μλΉμ€ μ컀 μ€ν¬λ¦½νΈ(`background.js`)μ κ²½λ‘λ₯Ό μ§μ ν©λλ€.
- `"permissions"` λ°°μ΄μλ μλ¦Όμ νμνλ λ° νμν `"notifications"`κ° ν¬ν¨λ©λλ€.
2. μλΉμ€ μ컀 μ€ν¬λ¦½νΈ λ§λ€κΈ° (background.js)
`background.js`λΌλ νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μΆκ°νμΈμ:
chrome.runtime.onStartup.addListener(() => {
// λΈλΌμ°μ κ° μμλ λ μλ¦Ό νμ
chrome.notifications.create('startup-notification', {
type: 'basic',
iconUrl: 'images/icon48.png',
title: 'Browser Started',
message: 'The browser has started.',
});
});
μ€λͺ :
- μ€ν¬λ¦½νΈλ λΈλΌμ°μ κ° μμλ λ νΈλ¦¬κ±°λλ `chrome.runtime.onStartup` μ΄λ²€νΈλ₯Ό μμ ν©λλ€.
- `chrome.notifications.create()`λ₯Ό μ¬μ©νμ¬ μ§μ λ μμ±μΌλ‘ μλ¦Όμ νμν©λλ€.
λΈλΌμ°μ μμ νμ₯ νλ‘κ·Έλ¨μ λ€μ λ‘λνμΈμ. μ΄μ λΈλΌμ°μ λ₯Ό λ€μ μμνλ©΄ νμ₯ νλ‘κ·Έλ¨μμ λ³΄λΈ μλ¦Όμ΄ νμλ©λλ€.
μ½ν μΈ μ€ν¬λ¦½νΈ
μ½ν μΈ μ€ν¬λ¦½νΈλ μΉ νμ΄μ§μ 컨ν μ€νΈμμ μ€νλλ μλ°μ€ν¬λ¦½νΈ νμΌμ λλ€. μΉ νμ΄μ§μ DOMμ μ κ·Όνκ³ μμ ν μ μμ΄ μΉμ¬μ΄νΈμ λμκ³Ό λͺ¨μμ μ¬μ©μ μ μν μ μμ΅λλ€.
μ½ν μΈ μ€ν¬λ¦½νΈμ μ£Όμ νΉμ§:
- DOM μ κ·Ό: μ½ν μΈ μ€ν¬λ¦½νΈλ μΉ νμ΄μ§μ DOMμ μ κ·Όνκ³ μ‘°μν μ μμ΅λλ€.
- μΉ νμ΄μ§ μ€ν¬λ¦½νΈλ‘λΆν°μ 격리: μ½ν μΈ μ€ν¬λ¦½νΈλ 격리λ νκ²½μμ μ€νλμ΄ μΉ νμ΄μ§ μ€ν¬λ¦½νΈμμ μΆ©λμ λ°©μ§ν©λλ€.
- λ°±κ·ΈλΌμ΄λ μ€ν¬λ¦½νΈμμ ν΅μ : μ½ν μΈ μ€ν¬λ¦½νΈλ λ©μμ§ μ λ¬μ μ¬μ©νμ¬ λ°±κ·ΈλΌμ΄λ μ€ν¬λ¦½νΈμ ν΅μ ν μ μμ΅λλ€.
μμ : μ½ν μΈ μ€ν¬λ¦½νΈ μ¬μ©νκΈ°
μΉ νμ΄μ§μ λ°°κ²½μμ νλμμΌλ‘ λ³κ²½νλ νμ₯ νλ‘κ·Έλ¨μ λ§λ€μ΄ λ΄ μλ€.
1. λ§€λνμ€νΈ νμΌ μ λ°μ΄νΈνκΈ° (manifest.json)
`manifest.json`μ λ€μ λ΄μ©μΌλ‘ μ λ°μ΄νΈνμΈμ:
{
"manifest_version": 3,
"name": "Content Script Example",
"version": "1.0",
"description": "An extension that uses a content script",
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": [""],
"js": ["content.js"]
}
],
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
}
μ€λͺ :
- `"content_scripts"` μμ±μ μΉ νμ΄μ§μ μ£Όμ λ μ½ν μΈ μ€ν¬λ¦½νΈμ λ°°μ΄μ μ§μ ν©λλ€.
- `"matches"`λ μ½ν
μΈ μ€ν¬λ¦½νΈκ° μ£Όμ
λ URLμ μ§μ ν©λλ€ (`
`λ λͺ¨λ URLκ³Ό μΌμΉ). - `"js"`λ μ½ν μΈ μ€ν¬λ¦½νΈ(`content.js`)μ κ²½λ‘λ₯Ό μ§μ ν©λλ€.
- `"permissions"` λ°°μ΄μλ μ€ν¬λ¦½νΈλ₯Ό μ£Όμ νλ λ° νμν `"activeTab"`κ³Ό `"scripting"`μ΄ ν¬ν¨λ©λλ€.
2. μ½ν μΈ μ€ν¬λ¦½νΈ λ§λ€κΈ° (content.js)
`content.js`λΌλ νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μΆκ°νμΈμ:
document.body.style.backgroundColor = 'lightblue';
3. μλΉμ€ μ컀 λ§λ€κΈ° (background.js)
`background.js`λΌλ νμΌμ λ§λ€κ³ λ€μ μ½λλ₯Ό μΆκ°νμΈμ:
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: () => {
document.body.style.backgroundColor = 'lightblue';
}
});
});
μ€λͺ :
- μ½ν μΈ μ€ν¬λ¦½νΈλ `body` μμμ λ°°κ²½μμ λ¨μν νλμμΌλ‘ μ€μ ν©λλ€.
- μλΉμ€ μ컀λ ν΄λ¦ μ΄λ²€νΈλ₯Ό μμ νκ³ νμ¬ ν λ΄μμ λ°°κ²½μμ λ³κ²½νλ ν¨μλ₯Ό μ€νν©λλ€.
λΈλΌμ°μ μμ νμ₯ νλ‘κ·Έλ¨μ λ€μ λ‘λνμΈμ. μ΄μ μ΄λ€ μΉ νμ΄μ§λ₯Ό μ΄λ λ°°κ²½μμ΄ νλμμΌλ‘ λ°λλλ€.
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ λλ²κΉ νκΈ°
λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ λλ²κΉ νλ κ²μ κ°λ° κ³Όμ μ νμμ μΈ λΆλΆμ λλ€. Chromeκ³Ό Firefoxλ νμ₯ νλ‘κ·Έλ¨ λλ²κΉ μ μν νλ₯ν κ°λ°μ λꡬλ₯Ό μ 곡ν©λλ€.
Chromeμμ λλ²κΉ νκΈ°:
- Chromeμ μ΄κ³ `chrome://extensions`λ‘ μ΄λν©λλ€.
- μ€λ₯Έμͺ½ μλ¨μμ "κ°λ°μ λͺ¨λ"λ₯Ό νμ±νν©λλ€.
- νμ₯ νλ‘κ·Έλ¨μ "Inspect views background page"(λ°±κ·ΈλΌμ΄λ νμ΄μ§ κ²μ¬)λ₯Ό ν΄λ¦ν©λλ€. κ·Έλ¬λ©΄ λ°±κ·ΈλΌμ΄λ μ€ν¬λ¦½νΈμ λν Chrome DevToolsκ° μ΄λ¦½λλ€.
- μ½ν μΈ μ€ν¬λ¦½νΈλ₯Ό λλ²κΉ νλ €λ©΄ μ½ν μΈ μ€ν¬λ¦½νΈκ° μ£Όμ λ μΉ νμ΄μ§λ₯Ό μ΄κ³ ν΄λΉ νμ΄μ§μ λν Chrome DevToolsλ₯Ό μ½λλ€. "Sources"(μμ€) ν¨λμ μ½ν μΈ μ€ν¬λ¦½νΈκ° λμ΄λ κ²μ λ³Ό μ μμ΅λλ€.
Firefoxμμ λλ²κΉ νκΈ°:
- Firefoxλ₯Ό μ΄κ³ `about:debugging#/runtime/this-firefox`λ‘ μ΄λν©λλ€.
- λͺ©λ‘μμ νμ₯ νλ‘κ·Έλ¨μ μ°Ύμ "Inspect"(κ²μ¬)λ₯Ό ν΄λ¦ν©λλ€. κ·Έλ¬λ©΄ νμ₯ νλ‘κ·Έλ¨μ λν Firefox κ°λ°μ λκ΅¬κ° μ΄λ¦½λλ€.
- μ½ν μΈ μ€ν¬λ¦½νΈλ₯Ό λλ²κΉ νλ €λ©΄ μ½ν μΈ μ€ν¬λ¦½νΈκ° μ£Όμ λ μΉ νμ΄μ§λ₯Ό μ΄κ³ ν΄λΉ νμ΄μ§μ λν Firefox κ°λ°μ λꡬλ₯Ό μ½λλ€. "Debugger"(λλ²κ±°) ν¨λμ μ½ν μΈ μ€ν¬λ¦½νΈκ° λμ΄λ κ²μ λ³Ό μ μμ΅λλ€.
μΌλ°μ μΈ λλ²κΉ κΈ°μ :
- μ½μ λ‘κΉ : `console.log()`λ₯Ό μ¬μ©νμ¬ μ½μμ λ©μμ§λ₯Ό μΆλ ₯ν©λλ€.
- μ€λ¨μ (Breakpoints): μ½λμ μ€λ¨μ μ μ€μ νμ¬ μ€νμ μΌμ μ€μ§νκ³ λ³μλ₯Ό κ²μ¬ν©λλ€.
- μμ€ λ§΅(Source maps): μ½λκ° μΆμλκ±°λ νΈλμ€νμΌλμλλΌλ μμ€ λ§΅μ μ¬μ©νμ¬ μλ³Έ ννλ‘ μ½λλ₯Ό λλ²κΉ ν©λλ€.
- μ€λ₯ μ²λ¦¬: μ€λ₯λ₯Ό ν¬μ°©νκ³ κΈ°λ‘νκΈ° μν΄ μ€λ₯ μ²λ¦¬λ₯Ό ꡬνν©λλ€.
νμ₯ νλ‘κ·Έλ¨ κ²μνκΈ°
νμ₯ νλ‘κ·Έλ¨μ κ°λ°νκ³ ν μ€νΈν νμλ Chrome μΉ μ€ν μ΄λ Firefox λΆκ° κΈ°λ₯ λ§μΌνλ μ΄μ€μ κ²μν μ μμ΅λλ€.
Chrome μΉ μ€ν μ΄μ κ²μνκΈ°:
- Chrome μΉ μ€ν μ΄μμ κ°λ°μ κ³μ μ λ§λλλ€.
- νμ₯ νλ‘κ·Έλ¨μ `.zip` νμΌλ‘ ν¨ν€μ§ν©λλ€.
- `.zip` νμΌμ Chrome μΉ μ€ν μ΄μ μ λ‘λν©λλ€.
- νμ₯ νλ‘κ·Έλ¨μ μ΄λ¦, μ€λͺ , μ€ν¬λ¦°μ·κ³Ό κ°μ νμ λ©νλ°μ΄ν°λ₯Ό μ 곡ν©λλ€.
- κ²ν λ₯Ό μν΄ νμ₯ νλ‘κ·Έλ¨μ μ μΆν©λλ€.
Firefox λΆκ° κΈ°λ₯ λ§μΌνλ μ΄μ€μ κ²μνκΈ°:
- Firefox λΆκ° κΈ°λ₯ λ§μΌνλ μ΄μ€μμ κ°λ°μ κ³μ μ λ§λλλ€.
- νμ₯ νλ‘κ·Έλ¨μ `.zip` νμΌλ‘ ν¨ν€μ§ν©λλ€.
- `.zip` νμΌμ Firefox λΆκ° κΈ°λ₯ λ§μΌνλ μ΄μ€μ μ λ‘λν©λλ€.
- νμ₯ νλ‘κ·Έλ¨μ μ΄λ¦, μ€λͺ , μ€ν¬λ¦°μ·κ³Ό κ°μ νμ λ©νλ°μ΄ν°λ₯Ό μ 곡ν©λλ€.
- κ²ν λ₯Ό μν΄ νμ₯ νλ‘κ·Έλ¨μ μ μΆν©λλ€.
κ²μλ₯Ό μν λͺ¨λ² μ¬λ‘:
- νμ₯ νλ‘κ·Έλ¨μ λν λͺ ννκ³ κ°κ²°ν μ€λͺ μ μμ±ν©λλ€.
- νμ₯ νλ‘κ·Έλ¨μ κΈ°λ₯μ 보μ¬μ£ΌκΈ° μν΄ κ³ νμ§ μ€ν¬λ¦°μ·κ³Ό λΉλμ€λ₯Ό μ 곡ν©λλ€.
- μ μΆνκΈ° μ μ νμ₯ νλ‘κ·Έλ¨μ μ² μ ν ν μ€νΈν©λλ€.
- μ¬μ©μ 리뷰μ νΌλλ°±μ μ μνκ² μλ΅ν©λλ€.
- μ΅μ λΈλΌμ°μ λ²μ λ° λ³΄μ ν¨μΉμ λ§μΆ° νμ₯ νλ‘κ·Έλ¨μ μ΅μ μνλ‘ μ μ§ν©λλ€.
보μ κ³ λ € μ¬ν
보μμ λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ κ°λ°μ μ€μν μΈ‘λ©΄μ λλ€. νμ₯ νλ‘κ·Έλ¨μ λ―Όκ°ν μ¬μ©μ λ°μ΄ν°μ μ κ·Όνκ³ μΉ νμ΄μ§ μ½ν μΈ λ₯Ό μμ ν μ μμΌλ―λ‘, μ¬μ©μλ₯Ό μ μ± μ½λλ‘λΆν° 보νΈνκΈ° μν΄ λ³΄μ λͺ¨λ² μ¬λ‘λ₯Ό λ°λ₯΄λ κ²μ΄ νμμ μ λλ€.
μ£Όμ 보μ κ³ λ € μ¬ν:
- κΆν μ΅μν: νμ₯ νλ‘κ·Έλ¨μ΄ μ€μ λ‘ νμν κΆνλ§ μμ²ν©λλ€.
- μ¬μ©μ μ λ ₯ κ²μ¦: κ΅μ°¨ μ¬μ΄νΈ μ€ν¬λ¦½ν (XSS) 곡격μ λ°©μ§νκΈ° μν΄ λͺ¨λ μ¬μ©μ μ λ ₯μ μ μ νκ³ κ²μ¦ν©λλ€.
- HTTPS μ¬μ©: μ격 μλ²μ ν΅μ ν λλ νμ HTTPSλ₯Ό μ¬μ©ν©λλ€.
- μ½ν μΈ λ³΄μ μ μ± (CSP): μμμ μ½λ μ€νμ λ°©μ§νκΈ° μν΄ μ격ν CSPλ₯Ό μνν©λλ€.
- μ κΈ°μ μΈ νμ₯ νλ‘κ·Έλ¨ μ λ°μ΄νΈ: μ΅μ 보μ ν¨μΉλ‘ νμ₯ νλ‘κ·Έλ¨μ μ΅μ μνλ‘ μ μ§ν©λλ€.
μ΄λ¬ν 보μ μ§μΉ¨μ λ°λ₯΄λ©΄ λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ΄ μ¬μ©μλ₯Ό μν΄ μμ νκ³ λ³΄μμ΄ μ μ§λλλ‘ λμΈ μ μμ΅λλ€.
κ²°λ‘
Manifest V3μ μλ°μ€ν¬λ¦½νΈ APIλ₯Ό μ¬μ©ν λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨ κ°λ°μ λΈλΌμ°μ§ κ²½νμ λ§μΆ€ μ€μ νκ³ μΉ λΈλΌμ°μ μ μλ‘μ΄ κΈ°λ₯μ μΆκ°νλ κ°λ ₯ν λ°©λ²μ μ 곡ν©λλ€. μ΄ κ°μ΄λμμ μ€λͺ ν ν΅μ¬ κ°λ , API λ° λͺ¨λ² μ¬λ‘λ₯Ό μ΄ν΄ν¨μΌλ‘μ¨, μμ°μ±μ ν₯μμν€κ³ 보μμ κ°μ νλ©° μ μΈκ³ μ¬μ©μμκ² λ λμ λΈλΌμ°μ§ κ²½νμ μ 곡νλ κ°λ ₯νκ³ μμ ν νμ₯ νλ‘κ·Έλ¨μ λ§λ€ μ μμ΅λλ€. μΉμ΄ κ³μ μ§νν¨μ λ°λΌ λΈλΌμ°μ νμ₯ νλ‘κ·Έλ¨μ μ¨λΌμΈ μνΈ μμ©μ λ―Έλλ₯Ό νμ±νλ λ° μ μ λ μ€μν μν μ ν κ²μ λλ€. Manifest V3μ νλΆν μλ°μ€ν¬λ¦½νΈ APIκ° μ 곡νλ κΈ°νλ₯Ό λ°μλ€μ¬ νμ μ μ΄κ³ κ°μΉ μλ νμ₯ νλ‘κ·Έλ¨μ ꡬμΆνμμμ€.