Make Chrome Extension - manifest.json
π§ ν¬λ‘¬ μ΅μ€ν μ ꡬ쑰 κ°λ μ 리
ν¬λ‘¬ μ΅μ€ν μ μ κΈ°λ³Έμ μΌλ‘ μΉ κΈ°μ λ‘ λ§λ€ μ μλ μμ μ±μ΄λ€.
κΈ°λ³Έμ μΈ κ΅¬μ± μμλ λ€μκ³Ό κ°λ€.
- mainfest.json : μ΅μ€ν μ μ€μ νμΌ (νμ) (μ΄ νμΌμ΄ μμ΄μΌ ν¬λ‘¬ μ΅μ€ν μ μΌλ‘ μΈμν μ μλ€.)
- popup : ν¬λ‘¬ ν΄λ°μμ μμ΄μ½μ ν΄λ¦νλ©΄ λμ€λ UI
- background script : λ°±κ·ΈλΌμ΄λμμ κ³μ λμνλ JS
- content script : μΉ νμ΄μ§μ μ½μ λλ JS
- options page : μ¬μ©μ μ€μ νμ΄μ§
- permissions : μ΄λ€ κΈ°λ₯μ μ¬μ©ν μ§ μ€μ (μ: ν μ κ·Ό, μ€ν 리μ§)
μμ)
{
"manifest_version": 3, // λ²μ 3 μ¬μ© (λ²μ 2λ μ§μ μ’
λ£)
"name": "My First Extension", // μ΅μ€ν
μ
μ΄λ¦
"version": "0.1.0", // νμ¬ λ²μ (μ± μ²λΌ κ΄λ¦¬λ¨)
"description": "This is a beginner-friendly Chrome extension.", // μ΅μ€ν
μ
μ€λͺ
"icons": { // νμ₯ νλ‘κ·Έλ¨ μμ΄μ½ νμΌ κ²½λ‘
"16": "assets/icon-16.png",
"48": "assets/icon-48.png",
"128": "assets/icon-128.png"
},
"action": { // ν¬λ‘¬ ν΄λ°μμ ν΄λ¦νμ λ λμ€λ νμ
μ€μ
"default_popup": "src/popup.html", // μμ΄μ½ ν΄λ¦ μ νμλ HTML νμΌ κ²½λ‘
"default_icon": "assets/icon-48.png" // μμ΄μ½ νμΌ κ²½λ‘
},
"background": {
"service_worker": "src/background.js" // λ°±κ·ΈλΌμ΄λμμ κ³μ μ€νλλ μ€ν¬λ¦½νΈ
},
"permissions": ["storage", "tabs"], // μ΅μ€ν
μ
μ΄ μ¬μ©νλ €λ κΈ°λ₯λ€
// storage: λ°μ΄ν° μ μ₯ , tabs: ν μ‘°μ
"host_permissions": ["https://example.com/*"], // νΉμ λλ©μΈ μ κ·Ό κΆν μ€μ
"content_scripts": [ // μΉ νμ΄μ§μ μ½μ
λλ JS μ€μ
{
"matches": ["https://*/*"], // μ΄λ€ URLμμ μ½ν
μΈ μ€ν¬λ¦½νΈλ₯Ό μ€νν μ§ λͺ
μ
"js": ["src/content.js"] // μ€νν μλ°μ€ν¬λ¦½νΈ νμΌ κ²½λ‘
}
]
}
π§© μ popup.htmlμ μ¨μΌ ν κΉ?
λλ React λ‘ νλ‘μ νΈλ₯Ό μμ±νκΈ° λλ¬Έμ, λ΄ κ²½μ° src/Popup.tsx μμ νμ μ»΄ν¬λνΈλ₯Ό μμ±ν΄λμλ€.
κ·Έλ°λ°, ν¬λ‘¬ μ΅μ€ν μ μ default_popupμ HTML νμΌ κ²½λ‘λ§ λ°μ μ μλ€κ³ νλ€.
React μ»΄ν¬λνΈ(popup.tsx)λ λΈλΌμ°μ κ° μ§μ μ΄ν΄ν μ μκΈ° λλ¬Έμ, λ°λμ HTMLλ‘ κ°μΈμ€μΌ νλ€.
μ¦, popup.tsxλ μ§μ λ£μ μ μκ³ ,
"action": {
"default_popup": "popup.html"
}
μ΄λ° μμΌλ‘ μ¨μΌ νκ³ , popup.html μμμ React μ±(popup.tsx)μ λ§μ΄νΈνλ λ°©μμΌλ‘ ν΄κ²°ν μ μλ€.
π ꡬ쑰 μμ
src/
βββ popup.tsx
βββ popup.html
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Popup</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/popup.tsx"></script>
</body>
</html>
popup.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
function Popup() {
return <div className="text-xl text-blue-500">Hello from Popup!</div>
}
const root = document.getElementById('root')!
ReactDOM.createRoot(root).render(<Popup />)
π Vite μ€μ ν
Viteλ κΈ°λ³Έμ μΌλ‘ index.htmlμ κΈ°μ€μΌλ‘ μλνμ§λ§, μ¬λ¬ κ°μ entry HTMLμ λ§λ€ μ μλ€.
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
export default defineConfig({
plugins: [react()],
build: {
rollupOptions: {
input: {
popup: resolve(__dirname, 'src/popup.html'),
// background μ€ν¬λ¦½νΈλ content scriptλ entryλ§ λ±λ‘ν΄μ€λ λ¨
},
output: {
// ν΄λ ꡬ쑰 κΉλνκ² μ 리νκ³ μΆλ€λ©΄ μ¬κΈ°μ μ‘°μ
}
},
outDir: 'dist',
},
})
π λλ²κΉ νλ λ°©λ²
π κ°μ΄λ
- 리μ‘νΈλ‘ κ°λ°νκ³ μλ€λ©΄, build ν, dist/ ν΄λμλ manifest.jsonμ 볡μ¬νλ€.
- ν¬λ‘¬ μ£Όμμ°½μ chrome://extensionsλ₯Ό μ λ ₯νλ€.

- "κ°λ°μ λͺ¨λ"λ₯Ό νμ±ννλ€.

- "μμΆν΄μ λ νμ₯ νλ‘κ·Έλ¨μ λ‘λν©λλ€" λ²νΌμ ν΄λ¦νλ€. (Load unpacked λ²νΌ ν΄λ¦)
- νλ‘μ νΈ ν΄λλ₯Ό μ ννλ€. (λ‘컬 λλ°μ΄μ€μ dist ν΄λ κ²½λ‘λ₯Ό μ°Ύμμ μ
λ‘λν΄ μ€λ€. )
- μ μμ μΌλ‘ λ‘λλμλ€λ©΄ ν΄λ°μ μμ΄μ½μ΄ λνλ κ²μ΄λ€.
π μ°Έκ³ μ¬ν
backgroundμ content_scriptsλ κ°κ° λ³λμ λλ²κΉ μ½μμ κ°μ§λ€.