크롬 확장프로그램 개발
어느 날 잘쓰고 있던 학교 선배님이 만든 LMS(학습 관리 시스템)기능 확장프로그램이 학교 사이트 개편으로 인해 더 이상 쓸 수가 없어져서..내가 만들어야겠다고 생각했다..
구조
구조를 보면 간단하다. HTML+CSS+JavaScript 를 사용해서 충분히 만들 수 있다.
-
contentscript.js 사용자가 방문하는 영역에서 작동하는 스크립트 페이지의 현재 상태에 대한 정보를 전달한다. 현재 페이지의 DOM을 읽어와서 조작이 가능하다.
-
background.js 브라우저 영역에서 작동하는 스크립트 플러그인의 이벤트 핸들러 중요한 모든 이벤트 리스너가 여기 저 장된다. 이벤트가 트리거 되고, 할당된 로직을 실행할 때까지 inactive 상태로 유지된다.
-
popup.js 시각적인 기능을 담당한다. HTML과 직접 상호작용하고, background 스크립트와 함께 API를 호출 popup.html이 index.html과 같은 의미이다.
크롬 설정을 누르면 확장 프로그램에 대해서 확인할 수 있다.
확장 프로그램 관리와 Chrome 웹 스토어 방문하기가 있는데 생각보다 크롬 확장프로그램을 사용을 안하는 사람이 많다.
개발자라면 도움이 되는 확장 프로그램이 많다!! CSS viewer 라던가.. Json Viewer라던가.. 코테문제를 풀면 자동으로 깃허브에 저장된다던가..!
파일을 드래고 하거단 로드를 할 수 있는데 기본적으로
menifest 파일이 존재해야한다!!!!
Manifest 파일의 핵심 역할
Chrome 확장 프로그램의 manifest 파일(manifest.json)은 확장 프로그램의 DNA다. 이 파일은 다음과 같은 중요한 기능을 한다:
1> - 확장 프로그램 신원 확립:2>name, version, description 필드에 기본 정보가 들어간다.3이 정보로 사용자와 Chrome 웹 스토어가 프로그램을 식별한다.4
5
6- 권한 선언:7>permissions 배열에 필요한 권한이 나열된다.8이는 사용자의 프라이버시와 보안을 지킨다.9
10
11- 리소스 정의:12>icons, action 등에 시각적 요소의 위치가 지정된다.13사용자 인터페이스 관련 파일들의 경로가 여기에 있다.14
15
16- 백그라운드 로직 설정:17>background 섹션에 서비스 워커나 백그라운드 페이지가 정의된다.18확장 프로그램의 '두뇌' 역할을 하는 스크립트가 여기에 지정된다.19
20
21- 콘텐츠 스크립트 선언:22>content_scripts 섹션에 웹 페이지에 삽입될 스크립트가 정의된다.23이를 통해 확장 프로그램이 웹 페이지와 상호작용한다.24
25
26- 보안 정책 설정:27>content_security_policy에 확장 프로그램의 보안 정책이 정의된다.28XSS 공격 등으로부터 확장 프로그램을 보호한다.29
30
31- API 버전 명시:32>manifest_version에 사용하는 manifest 파일의 버전이 지정된다.33이에 따라 Chrome이 확장 프로그램을 해석하고 실행한다.34
35
36- 웹 접근 범위 정의:37>host_permissions에 접근 가능한 웹 사이트가 지정된다.38사용자의 동의 하에 특정 도메인에 대한 접근 권한이 부여된다.39
40
41- 국제화 지원:42>default_locale과 관련 리소스 파일로 다국어를 지원한다.43이를 통해 전 세계 사용자를 위한 현지화가 가능하다.44
45
46- 웹 접근성 기능:47>commands 섹션에 키보드 단축키가 정의된다.48이로써 사용자 경험이 향상되고 접근성이 개선된다.천천히 읽어보면 좋다 !
menifest작성이 끝났다면 popup,contentscript,background를 작성하면 간단한 확장프로그램은 만들 수 있다.
배경색을 바꾸는 확장프로그램을 만들어 보자 !!
1// manifest.json2{3 "name": "Simple Change Color",4 "description": "현재 탭의 배경색을 변경하고 텍스트를 추가하는 간단한 MV3 확장 프로그램",5 "version": "1.0.0",6 "manifest_version": 3,7 "permissions": [8 "activeTab",9 "scripting"10 ],11 "host_permissions": [12 "<all_urls>"13 ],14 "action": {15 "default_popup": "popup.html"16 },17 "content_scripts": [18 {19 "matches": [20 "<all_urls>"21 ],22 "js": [23 "contentScript.js"24 ],25 "run_at": "document_idle"26 }27 ]28}29
30// popup.html31<!DOCTYPE html>32<html>33
34<head>35 <title>Change background Color</title>36</head>37
38
39<body>40 <button id="changeColor">background Color change</button>41 <button id="addText">text add</button>42 <script src="popup.js"></script>43</body>44
45</html>46
47// popup.js48document.getElementById('changeColor').addEventListener('click', async () => {49 let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });50 if (chrome.runtime.lastError) {51 console.error(chrome.runtime.lastError);52 return;53 }54 if (tab && !tab.url.startsWith("chrome://")) {55 try {56 await chrome.scripting.executeScript({57 target: { tabId: tab.id },58 function: setPageBackgroundColor,59 });60 console.log("Script executed successfully");61 } catch (error) {62 console.error("Error executing script:", error);63 }64 } else {65 console.error("Cannot execute script on this page");66 }67});68
69function setPageBackgroundColor() {70 document.body.style.backgroundColor = `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255})`;71}72
73document.getElementById('addText').addEventListener('click', async () => {74 let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });75 if (chrome.runtime.lastError) {76 console.error(chrome.runtime.lastError);77 return;78 }79 if (tab && !tab.url.startsWith("chrome://")) {80 try {81 const response = await chrome.tabs.sendMessage(tab.id, {action: "addText"});82 console.log("Message sent successfully", response);83 } catch (error) {84 console.error("Error sending message:", error);85 // Content Script가 로드되지 않았을 수 있으므로, 스크립트를 주입하고 다시 시도합니다.86 try {87 await chrome.scripting.executeScript({88 target: { tabId: tab.id },89 files: ["contentScript.js"]90 });91 const response = await chrome.tabs.sendMessage(tab.id, {action: "addText"});92 console.log("Message sent successfully after injecting content script", response);93 } catch (injectError) {94 console.error("Error injecting and executing content script:", injectError);95 }96 }97 } else {98 console.error("Cannot send message to this page");99 }100});101
102// background.js103chrome.runtime.onInstalled.addListener(() => {104 console.log('배경색 변경기가 설치되었습니다.');105});106
107// contentScript.js108chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {109 if (request.action === "addText") {110 const newElement = document.createElement('div');111 newElement.textContent = '이 텍스트는 확장 프로그램에 의해 추가되었습니다!';112 newElement.style.position = 'fixed';113 newElement.style.top = '10px';114 newElement.style.right = '10px';115 newElement.style.backgroundColor = 'yellow';116 newElement.style.padding = '10px';117 newElement.style.zIndex = '9999';118 document.body.appendChild(newElement);119 sendResponse({status: "Text added successfully"});120 }121 return true; // 비동기 응답을 위해 필요합니다.122});파일은 위 주석에 나와있는 것처럼 나눠야 한다.
이렇게 파일이 만들어지면 위에서 확장프로그램 개발자모드를 체크! 하고 파일을 로드하면 된다.
이런식으로 작동이 잘 되는걸 볼 수 있다. !!