1. 소개
Meet 통화에 참여하지만 다른 사람이 먼저 참여하고 싶지 않으신가요? 이 문제에 해당한다면 해결책이 있습니다.
이 Codelab에서는 첫 번째 참여자가 통화에 참여하면 알림을 표시하는 Chrome 확장 프로그램을 만들어 보겠습니다.
Chrome 확장 프로그램의 다양한 요소를 학습한 후 확장 프로그램의 각 부분에 대해 자세히 살펴봅니다. 콘텐츠 스크립트, 서비스 워커 및 메시지 전달과 같은 확장 기능에 대해 학습합니다.
참여자가 Meet 통화에 참여할 때마다 알림을 받으려면 매니페스트 v3 버전을 준수해야 합니다.
2. 시작하기 전에
기본 요건
이 Codelab은 초보자에게 적합하지만 JavaScript에 관한 기본적인 이해가 있으면 경험을 크게 향상할 수 있습니다.
설정/요구사항
- Chrome 브라우저
- 로컬 시스템의 IDE/편집기 설정
- gcloud를 사용하여 Gemini API를 사용 설정하려면 gcloud cli를 설치하세요.
Gemini API 사용 설정
- Google Cloud 콘솔의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.
- Cloud 프로젝트에 결제가 사용 설정되어 있어야 하므로 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.
- Gemini Marketplace 페이지로 이동하여 API를 사용 설정합니다. gcloud를 사용하여 API를 사용 설정할 수도 있습니다.
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID
- 새 탭에서 Cloud 콘솔을 위한 Gemini 페이지를 방문하여 '채팅 시작'을 클릭합니다.
Note that if you're writing the code in the Cloud Shell editor, then you will have to download the folder somewhere on your local filesystem to test the extension locally.
3. 산타 추적 시작하기
기본 확장 프로그램 설치
프로젝트의 루트로 사용할 디렉터리를 만들어 보겠습니다.
mkdir gemini-chrome-ext
cd gemini-chrome-ext
Gemini에 구체적인 질문을 시작하기 전에 Chrome 확장 프로그램의 일반적인 구조에 관한 몇 가지 질문을 해 보겠습니다.
프롬프트:
What are the important parts to build a chrome extension?
manifest
파일, background script
에 관한 사소한 세부정보, 사용자 인터페이스에 관한 세부정보를 지정하는 응답을 받습니다. 이러한 특정 파일에 대해 자세히 살펴보겠습니다.
프롬프트:
Create a manifest.json file to build a chrome extension. Make the name of the extension "Meet Joinees Notifier" and the author "<YOUR_EMAIL>"
작성자 입력란에 원하는 이름과 이메일을 입력할 수 있습니다.
Gemini는 필요한 매니페스트 파일의 콘텐츠를 반환하지만 action
필드와 같이 필요하지 않은 몇 가지 추가 필드를 가져옵니다. 그리고 설명이 필요합니다. 이 문제를 해결해보겠습니다.
프롬프트:
Remove the "action" field and make the description as "Adds the ability to receive a notification when a participant joins a Google meet".
이 콘텐츠를 프로젝트 루트에 있는 manifest.json
파일에 넣어 보겠습니다.
이 단계에서 매니페스트 파일은 다음과 같습니다.
{
"name": "Meet Joinees Notifier",
"version": "1.0",
"manifest_version": 3,
"description": "Adds the ability to receive a notification when a participant joins a Google Meet",
"author": "<YOUR_EMAIL>"
}
이 Codelab에서는 매니페스트 파일에서 생성된 필드를 가정하므로 지금은 매니페스트 파일에서 생성된 다른 모든 추가 필드를 삭제합니다.
이제 확장 프로그램이 작동하는지 테스트하려면 어떻게 해야 할까요? 친구 Gemini에게 물어볼까요?
프롬프트:
Guide me on the steps needed to test a chrome extension on my local filesystem.
테스트하는 방법에 관한 몇 가지 단계를 알려줍니다. chrome://extensions
로 이동하여 "Extensions Page"
로 이동하고 "Developer Mode"
버튼을 사용 설정합니다. 그러면 확장 프로그램 파일이 포함된 폴더로 이동하는 데 사용할 수 있는 "Load unpacked"
버튼이 표시됩니다. 그러면 "Extensions Page"
에 확장 프로그램이 표시됩니다.
좋습니다. 확장 프로그램이 표시되지만 몇 가지 기능을 추가해 보겠습니다.
4. 콘텐츠 스크립트 추가
콘텐츠 스크립트를 사용하여 실행할 수 있는 https://meet.google.com
에서만 일부 자바스크립트 코드를 실행하려고 합니다. 확장 프로그램에서 이 목표를 달성하는 방법을 Gemini에 물어보세요.
프롬프트:
How to add a content script in our chrome extension?
또는 더 구체적으로 설명하면 다음과 같습니다.
프롬프트:
How to add a content script to run on meet.google.com subdomain in our chrome extension?
또는 다른 버전:
프롬프트:
Help me add a content script named content.js to run on meet.google.com subdomain in our chrome extension. The content script should simply log "Hello Gemini" when we navigate to "meet.google.com".
Gemini는 manifest.json 파일에서 실행해야 하는 정확한 변경사항과 content.js
파일에 필요한 자바스크립트를 제공합니다.
content_scripts를 추가하면 매니페스트 파일은 다음과 같이 변경됩니다.
{
"name": "Meet Joinees Notifier",
"version": "1.0",
"manifest_version": 3,
"description": "Adds the ability to receive a notification when a participant joins a Google Meet",
"author": "abc@example.com",
"content_scripts": [
{
"matches": ["https://meet.google.com/*"],
"js": ["content.js"]
}
]
}
이렇게 하면 하위 도메인의 페이지로 이동할 때마다 content.js
콘텐츠 스크립트를 삽입하도록 Chrome에 지시합니다. https://meet.google.com에서 확인할 수 있습니다. 이 파일을 추가하고 테스트해 보겠습니다.
이 코드를 content.js
파일에 추가해 보겠습니다.
console.log("Hello Gemini");
당연하지! meet.google.com에 방문하면 'Hello Gemini'가 표시됩니다. 를 클릭합니다(Mac: Cmd + Opt + J
/ Win/Linux: Ctrl + Shift + J
).
manifest.json
{
"name": "Meet Joinees Notifier",
"version": "1.0",
"manifest_version": 3,
"description": "Adds the ability to receive a notification when a participant joins a Google Meet",
"author": "luke@cloudadvocacyorg.joonix.net",
"permissions": [
"tabs",
"notifications"
],
"content_scripts": [
{
"matches": [
"https://meet.google.com/*"
],
"js": [
"content.js"
]
}
]
}
content.js
‐·console.log("안녕하세요. Gemini!");
‐
좋습니다. 이제 앱에 JavaScript 관련 기능을 추가할 수 있습니다. 잠시 시간을 내어 우리가 달성하고자 하는 목표에 대해 생각해 보겠습니다.
콘텐츠 스크립트 개선
다른 사용자가 회의에 참여하면 회의 페이지(회의 참여 옵션이 있는 경우)에서 알림을 받을 수 있도록 하고 싶습니다. 이를 위해 회의가 비어 있을 때와 다른 사람이 회의에 참여했을 때 화면이 어떻게 시각적으로 바뀌는지 관찰해 보겠습니다.
회의에 아무도 없을 때 표시되는 화면은 다음과 같습니다.
반면 회의에 일부 참석자가 있을 때의 시각 자료입니다.
테스트 직후에 두 가지 눈에 띄는 차이점을 확인할 수 있습니다.
- 상태 텍스트가 '다른 사용자 없음'에서 변경됩니다. '[사용자] 님이 통화에 참여 중입니다.'로 변경합니다.
- 통화에 참여한 사용자의 이미지가 표시됩니다.
이 두 가지 변경사항으로 회의에 참여한 사람이 있는지 확인할 수 있지만, 후자를 사용하면 이미 참여한 사용자의 정보를 얻을 수 있으므로 이 방법을 사용해 보겠습니다.
'Elements Inspector'를 엽니다. Chrome에서 핫키 ( Mac: Cmd + Opt + C / Win: Ctrl + Shift + C
)를 사용하여 로그인한 다음 참여한 사용자의 이미지를 클릭합니다.
이미지에 수업 문자열이 거의 없는데 이미지의 제목 속성에는 회의에 참여한 사용자의 이름이 포함되어 있습니다. 또한 이 이미지 태그는 U04fid
클래스를 사용하여 div에 래핑됩니다. 테스트 회의에 참석자를 추가하면 이 상위 div가 여러 이미지(서로 다른 사용자에 해당)를 호스팅하는 것을 확인할 수 있습니다.
따라서 다음과 같은 부분적인 전략을 염두에 두겠습니다.
U04fid
클래스를 포함하는 div에 요소가 포함되어 있으면 감지합니다.- 표시된다면 회의에 참석자가 있음을 의미합니다.
- 사용자에게 알립니다.
Gemini로 돌아가서 어떻게 이 단계를 차근차근 달성할 수 있는지 질문해 보겠습니다.
프롬프트:
How to detect for element changes in the HTML page?
이 명령어는 MutationObserver
와 관련된 솔루션을 제공하지만 요구사항과는 관련이 없습니다. 프롬프트를 수정해 보겠습니다.
프롬프트:
How can I detect if an element "div.U04fid" has any child images in the HTML page?
이번에는 MutationObserver
를 포함하지 않는 솔루션을 얻었지만, 상위 div를 사용하여 조인을 확인하는 솔루션을 얻었습니다.
접수된 내용은 다음과 같습니다.
const divU04fid = document.querySelector('div.U04fid');
const childImages = divU04fid.querySelectorAll('img');
if (childImages.length > 0) {
// div.U04fid has at least one child image.
}
접근 방식을 좀 더 수정해 보겠습니다.
프롬프트:
Create a method which checks if the element div.U04fid has any child elements, if it does it should log it on the console. The method should be called checkJoinees and it should be called as a callback for MutationObserver which is observing the document.body.
다음 코드 스니펫과 함께 반환됩니다.
function checkJoinees(mutations) {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
// A child node was added or removed.
if (document.querySelector('div.U04fid') && document.querySelector('div.U04fid').childElementCount > 0) {
// div.U04fid has at least one child element.
console.log('div.U04fid has at least one child element.');
}
}
}
return false;
}
const observer = new MutationObserver(checkJoinees);
observer.observe(document.body, {
childList: true,
delay: 1000
});
이 코드를 content.js
파일에 복사하고 확장 프로그램을 새로고침한 다음 Meet 페이지를 새로고침합니다.
이제 누군가 회의에 참여하면 콘솔에서 로그 구문을 볼 수 있습니다.
5. 사용자에게 알림 보내기
이제 참여자가 회의에 참여했음을 감지할 수 있으므로 Chrome 확장 프로그램에 알림 부분을 추가해 보겠습니다. Chrome 확장 프로그램 문서를 둘러보거나 프롬프트를 조정하여 원하는 내용을 알 수 있지만 기본적으로 chrome.notifications.create
API를 사용해야 하며 이 메서드에 대한 호출은 백그라운드 서비스 워커에서 가져와야 합니다.
프롬프트:
Using the documentation for chrome notifications tell me how to use the chrome.notifications.create method.
주요 세부 단계는 다음과 같습니다.
- 매니페스트 파일에
notifications
권한을 추가합니다. - chrome.notifications.create를 호출합니다.
- 통화는 백그라운드 스크립트로 진행해야 합니다.
manifest version 3
의 Chrome 확장 프로그램에 백그라운드 스크립트를 추가하려면 manifest.json
파일에 background.service_worker
선언이 필요합니다.
background.js라는 파일을 만들고 manifest.json 파일에 다음을 추가합니다.
"background": {
"service_worker": "background.js"
},
"permissions": [
"notifications"
]
위의 내용을 추가하면 매니페스트 파일은 다음과 같이 됩니다.
{
"name": "Meet Joinees Notifier",
"version": "1.0",
"manifest_version": 3,
"description": "Adds the ability to receive a notification when a participant joins a Google Meet",
"author": "<YOUR_EMAIL>",
"content_scripts": [
{
"matches": ["https://meet.google.com/*"],
"js": ["content.js"]
}
],
"background": {
"service_worker": "background.js"
},
"permissions": [
"notifications"
]
}
프롬프트:
Create a method sendNotification that calls the chrome.notifications.create method with the message, "A user joined the call" for a chrome extension with manifest v3, the code is in the background service worker
이 이미지를 폴더의 루트에 저장하고 이름을 success.png
로 바꿉니다.
그런 다음 background.js
에 다음 코드 스니펫을 추가합니다.
function sendNotification(notificationId, message) {
chrome.notifications.create(notificationId, {
type: "basic",
title: "A user joined the call",
message: message,
iconUrl: "./success.png"
});
}
sendNotification("notif-id", "test message");
이제 확장 프로그램 페이지에서 확장 프로그램을 새로고침하면 즉시 알림 팝업이 표시됩니다.
6. Chrome 확장 프로그램에 전달되는 메시지 추가
이제 필요한 마지막 주요 단계는 콘텐츠 스크립트의 참여자 감지와 백그라운드 스크립트의 sendNotification
메서드를 연결하는 것입니다. Chrome 확장 프로그램에서는 message passing
라는 기법을 통해 이를 실행합니다.
이를 통해 Chrome 확장 프로그램의 여러 부분(여기서는 콘텐츠 스크립트에서 백그라운드 서비스 워커까지) 간에 통신할 수 있습니다. 이 목표를 달성하는 방법을 친구 Gemini에게 물어보세요.
프롬프트:
How to send a message from the content script to the background script in a chrome extension
Gemini가 적절한 chrome.runtime.sendMessage
및 chrome.runtime.onMessage.addListener
호출로 응답합니다.
기본적으로 sendMessage
를 사용하여 다른 사용자가 Meet 통화에 참여했다는 콘텐츠 스크립트에서 메시지를 전송하고 onMessage.addListener
를 이벤트 리스너로 사용하여 콘텐츠 스크립트에서 보낸 메시지에 반응합니다. 이 경우 이 이벤트 리스너에서 sendNotification
메서드 호출을 트리거합니다.
알림 메시지와 action
속성을 백그라운드 서비스 워커에 전달합니다. action
속성은 백그라운드 스크립트가 응답하는 대상을 설명합니다.
다음은 content.js
코드입니다.
function checkJoinees(mutations) {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
// A child node was added or removed.
if (document.querySelector('div.U04fid') && document.querySelector('div.U04fid').childElementCount > 0) {
// div.U04fid has at least one child element.
sendMessage();
}
}
}
return false;
}
const observer = new MutationObserver(checkJoinees);
observer.observe(document.body, {
childList: true,
delay: 1000
});
function sendMessage() {
chrome.runtime.sendMessage({
txt: "A user has joined the call!",
action: "people_joined"
});
}
다음은 background.js
코드입니다.
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "people_joined") {
sendNotification("notif-id", message.txt);
}
});
function sendNotification(notificationId, message) {
chrome.notifications.create(notificationId, {
type: "basic",
title: "A user joined the call",
message: message,
iconUrl: "./success.png"
});
}
알림 메시지를 맞춤설정하고 고유한 알림 ID를 생성해 보겠습니다. 알림 메시지의 경우 사용자 이름을 포함할 수 있습니다. 이전 단계에서 설명했듯이, 이미지의 제목 속성에서 사용자의 이름을 볼 수 있습니다. 따라서 document.querySelector('div.U04fid > img').getAttribute('title').
를 사용하여 참여자의 이름을 가져올 수 있습니다.
알림 ID의 경우 콘텐츠 스크립트의 탭 ID를 가져와 알림 ID로 사용할 수 있습니다. 이 작업은 sender.tab.id.
를 다음 이벤트 리스너 chrome.runtime.onMessage.addListener
내에서 실행할 수 있습니다.
마지막으로 파일은 다음과 같아야 합니다.
manifest.json
{
"name": "Meet Joinees Notifier",
"version": "1.0",
"manifest_version": 3,
"description": "Adds the ability to receive a notification when a participant joins a Google Meet",
"author": "<YOUR_EMAIL>",
"content_scripts": [
{
"matches": ["https://meet.google.com/*"],
"js": ["content.js"]
}
],
"background": {
"service_worker": "background.js"
},
"permissions": [
"notifications"
]
}
content.js
function checkJoinees(mutations) {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
// A child node was added or removed.
if (document.querySelector('div.U04fid') && document.querySelector('div.U04fid').childElementCount > 0) {
const name = document.querySelector('div.U04fid > img').getAttribute('title');
sendMessage(name);
}
}
}
return false;
}
const observer = new MutationObserver(checkJoinees);
observer.observe(document.body, {
childList: true,
delay: 1000
});
function sendMessage(name) {
const joinee = (name === null ? 'Someone' : name),
txt = `${joinee} has joined the call!`;
chrome.runtime.sendMessage({
txt,
action: "people_joined",
});
}
background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "people_joined") {
sendNotification("" + sender.tab.id, message.txt); // We are casting this to string as notificationId is expected to be a string while sender.tab.id is an integer.
}
});
function sendNotification(notificationId, message) {
chrome.notifications.create(notificationId, {
type: "basic",
title: "A user joined the call",
message: message,
iconUrl: "./success.png"
});
}
7. 축하합니다
얼마 지나지 않아 Gemini의 도움을 받아 Chrome 확장 프로그램을 빌드할 수 있었습니다. 숙련된 Chrome 확장 프로그램 개발자든 확장 프로그램을 처음 사용하는 초보자든 Gemini는 원하는 모든 작업에 도움을 드릴 수 있습니다.
Chrome 확장 프로그램으로 할 수 있는 여러 가지 작업에 대해 문의해 보시기 바랍니다. chrome.storage
, alarms
등 살펴볼 만한 여러 API가 있습니다. 문제가 있는 경우 Gemini 또는 문서를 사용하여 잘못된 부분을 파악하고 문제를 해결하기 위한 다양한 방법을 수집하세요.
필요한 도움을 받으려면 프롬프트를 수정해야 하는 경우가 많지만, 모든 상황별 여정이 저장된 하나의 탭에서 이를 수행할 수 있습니다.