확장 프로그램 서비스 워커 개념을 다루는 튜토리얼입니다.
개요
이 튜토리얼에서는 Chrome 확장 프로그램 서비스 워커를 소개합니다. 이 튜토리얼에서는 사용자가 검색주소창을 사용하여 Chrome API 참조 페이지로 빠르게 이동할 수 있는 확장 프로그램을 빌드합니다. 다음을 수행하는 방법을 배우게 됩니다.
- 서비스 워커를 등록하고 모듈을 가져옵니다.
- 확장 프로그램 서비스 워커를 디버그합니다.
- 상태를 관리하고 이벤트를 처리합니다.
- 주기적인 이벤트를 트리거합니다.
- 콘텐츠 스크립트와 통신합니다.
시작하기 전에
이 가이드에서는 기본적인 웹 개발 경험이 있다고 가정합니다. 확장 프로그램 개발에 관한 소개는 확장 프로그램 101 및 Hello World를 검토하는 것이 좋습니다.
확장 프로그램 빌드
먼저 확장 파일을 보관할 quick-api-reference
라는 새 디렉터리를 만듭니다. 또는
GitHub 샘플 저장소에서 소스 코드를 다운로드합니다.
1단계: 서비스 워커 등록
프로젝트의 루트에 매니페스트 파일을 만들고 다음 코드를 추가합니다.
manifest.json:
{
"manifest_version": 3,
"name": "Open extension API reference",
"version": "1.0.0",
"icons": {
"16": "images/icon-16.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "service-worker.js"
}
}
확장 프로그램은 매니페스트에 서비스 워커를 등록하며, 이때 단일 JavaScript 파일만 사용합니다.
웹페이지에서와 같이 navigator.serviceWorker.register()
를 호출할 필요는 없습니다.
images
폴더를 만든 다음 아이콘을 다운로드합니다.
매니페스트에 있는 확장 프로그램의 메타데이터 및 아이콘에 대해 자세히 알아보려면 읽기 시간 튜토리얼의 첫 번째 단계를 확인하세요.
2단계: 여러 서비스 워커 모듈 가져오기
서비스 워커는 두 가지 기능을 구현합니다. 유지보수성을 높이기 위해 각 기능을 별도의 모듈에 구현합니다. 먼저 매니페스트에서 서비스 워커를 ES 모듈로 선언해야 합니다. 그러면 서비스 워커에서 모듈을 가져올 수 있습니다.
manifest.json:
{
"background": {
"service_worker": "service-worker.js",
"type": "module"
},
}
service-worker.js
파일을 만들고 다음 두 모듈을 가져옵니다.
import './sw-omnibox.js';
import './sw-tips.js';
이러한 파일을 만들고 각 파일에 콘솔 로그를 추가합니다.
sw-omnibox.js:
console.log("sw-omnibox.js");
sw-tips.js:
console.log("sw-tips.js");
서비스 워커에서 여러 파일을 가져오는 다른 방법에 관해 알아보려면 스크립트 가져오기를 참고하세요.
선택사항: 서비스 워커 디버깅
서비스 워커 로그를 찾고 종료된 시점을 확인하는 방법을 설명하겠습니다. 먼저 안내에 따라 압축 해제된 확장 프로그램을 로드합니다.
30초 후에 '서비스 워커 (비활성)'가 표시됩니다. 서비스 워커가 종료되었음을 의미합니다 '서비스 워커(비활성)' 링크를 클릭하여 검사합니다. 다음 애니메이션은 이를 보여줍니다.
서비스 워커를 검사하다가 깨웠다는 걸 알아채셨나요? DevTools에서 서비스 워커를 열면 서비스 워커가 활성 상태로 유지됩니다. 서비스 워커가 종료될 때 확장 프로그램이 올바르게 작동하도록 하려면 DevTools를 닫으세요.
이제 확장 프로그램을 중단하여 오류가 있는 위치를 확인합니다. 이를 수행하는 한 가지 방법은 service-worker.js
파일의 './sw-omnibox.js'
가져오기에서 '.js'를 삭제하는 것입니다. Chrome에서 서비스 워커를 등록할 수 없습니다.
chrome://extensions로 돌아가 확장 프로그램을 새로고침합니다. 다음과 같은 두 가지 오류가 표시됩니다.
Service worker registration failed. Status code: 3.
An unknown error occurred when fetching the script.
확장 프로그램 서비스 워커를 디버그하는 다른 방법은 확장 프로그램 디버깅을 참고하세요.
4단계: 상태 초기화
Chrome은 서비스 워커가 필요하지 않은 경우 이를 종료합니다. chrome.storage
API를 사용하여 서비스 워커 세션 간에 상태를 유지합니다. 저장소 액세스의 경우 매니페스트에서 권한을 요청해야 합니다.
manifest.json:
{
...
"permissions": ["storage"],
}
먼저 스토리지에 기본 추천을 저장합니다. 확장 프로그램이 처음 설치될 때 runtime.onInstalled()
이벤트를 수신 대기하여 상태를 초기화할 수 있습니다.
sw-omnibox.js:
...
// Save default API suggestions
chrome.runtime.onInstalled.addListener(({ reason }) => {
if (reason === 'install') {
chrome.storage.local.set({
apiSuggestions: ['tabs', 'storage', 'scripting']
});
}
});
서비스 워커는 창 객체에 직접 액세스할 수 없으므로
window.localStorage
: 값을 저장합니다. 또한 서비스 워커는 수명이 짧은 실행 환경입니다. 서비스 워커는 사용자의 브라우저 세션 전체에서 반복적으로 종료되므로 전역 변수와 호환되지 않습니다. 대신 로컬 머신에 데이터를 저장하는 chrome.storage.local
를 사용하세요.
확장 프로그램 서비스 워커를 위한 다른 스토리지 옵션에 대해 알아보려면 전역 변수를 사용하는 대신 데이터 유지를 참조하세요.
5단계: 이벤트 등록
모든 이벤트 리스너는 서비스 워커의 전역 범위에 정적으로 등록되어야 합니다. 즉, 이벤트 리스너는 비동기 함수에 중첩되어서는 안 됩니다. 이렇게 하면 Chrome에서 서비스 워커가 재부팅되는 경우 모든 이벤트 핸들러가 복원되도록 할 수 있습니다.
이 예에서는 chrome.omnibox
API를 사용하지만 먼저 매니페스트에서 검색주소창 키워드 트리거를 선언해야 합니다.
manifest.json:
{
...
"minimum_chrome_version": "102",
"omnibox": {
"keyword": "api"
},
}
이제 스크립트 최상위 수준에서 omnibox 이벤트 리스너를 등록합니다. 사용자가 주소 표시줄에 검색주소창 키워드(api
)를 입력한 후 탭 또는 공백을 입력하면 Chrome에서 저장소의 키워드를 기반으로 추천 목록을 표시합니다. 현재 사용자 입력과 suggestResult
객체를 가져오는 onInputChanged()
이벤트가 이러한 추천을 채웁니다.
sw-omnibox.js:
...
const URL_CHROME_EXTENSIONS_DOC =
'https://developer.chrome.com/docs/extensions/reference/';
const NUMBER_OF_PREVIOUS_SEARCHES = 4;
// Display the suggestions after user starts typing
chrome.omnibox.onInputChanged.addListener(async (input, suggest) => {
await chrome.omnibox.setDefaultSuggestion({
description: 'Enter a Chrome API or choose from past searches'
});
const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');
const suggestions = apiSuggestions.map((api) => {
return { content: api, description: `Open chrome.${api} API` };
});
suggest(suggestions);
});
사용자가 추천을 선택하면 onInputEntered()
에 해당하는 Chrome API 참조 페이지가 열립니다.
sw-omnibox.js:
...
// Open the reference page of the chosen API
chrome.omnibox.onInputEntered.addListener((input) => {
chrome.tabs.create({ url: URL_CHROME_EXTENSIONS_DOC + input });
// Save the latest keyword
updateHistory(input);
});
updateHistory()
함수는 omnibox 입력을 가져와 storage.local
에 저장합니다. 이렇게 하면 최근 검색어를 나중에 검색주소창 추천 검색어로 사용할 수 있습니다.
sw-omnibox.js:
...
async function updateHistory(input) {
const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');
apiSuggestions.unshift(input);
apiSuggestions.splice(NUMBER_OF_PREVIOUS_SEARCHES);
return chrome.storage.local.set({ apiSuggestions });
}
6단계: 반복 일정 설정
setTimeout()
또는 setInterval()
메서드는 일반적으로 지연되거나 주기적인 작업을 수행하는 데 사용됩니다.
할 수 있습니다 그러나 서비스 작업자가 종료되면 스케줄러가 타이머를 취소하므로 이러한 API가 실패할 수 있습니다. 대신 확장 프로그램에서 chrome.alarms
API를 사용할 수 있습니다.
먼저 매니페스트에서 "alarms"
권한을 요청합니다. 또한 원격 호스팅 위치에서 확장 프로그램 도움말을 가져오려면 호스트 권한을 요청해야 합니다.
manifest.json:
{
...
"permissions": ["storage"],
"permissions": ["storage", "alarms"],
"host_permissions": ["https://extension-tips.glitch.me/*"],
}
확장 프로그램이 모든 도움말을 가져와 무작위로 하나를 선택하여 저장소에 저장합니다. 팁을 업데이트하기 위해 하루에 한 번 트리거되는 알람이 생성됩니다. Chrome을 닫으면 알람이 저장되지 않습니다. 따라서 알람이 있는지 확인하고 없는 경우 만들어야 합니다.
sw-tips.js:
// Fetch tip & save in storage
const updateTip = async () => {
const response = await fetch('https://extension-tips.glitch.me/tips.json');
const tips = await response.json();
const randomIndex = Math.floor(Math.random() * tips.length);
return chrome.storage.local.set({ tip: tips[randomIndex] });
};
const ALARM_NAME = 'tip';
// Check if alarm exists to avoid resetting the timer.
// The alarm might be removed when the browser session restarts.
async function createAlarm() {
const alarm = await chrome.alarms.get(ALARM_NAME);
if (typeof alarm === 'undefined') {
chrome.alarms.create(ALARM_NAME, {
delayInMinutes: 1,
periodInMinutes: 1440
});
updateTip();
}
}
createAlarm();
// Update tip once a day
chrome.alarms.onAlarm.addListener(updateTip);
7단계: 다른 컨텍스트와 통신
확장 프로그램은 콘텐츠 스크립트를 사용하여 페이지의 콘텐츠를 읽고 수정합니다. 사용자가 Chrome API 참조 페이지를 방문하면 확장 프로그램의 콘텐츠 스크립트가 최신 정보로 페이지를 업데이트합니다. 서비스 워커에 오늘의 도움말을 요청하는 메시지를 전송합니다.
먼저 매니페스트에서 콘텐츠 스크립트를 선언하고 Chrome API 참조 문서에 해당하는 일치 패턴을 추가합니다.
manifest.json:
{
...
"content_scripts": [
{
"matches": ["https://developer.chrome.com/docs/extensions/reference/*"],
"js": ["content.js"]
}
]
}
새 콘텐츠 파일을 만듭니다. 다음 코드는 서비스 워커에 팁을 요청하는 메시지를 보냅니다. 그런 다음 확장 프로그램 도움말이 포함된 팝오버를 여는 버튼을 추가합니다. 이 코드는 새로운 웹 플랫폼인 Popover API를 사용합니다.
content.js:
(async () => {
// Sends a message to the service worker and receives a tip in response
const { tip } = await chrome.runtime.sendMessage({ greeting: 'tip' });
const nav = document.querySelector('.upper-tabs > nav');
const tipWidget = createDomElement(`
<button type="button" popovertarget="tip-popover" popovertargetaction="show" style="padding: 0 12px; height: 36px;">
<span style="display: block; font: var(--devsite-link-font,500 14px/20px var(--devsite-primary-font-family));">Tip</span>
</button>
`);
const popover = createDomElement(
`<div id='tip-popover' popover style="margin: auto;">${tip}</div>`
);
document.body.append(popover);
nav.append(tipWidget);
})();
function createDomElement(html) {
const dom = new DOMParser().parseFromString(html, 'text/html');
return dom.body.firstElementChild;
}
마지막 단계는 일일 도움말이 포함된 답장을 콘텐츠 스크립트에 전송하는 메시지 핸들러를 서비스 워커에 추가하는 것입니다.
sw-tips.js:
...
// Send tip to content script via messaging
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.greeting === 'tip') {
chrome.storage.local.get('tip').then(sendResponse);
return true;
}
});
작동 여부 테스트
프로젝트의 파일 구조가 다음과 같은지 확인합니다.
로컬에서 확장 프로그램 로드
개발자 모드에서 압축해제된 확장 프로그램을 로드하려면 Hello world의 단계를 따르세요.
참조 페이지 열기
- 키워드 'api'를 입력하세요. 를 입력합니다.
- '탭' 또는 '스페이스'를 누릅니다.
- API의 전체 이름을 입력합니다.
- 또는 이전 검색 목록에서 선택합니다.
- Chrome API 참조 페이지가 새 페이지로 열립니다.
예를 들면 다음과 같습니다.
오늘의 팁 열기
탐색 메뉴에 있는 도움말 버튼을 클릭하여 확장 프로그램 도움말을 엽니다.
🎯 잠재적 개선사항
오늘 배운 내용을 바탕으로 다음 중 하나를 완료해 보세요.
- omnibox 추천을 구현하는 다른 방법을 살펴보세요.
- 확장 프로그램 도움말을 표시할 맞춤 모달을 만듭니다.
- MDN의 웹 확장 프로그램 참조 API 페이지에 대한 추가 페이지를 엽니다.
계속 빌드하세요!
이 튜토리얼을 완료하신 것을 축하합니다 🎉. 다른 초보자 튜토리얼을 완료하여 실력을 계속 키워 보세요.
확장 | 학습할 내용 |
---|---|
읽기 시간 | 특정 페이지 모음에 요소를 자동으로 삽입합니다. |
탭 관리자 | 브라우저 탭을 관리하는 팝업을 만듭니다. |
포커스 모드 | 확장 프로그램 작업을 클릭한 후 현재 페이지에서 코드를 실행합니다. |
계속 탐색하기
확장 프로그램 서비스 워커 학습 과정을 계속하려면 다음 도움말을 살펴보는 것이 좋습니다.