1. 서론
이번 포스트에서는 크롬 확장프로그램 manifest v3와 Typescript 활용 방법에 대해 소개한다.
크롬 확장프로그램은 크게 Popup과 Background로 이루어져있다. 이 둘은 웹서비스로 비유하자면 Frontend와 Backend같은 역할을 하며 확장프로그램을 이룬다. Chrome browser API를 통해 Popup과 Background가 서로 통신하며 API에서 제공하는 기능들을 이용해 사용자의 편의성을 향상시킬 수 있는 확장 프로그램을 개발할 수 있다.
(필자의 모든 JS/Node 생태계 관련 포스트는 Typescript를 기준으로 설명한다. Typescript를 생활화하자.)
2. manifest v2 vs manifest v3
manifest는 크롬 확장프로그램의 json 메타데이터 파일이다(Node 생태계로 치면 package.json 같은 존재이다.)
이전에는 v2 버전이 주로 사용되었었고 아직도 크롬 웹스토어에는 v2 버전을 사용하는 확장프로그램들이 많이 등록되어있다.
하지만 구글이 v3를 공개하면서 점진적으로 v2를 제거해나가기로 밝혔고, 이미 2022년 6월부터 새로운 manifest v2기반 확장프로그램의 신규 등록이 중단된 상태이다. 2023년 1월부터는 Chrome 112 버전부터 Canary, Dev 및 Beta 채널에서 Manifest v2 확장프로그램 지원을 해제하는 실험을 실행할 수 있고, 2023년 6월부터 Chrome 115는 모든 채널에 대한 Manifest v2 확장프로그램의 지원을 중단하는 실험을 진행할 수 있으며 2024년 1월부터는 크롬 웹스토어에 기존 Manifest v2 확장 프로그램의 업데이트를 중단되며 모든 v2 확장프로그램이 스토어에서 제거된다.
예전에는 개발자들 사이에서도 v3는 관련 레퍼런스가 아직 부족하니 v3보단 v2를 추천하는 추세였다면, 현재는 구글의 Manifest v3 마이그레이션 의지가 뚜렸하고 이미 그 행동이 시작되었으며 요즘은 v3에 대한 레퍼런스들도 많이 생겼기 때문에 신규로 크롬 확장프로그램을 개발해야한다면 manifest v3를 사용하여 개발해야한다.
manifest v2와 manifest v3의 자세한 차이점을 확인하고 싶다면 아래 페이지를 참고하기 바란다.
3. 크롬 확장프로그램 기본 구조
기본적인 크롬 확장프로그램에 필요한 필수 파일 구조는 아래와 같다
아래 구조안에 포함된 파일들은 꼭 프로젝트 안에 포함되어있어야 한다 (단, manifest.json은 꼭 파일명이 "manifest.json"이어야 하고 나머지 파일들은 manifest.json의 설정 내용에 따라 이름이 달라질 수도 있다.)
/
ㄴ icon/
ㄴ icon16.png
ㄴ icon32.png
ㄴ icon48.png
ㄴ icon128.png
ㄴ manifest.json
ㄴ popup.html
ㄴ background.js
3-1. manifest.json
Node의 package.json같은 크롬 확장프로그램의 메타 데이터를 정의하는 파일이다.
여기서 확장프로그램의 "이름", "설명", "버전", "manifest 버전", "브라우저 권한", "호스트 권한", "백그라운드 파일", "팝업 HTML 파일", "아이콘" 등을 설정할 수 있다.
이번 포스트에선 manifest v3를 기준으로 하고있기 때문에 "manifest 버전"은 "3"으로, "백그라운드 파일"은 "service_worker"로 설정해야한다.
아래는 manifest.json의 예시이다 (manifest v3 기준이다.)
[manifest.json 예시]
{
"name": "Chrome Extension manifest v3 Example",
"description": "Chrome Extension manifest v3 Example",
"version": "0.0.0.1",
"manifest_version": 3,
"permissions": ["tabs", "scripting", "alarms"],
"host_permissions": ["*"],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_title": "tooltip message string"
"default_icon": {
"16": "icon/icon16.png",
"32": "icon/icon32.png",
"48": "icon/icon48.png",
"128": "icon/icon128.png"
}
}
}
manifest v3와 v2의 가장 큰 차이점은 확장프로그램 백그라운드 방식이 바뀌었다는 것이다. v2에선 "Background Script"라는 개념을 사용했고 v3에선 "Service Worker"라는 개념을 사용한다. 그래서 이 둘은 manifest.json에서 백그라운드 관련 js파일을 지정하는데에도 약간 차이점이 존재한다. v2에서는 "scripts"라는 키로 여러개의 Background Script js파일이 등록 가능했지만, v3에서는 "service_worker"라는 키로 단 하나의 Service Worker 파일을 등록할 수 있다
(여기서 "background.js" 는 관례적으로 사용하는 이름일 뿐이기 때문에 꼭 이름이 "background"일 필요는 없다.)
[v2]
...(생략)...
"background": {
"scripts": ["background.js"],
"persistent": false
},
...(생략)...
[v3]
...(생략)...
"background": {
"service_worker": "background.js"
},
...(생략)...
"action"이라는 키를 통해 팝업에서 사용될 기본 HTML과 확장 프로그램 아이콘에 마우스 오버시 표시될 툴팁, 기본 아이콘을 지정할 수 있다. 이후에 Chrome browser API 중 chrome.action 내 메소드를 이용해 팝업 HTML, 툴팁, 아이콘을 스크립트 상에서 바꿀 수도 있다. 이 부분은 아래 페이지를 참고하길 바란다.
...(생략)...
"action": {
"default_popup": "popup.html",
"default_title": "tooltip message string"
"default_icon": {
"16": "icon/icon16.png",
"32": "icon/icon32.png",
"48": "icon/icon48.png",
"128": "icon/icon128.png"
}
},
...(생략)...
"permissions"라는 키를 통해 확장프로그램 구현에 필요한 Chrome browser API의 기능별 권한 요청을 배열의 형태로 지정할 수 있다. 이후 크롬 웹스토어 신규 배포 등록을 위해 manifest.json에 기재된 권한마다 이용 목적을 작성해야하기 때문에 꼭 필요한 권한만 요청해야한다.
사용할 수 있는 기능 권한들은 아래 페이지를 참고하길 바란다.
...(생략)...
"permissions": ["tabs", "scripting", "alarms"],
...(생략)...
"host_permissions"라는 키를 통해 확장프로그램에서 Chrome brower API를 호출할 수 있는 호스트 위치를 지정할 수 있다.
특정 URL을 지정할 수도 있고, 와일드카드 문자로 모든 URL로 지정할 수도 있으며 특정 URL 안에 와일드카드 문자를 넣어서 가변 서브도메인이나 쿼리 등을 표현할 수 있다.
"host_permissions": ["*"]
또는
"host_permissions": ["https://www.youtube.com"]
또는
"host_permissions": ["https://*.youtube.com/*"]
3-2. popup.html
popup.html은 우리가 확장프로그램을 클릭했을때 보여지는 팝업에 들어갈 HTML 파일이다. 웹서비스로 비유하자면 확장프로그램의 프론트엔드같은 역할을 한다.
popup.html에서 js를 사용하여 Chrome browser API를 사용하여 서비스워커와 통신하거나 브라우저로부터 기능을 호출할 수 있다.
확장프로그램 팝업은 닫았다 열게 되면 페이지가 새로고침되기 때문에 팝업이 닫힌 이후에도 지속적으로 작업을 수행하려면 서비스워커를 통해 작업을 처리하고 이를 메시지로 통신하여 결과를 전달하는 방법이 필요하다. 또한 팝업에서 어떠한 데이터를 영구적으로(확장 프로그램이 삭제되기 전까지) 저장하고 싶다면 LocalStorage나 IndexedDB, WebSQL을 사용하면 된다.
popup.html은 일반적인 HTML 표준에 따라 작성하면 된다.
위 이미지같은 경우 svelte를 사용하는 프로젝트의 popup.html이라 내용이 크게 특별할거 없이 svelte가 번들링된 js를 가져오고 번들링된 css와 전역 css를 가져오는 정도가 전부이다. 이마저도 필수사항은 아니니 프로젝트 상황에 따라 적절하게 이용하면 되는 것이다.
3-3. background.js
background.js는 크롬 확장프로그램의 서비스워커 소스코드이다. 웹서비스로 비유하자면 확장프로그램의 백엔드같은 역할을 한다.
확장프로그램의 팝업이 닫힌 이후에도 지속적으로 수행되어야 할 작업은 서비스워커에 구현한 후 Chrome brower API를 이용해 팝업으로 전달해야한다. 마찬가지로 어떠한 데이터를 영구적으로(확장 프로그램이 삭제되기 전까지) 저장하고 싶다면 LocalStorage나 IndexedDB, WebSQL을 사용하면 된다.
4. Chrome browser API
크롬 브라우저에서는 전역객체 window.chrome를 통해 크롬 브라우저에서만 사용할 수 있는 API들을 제공한다. 다만, 크롬 확장프로그램의 javascript 런타임 chrome 객체와 일반 브라우징 환경에서의 javascript 런타임 chrome 객체는 서로 포함하고 있는 멤버에 차이가 있다.
각각의 환경에서 chrome 객체를 확인해보면 확연하게 차이가 나는것을 볼 수 있다. 크롬 확장프로그램 환경에서 제공되는 chrome 객체에는 manifest.json에서 요청된 권한에 따라 조금씩 달라지지만 크롬 확장프로그램에서만 사용할 수 있는 API들이 제공됨을 알 수 있다.
확장프로그램의 팝업과 서비스워커는 이 객체를 이용하여 Chrome browser API를 호출할 수 있다.
Chrome browser API는 다양한 기능을 포함하고 있어서 여기서 모두 다룰 수는 없지만 간단한 예 하나를 소개한다.
chrome.runtime을 이용하면 팝업과 서비스워커 간의 통신을 구현할 수 있다 (이 기능을 사용하기 위해서는 manifest.json에서 "tabs" 권한을 요청해야한다.)
위 예에서는 popup.html에서 버튼을 클릭하면 서비스워커로 메시지를 보내고 이를 서비스워커가 수신하면 메시지 내의 "hello"의 값을 로그로 출력한 뒤 응답을 보내며, 팝업이 그 응답을 수신하고 로그로 출력한다.
워낙 기능이 다양하다보니 더 자세한 기능들은 아래 공식 레퍼런스를 확인해보길 바란다.
6. with Typescript
Typescript를 크롬 확장프로그램 개발에 사용하려면 크게 두 가지 문제가 해결되어야 한다.
1. Chrome browser API의 타입 문제
2. Typescript 빌드 문제
사실 두 가지 모두 해결방법은 간단하다.
1번의 경우, npm 패키지로 Chrome browser API의 타입정의가 공개되어있기 때문에 Typescript가 세팅된 프로젝트에서 아래 명령으로 설치할 수 있다.
npm install -D @types/chrome
또는
yarn add -D @types/chrome
2번도 사실은 수동으로 명령을 쳐가면서 사용할 수도 있겠지만,
그렇게 되면 매번 수정이 이루어질때마다 즉각적인 확인이 불가능하기 때문에 이는 Webpack이나 Rollup같은 번들러를 활용하면 쉽게 해결할 수 있다. 덕분에 핫리로딩과 자동 번들링을 이용할 수 있어서 개발 편의성이 향상된다. 이때 주의할 점은, popup.html에 사용될 스크립트의 이름은 크게 상관 없으나 서비스워커 소스로 사용될 스크립트의 빌드 파일 이름은 꼭 manifest에 정의한 파일명으로 생성될 수 있도록 설정해야한다.
번들러를 이용할 수 있다는 것는 React, Vue, Svelte 등의 프론트 프레임워크들을 크롬 확장프로그램 개발에 활용할 수 있다는 뜻이기도 하다. 사실 번들러를 이용할 수 있어서 라기보단 크롬 확장프로그램의 소스로 사용되는 정적 파일들을 생성할 수 있는 방법이라면 어떤 방법이든 활용할 수 있다.
7. 프론트 프레임워크 활용법
크롬 확장프로그램에서 프론트 프레임워크를 활용하는 방법에 대한 필자의 포스팅들이다.
이후에도 계속 업데이트 될 예정이다.
2022.10.07 - [SW/Typescript] - [Typescript] Svelte로 Chrome Extension 개발하기
'SW > Typescript' 카테고리의 다른 글
[Typescript] 유틸리티 타입 - 1 (0) | 2022.10.11 |
---|---|
[Typescript] Svelte로 Chrome Extension 개발하기 (0) | 2022.10.07 |
[Typescript] 소규모 서비스에서의 FaaS(Netlify Functions)와 WebRTC를 통한 Peer간 (서버측면)저비용 통신 서비스 구현 - 1. 방법론 (0) | 2022.06.10 |
[Typescript] Knex.js로 MySQL/MariaDB 연동하기 (0) | 2022.03.07 |
[Typescript] Promise 객체를 이용한 비동기(Asynchronous)적 처리 (0) | 2021.12.08 |