May 4, 2024 ˑ 13min read
이전 글에서는 확장 프로그램의 구성과 확장 프로그램의 백엔드 역할을 담당하는 백그라운드 스크립트에 대해 알아보았습니다. 이번 글에서는 유저 인터페이스를 통해 사용자와 상호 작용할 수 있는 확장 프로그램의 구성 요소에 대해 알아보려고 합니다.
Note글에서 소개하는 manifest.json 작성은 MV3을 기준으로 합니다.
백그라운드 스크립트가 모든 Chrome Extension API에 접근가능한 이유로 브라우저 기능을 제공하는 백엔드 역할을 했다면, 반대로 유저 인터페이스를 통해 사용자와 상호작용하는 프론트엔드 역할을 하는 요소들이 있습니다.
크롬 확장 프로그램의 UI 요소로는 브라우저 액션(Browser Action)과 팝업, 컨텐츠 스크립트(Content Script), 옵션 페이지(Options Page) 와 같이 CSS, JavaScript로 구성가능한 요소와 브라우저 자체 UI 요소인 시스템 알림(Notification), 컨텍스트 메뉴(Context Menu — 우클릭 메뉴) 등이 있습니다. 주로 사용되는 구성요소 몇가지에 대해 알아보겠습니다.
브라우저 액션은 브라우저 주소창 옆 툴바 영역에 있는 액션 아이콘을 클릭하면 발생하는 이벤트입니다. 아이콘을 클릭하게되면 팝업이나 사이드 패널을 표시하거나, 특정 Javascript 코드를 실행하거나, 새로운 탭/창을 열 수 있습니다. 필요에 따라서 아이콘 옆에 뱃지를 노출할 수 있고 간단한 숫자를 표기 하거나 마우스 호버시 노출할 툴팁을 구성할 수 있습니다.
브라우저 액션은 manifest.json의 action
키를 통해 설정할 수 있습니다.
{
...
"action": {
"default_icon": { // 아이콘 이미지 (여러 크기 제공 권장)
"16": "images/icon16.png",
"24": "images/icon24.png",
"32": "images/icon32.png"
},
"default_title": "My Extension", // 툴팁 (마우스 호버 시 표시)
"default_popup": "popup.html" // 클릭 시 팝업 열기 (선택 사항)
},
}
브라우저 액션을 통해 팝업을 노출하고 싶은 경우 action.default_popup
을 통해 팝업을 구성할 HTML 파일을 작성합니다. 해당 키를 통해 팝업이 구성되지 않은 경우 아이콘 클릭시 chrome.action.onClicked
이벤트가 발생합니다.
팝업은 사용자가 열고 닫을 수 있는 UI로 짧은 라이프 사이클을 갖기 때문에 간단한 로직을 위주로 구성하는게 좋습니다.
컨텐츠 스크립트는 확장 프로그램의 구성요소 중 웹 페이지와 상호작용할 수 있는 스크립트입니다.
컨텐츠 스크립트는 웹 페이지와 함께 로드되어 window 컨텍스트에서 실행되기 때문에 웹 페이지의 DOM
을 조작한다거나 window
객체에 접근하는 등 Web API를 사용할 수 있기 떄문에 다양한 기능을 구현할 수 있습니다.
다만 컨텐츠 스크립트가 웹 페이지에 로드되기 위해서는 manifest.json의 content_scripts.matches
키에 URL 패턴을 명시해야하며, 스크립트를 통해 웹 페이지에 접근하기 위해서는 host_permissions
이 필요합니다.
{
...
"host_permissions": ["https://example.com/*"],
"content_scripts": [
{
"matches": ["https://example.com/*"],
"js": ["content.js"]
}
]
}
컨텐츠 스크립트가 웹 페이지에 접근할 수 있다는 점에서 페이지 스크립트와 동일하게 보일 수 있지만 몇가지 차이점이 있습니다.
Note월드(World)를 통한 격리
크롬 브라우저는 확장 프로그램의 컨텐츠 스크립트와 웹 페이지의 스크립트가 서로 간접하지 않도록 격리하는 구조를 제공합니다. 이러한 격리된 환경을 월드라고 부르며 다음과 같은 특징이 있습니다.
- 월드는 세가지 종류가 있으며 메인 월드, 격리된 월드, 워커 월드가 있습니다.
- 이 중에서 페이지 스크립트는 메인 월드에서, 컨텐츠 스크립트는 격리된 월드에서 실행됩니다.
- 각 월드는 자체 컨텍스트를 갖으며, 글로벌 스코프와 프로토 타입 체인을 갖습니다.
- 대신 메인 월드와 격리된 월드는 웹페이지의 DOM 트리를 공유합니다.
컨텐츠 스크립트는 다음과 같은 방법으로 로드할 수 있습니다.
manifest.json
의 content_scripts
키를 통해 등록.특정 페이지에서 실행되어야 하는 경우에 사용될 수 있습니다. content_scripts.matches
키를 통해 스크립트를 로드할 URL 패턴을 지정할 수 있습니다.
{
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
// content script를 등록
chrome.scripting.registerContentScripts([{
id: 'content-script-1'
js: ["content.js"],
runAt: 'document_start',
matches: ['<all_urls>']
}]);
// 등록된 content script를 조회
chrome.scripting.getRegisteredContentScripts(['content-script-1', 'content-script-2'])
// 등록된 content script를 업데이트
chrome.scripting
.updateContentScripts([{
id: "content-script-1",
excludeMatches: ["*://admin.example.com/*"],
}])
// 등록된 content script를 제거
chrome.scripting
.unregisterContentScripts(['content-script-1', 'content-script-2'])
이벤트에 대한 응답이나 특정 상황에 실행되어야하는 경우 프로그래밍 방식을 사용할 수 있습니다. 프로그래밍 방식으로 컨텐츠 스크립트를 주입하기 위해서는 host_permissions이 필요합니다. 또는, activeTab 권한을 통해 일시적으로 컨텐츠 스크립트를 주입할 수 있는 권한을 획득할 수 있습니다.
NoteactiveTab 권한은 사용자가 명시적으로 확장 프로그램의 기능을 호출하였을 때, 호출한 탭에 대해서 확장 프로그램이 제한적인 접근 권한을 얻을 수 있도록 하는 권한을 의미합니다.
아래 예시는 팝업이 없이 브라우저 액션을 등록한 뒤, onClick 이벤트 핸들러를 통해 사용자가 아이콘을 클릭할 때 컨텐츠 스크립트를 주입하는 방법입니다.
{
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button" // 브라우저 액션을 등록
}
}
/**
* 1. 파일을 통해 주입하는 방법
*/
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"]
});
});
/**
* 2. 코드를 통해 주입하는 방법
*/
const injectedFunction = (color) => {
document.body.style.backgroundColor = color;
}
/**
* 코드를 통해 주입하게 되는 경우 `chrome.scripting.executeScript` API는 주입된 코드는 그 자체가 아닌 참조를 통해 복사한다는 점에 유의해야 합니다.
* 만약 함수 외부의 변수를 참조하게 되는 경우 `ReferenceError`가 발생할 수 있습니다.
*/
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target : {tabId : tab.id},
func : injectedFunction,
args : [ "orange" ],
});
});
사이드 패널은 비교적 최근인 114 버전 이상에서 제공되는 UI 요소입니다. 사이드 패널은 사용자가 보고있는 페이지와 함께 표시될 수 있는 보조 영역을 구성하는데 사용됩니다. 이러한 특징으로 팝업, 새 탭과 달리 사용자의 작업을 방해하지 않으면서도 페이지와 함께 사용될 수 있는 장점을 갖습니다. 이외에도, 사이드 패널은 확장 페이지로써 모든 Chrome Extension API에 접근 가능한 특징을 갖으며, 설정에 따라 탭 이동간에도 열려있도록 구성할 수 있습니다.
chrome.sidePanel
API를 통해 사이드 패널을 생성하고 관리할 수 있습니다.
사이드 패널은 manifest.json의 side_panel
키를 통해 구성할 수 있습니다.
{
...
"side_panel": {
"default_path": "sidepanel.html"
}
}
사이즈 패널이 열리도록 하는 방법은 다양하게 구성할 수 있는데요. 예를 들면, 탭 업데이트 이벤트를 통해 특정 웹 페이지에 접근했을때 열리도록 하거나, 브라우저 액션을 통해 열리도록 할 수 있습니다.
const TARGET_ORIGIN = 'https://www.example.com';
chrome.tabs.onUpdated.addListener(async (tabId, info, tab) => {
if (!tab.url) return;
const url = new URL(tab.url);
// example.com에 접속했을 때 사이드 패널 열기
if (url.origin === GOOGLE_ORIGIN) {
await chrome.sidePanel.setOptions({
tabId,
path: 'sidepanel.html',
enabled: true
});
} else {
// 다른 페이지에 접속했을 때 사이드 패널 닫기
await chrome.sidePanel.setOptions({
tabId,
enabled: false
});
}
});
{
...
"action": {
"default_title": "Action Button"
}
}
// 브라우저 액션 클릭 시 사이드 패널을 열도록 설정
chrome.sidePanel
.setPanelBehavior({ openPanelOnActionClick: true })
크롬 116버전에서 추가된 sidePanel.open()
API를 사용하면 프로그래밍 방식으로 원하는 시점에 사이드 패널을 열 수 있습니다.
아래 예시는 컨텍스트 메뉴에 추가한 메뉴를 클릭하였을 때, 사이드 패널이 열리도록 하는 방법입니다.
// 확장 프로그램이 설치되었을 때, 컨텍스트 메뉴에 "사이드 패널 열기" 메뉴 추가
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'open-side-panel',
title: '사이드 패널 열기',
context: ['all']
})
})
// 컨텍스트 메뉴의 클릭 이벤트가 발생하였을 때, 사이드 패널 열기
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === 'open-side-panel') {
chrome.sidePanel.open({ windowId: tab.windowId });
}
})
위에서 정리한 UI 요소 이외에도 크롬 확장프로그램으로 구성할 수 있는 요소는 다양합니다. 크롬 개발자 문서 에서는 구성하고자 하는 확장 프로그램에 필요한 더 많은 요소에 대한 정보를 알아볼 수 있습니다.
다음 글에서는 지금까지 알아본 크롬 확장 프로그램에 대한 구성을 토대로 프로젝트를 초기화하고, React.js와 Vite를 사용하여 확장 프로그램을 개발하는 방법에 대해 알아보겠습니다.
Chrome Extension
Mar 4, 2024
20 min read
크롬, 파이어폭스, 엣지, 오페라와 같은 주요 브라우저는 기능을 확장하거나 수정할 수 있는 확장 프로그램을 개발할 수 있는 환경과 API를 제공합니다. 확장 프로그램은 웹페이지의 UI를 변경하거나, 브라우저 이벤트를 감지하여 필요한 동작을 수행하는 등 다양한 응용이 가능한데요. 이번 글에서는 크롬 브라우저의 확장 프로그램을 개발하기에 앞서 확장 프로그램의 구성에 필요한 파일들과 그 역할에 대해 알아보려고 합니다.
Chrome Extension
May 4, 2024
12 min read
'React.js로 개발하는 크롬 확장 프로그램' 앞선 두 파트에서는 크롬 확장 프로그램을 구성하는 요소들에 대해 알아보았습니다. 이번 글에서는 Vite와 React.js를 이용하여 크롬 확장 프로그램 개발 환경을 구성하고, Chrome API를 사용하는 간단한 확장 프로그램을 만들어보겠습니다.