사내에서 외부 근무 관리 플랫폼을 사용하게 되며, 기존과는 다른 방식에 불편한 점이 생겨 이를 보완하기 위해 확장 프로그램을 제작하게 되었습니다.
크롬 웹 스토어에는 팝업에서 기능을 컨트롤하는 프로그램, 팝업에서 컨트롤하지 않아도 설치 시 편의 기능을 제공하는 프로그램 등... 다양하게 동작하는 확장 프로그램이 존재합니다.
확장 프로그램은 HTML, CSS, JavaScript 등의 웹 기술을 사용하여 크롬 브라우저의 기능을 확장하는 프로그램입니다.
확장 프로그램을 만들기 위해서는 기본적으로 manifest.json 파일을 작성하고, UI를 구성하는 HTML/CSS 및 동작을 제어하는 JavaScript 파일을 작성해야 합니다. 폴더 구조부터 시작하여 제작 방법을 알아보도록 하겠습니다.
확장 프로그램은 React와 같은 프론트엔드 라이브러리를 사용하여 제작할 수도 있지만, 추가적인 라이브러리 없이 HTML, CSS, JavaScript만을 사용하여 제작 가능합니다. 일반적인 폴더 구조는 아래와 같습니다.
my-extension
├── manifest.json
├── background.js
├── content.js
├── popup/
│ ├── popup.html
│ ├── popup.js
│ └── popup.css
└── images/
├── icon-16.png
├── icon-32.png
├── icon-48.png
└── icon-128.png
확장 프로그램의 동작을 그림으로 표현하면 아래와 같습니다.
출처 : https://developer.chrome.com/docs/extensions/mv2/architecture-overview?hl=ko
필수적인 파일로 확장 프로그램의 구조와 포함할 수 있는 기능을 설정하는 파일입니다.
루트 디렉터리에 있어야 하며, 자세한 작성 방법은 공식 문서에서 확인 가능합니다.
이 글에서는 몇 가지 항목에 대해서만 설명하도록 하겠습니다.
{
"manifest_version": 3, // manifest.json 파일 형식의 버전을 지정하는 정수입니다. 지원되는 값은 3입니다.
"name": "Run script automatically",
"description": "Runs a script on www.example.com automatically when user installs the extension",
"version": "1.0",
"host_permissions": ["*://*.example.com/*"], // 확장 프로그램이 상호작용할 수 있는 웹페이지를 나열합니다.
"permissions": ["activeTab", "scripting", "tabs"], // 확장 프로그램이 요청하는 브라우저 권한을 정의합니다. activeTab"을 사용하면 현재 활성화된 탭의 정보를 가져올 수 있습니다.
"icons": { // 확장 프로그램 페이지에서 노출되는 아이콘이며 WebP 및 SVG 파일은 지원되지 않습니다.
"16": "images/icon-16.png", // 확장 프로그램 페이지 및 컨텍스트 메뉴의 파비콘
"32": "images/icon-32.png", // Windows 컴퓨터에는 이 크기가 필요한 경우가 많습니다.
"48": "images/icon-48.png", // 확장 프로그램 페이지에 표시
"128": "images/icon-128.png" // 설치 시 및 Chrome 웹 스토어에 표시
},
"action": {
"default_title": "title", // 아이콘 위에 마우스 포인터를 가져가면 표시되는 타이틀입니다.
"default_popup": "popup/popup.html", // 툴바에 설정되는 아이콘 클릭 시 표시되는 팝업입니다. 콘텐츠에 맞게 자동으로 크기가 조절됩니다.
"default_icon": { // 툴바에 설정되는 아이콘 이미지입니다.
"16": "images/default_icon-16.png",
"32": "images/default_icon-32.png",
"48": "images/default_icon-48.png",
"64": "images/default_icon-64.png",
"128": "images/default_icon-128.png"
}
},
"background": { // 백그라운드에서 실행되는 스크립트를 정의합니다.
"service_worker": "background.js"
},
"content_scripts": [ // 특정 URL 패턴과 일치하는 페이지가 열릴 때 로드할 JavaScript 또는 CSS 파일을 정의합니다.
{
"matches": ["*://*.example.com/*"]
"js": ["content.js"],
"css": ["content.css"],
}
]
}
popup.html
은 팝업 UI가 필요한 경우에 작성합니다. 아래는 예시 코드입니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Popup</title>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<h1>확장 프로그램</h1>
<button id="btn">클릭</button>
<script src="popup.js"></script>
</body>
</html>
// 해당하는 url의 탭이 존재하는 경우 content.js를 실행하는 함수
function checkTabInfo() {
const targetUrl = 'url'
chrome.tabs.query({}, (tabs) => {
const matchingTabs = tabs.filter(
(tab) => tab.url && tab.url.includes(targetUrl),
)
if (matchingTabs.length > 0) {
matchingTabs.forEach((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ['content.js'],
})
})
}
})
}
// 확장 프로그램이 처음 설치될 때, 새 버전으로 업데이트될 때, Chrome이 새 버전으로 업데이트될 때 실행
chrome.runtime.onInstalled.addListener(() => {
console.log("확장 프로그램이 설치되었습니다.")
})
기능을 구현할 때 가장 살펴봐야 할 점은 chrome 객체의 활용입니다. 위는 background.js
에 작성한 chrome 객체 활용의 예시 코드로 이 외에도 다양한 API를 제공하고 있으며 문서에서 확인 가능합니다.
대부분의 API에 액세스하려면 manifest.json 파일에 권한을 선언해야 하며 일부 권한은 사용자가 확장 프로그램을 계속 사용하려면 허용해야 한다는 경고를 트리거 합니다.
API의 활용을 대략적으로 정리하면 아래와 같습니다.
chrome.runtime.onInstalled
와 같은 이벤트를 감지하여 특정 작업을 실행할 수 있습니다.chrome.storage
API를 사용하여 데이터를 저장하고 불러올 수 있습니다.chrome.runtime.sendMessage()
및 chrome.runtime.onMessage.addListener()
를 사용하여 다른 스크립트와 통신할 수 있습니다.chrome.alarms
API를 사용하여 주기적으로 또는 지정된 시간에 코드가 실행되도록 할 수 있습니다.chrome.tabs
API를 사용하여 브라우저 탭을 열고, 닫고, 수정할 수 있습니다.chrome 객체만 사용할 수 있는 것이 아닌, 일반적인 자바스크립트 이벤트 리스너 등을 활용하여 기능을 처리할 수 있습니다.
아래는 popup.js
에 작성한 예시 코드입니다.
document.addEventListener('DOMContentLoaded', () => {
const manifestData = chrome.runtime.getManifest() // manifest.json 정보 가져오기
console.log('test')
})
document.getElementById('btn').addEventListener('click', function() {
alert('버튼 클릭!');
});
아래 사진과 같이 팝업 내에서 우클릭 후 "검사"를 클릭하여 console 을 확인할 수도 있습니다.
content.js나 background.js 같은 팝업에서 실행되지 않는 스크립트에 작성한 console은 작동되는 페이지에서 확인 가능합니다.
참고
제가 제작한 확장 프로그램은 팝업 내에서 기능을 제어하지 않고 특정 페이지에 근무 관련 UI를 추가하는 프로그램으로 아래와 같은 로직을 갖고 있습니다.
1.background.js
에서 특정 tab에 대한 접속을 확인하고content.js
를 실행
2.content.js
에서 근무 관련 계산 및 UI 추가 로직 실행
3. 팝업(popup.html
,popup.js
,popup.css
)에서는 확장 프로그램 관련 단순 정보만 제공
chrome://extensions/
를 입력하여 확장 프로그램 페이지에 접속합니다.파일을 수정한 후 브라우저에서 변경사항을 확인하기 위해서는 확장 프로그램을 새로고침 해야 합니다.
출처 : https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world?hl=ko
오류가 있을 시에는 오류 버튼이 활성화됩니다. 클릭하여 상세 페이지로 접근하면 오류에 대한 정보를 확인 가능합니다.
배포는 같이 개발을 진행한 동료분께서 진행하여 추후 업데이트할 예정으로 간략한 내용과 공식 문서를 참고 부탁드립니다.
아래는 간략한 배포 과정 내용입니다.
처음에는 가벼운 마음으로 확장 프로그램 제작을 시작하였는데 생각보다 까다로운 점들도 있었고 React나 TypeScript 환경에서도 제작 가능하다는 이번 기회를 통해 여러 가지 알게 된 것 같습니다.
웹스토어 배포 전에는 베타 버전으로 Git에 release 페이지를 회사 분들께 공유하여 사용 방법을 가이드 드리기도 했습니다.
가이드 드린 내용 일부
불편하다고 생각되는 부분을 동료분과 함께 개발을 통해 편리하게 사용할 수 있게 만든 것이 굉장히 좋은 경험이었고 앞으로도 필요하다고 생각되는 부분은 직접 개발하여 해결하고 싶다는 생각이 듭니다.
함께해 준 동료분 나보다 2000배는 더 고생하셨는데 함께해 주셔서 감사합니다. 좋은 동료분을 만난 것도 참 복이다 😂