자바스크립트

프로그래머스 실행 용 크롬 확장 프로그램 제작

2022. 12. 9. 04:30


728x90

깃 클론을 하면 소스를 볼 수 있어요!

https://github.com/okanekudasai/programmersExtension.git

깃 클론의 방법

https://okane-on-cliff.tistory.com/226

 

깃 클론 하는 방법

깃 클론은 프로젝트 폴더를 다운로드 하는 방법 중 하나입니다. 즉 클론 이후에는 프로젝트 폴더가 생성이 됩니다. 개발자가 되는 것을 생각하지 않는 사람이라도 깃 클론을 통해 원본 소스들을

okane-on-cliff.tistory.com

 

깃 클론을 하면 폴더가 생성됩니다. 그 폴더를 chrome://extensions에서 

그 폴더를 이 버튼을 클록하여 등록하면 웹 스토어를 통하지 않아도 크롬에 설치할 수 있습니다. 단 우측상단의 개발자 모드를 켜야 됩니다

 

시연 영상 입니다

https://youtu.be/CmhYlFyhDLw

마우스를 사용하지 않고 코드 실행을 하고 있는 것을 확인 할 수 있습니다.

 

웹 스토어 다운로드 주소

https://chrome.google.com/webstore

 

프로그래머스확장

컨트롤 스페이스로 실행을 누를 수 잇습니다

chrome.google.com


제작과정

 

디렉터리 구조

프로젝트 폴더
|
|   background.js
|   hello.html
|   hello.js
|   manifest.json
|
+---images
|       icon-128.png
|       icon-16.png
|       icon-32.png
|       icon-48.png
|
\---scripts
        content.js

 

다음에도 확장 프로그램을 만들지도 모르겠으니 제작 과정을 설명해 놓고자 합니다.

 

제작과정
1. 코드 작성
2. 배포

 

1. 코드 작성

(1)모든 것의 시작은 manifest.json을 작성하는 것입니다. manifest.json은 해당 프로젝트의 명세서라 생각하면 됩니다

{
    "manifest_version": 3,
    "name": "프로그래머스확장",
    "description": "컨트롤 스페이스로 실행을 누를 수 잇습니다",
    "version": "1.0",
    "action": {
        "default_popup": "hello.html"
    },
    "background": {
        "service_worker": "background.js"
    },
    "icons": {
        "16": "images/icon-16.png",
        "32": "images/icon-32.png",
        "48": "images/icon-48.png",
        "128": "images/icon-128.png"
    },
    "content_scripts": [
        {
            "js": [
                "scripts/content.js"
            ],
            "matches": [
                "https://school.programmers.co.kr/learn/courses/30/lessons/*"
            ]
        }
    ],
    "permissions": [
        "storage"
    ]
}

icons는 앱 배포 및 익스텐션 리스트에 보여지는 아이콘이미지를 나타냅니다. 4개 크기의 아이콘이 모드 있어야 에러가 나지 않습니다.

 

content_scripts는 팝업 html에서가 아니라 현재 내가 보고있는 페이지에서 사용될 자바스크립트 코드가 적혀있습니다. matches에서 어디서 그 js파일이 실행 될 수 있을지 정의할 수 있습니다. 이러한 과정을 거치지 않고 팝업 html에서 직접 <script>를 작성한다면 에러가 발생합니다.

 

permission은 각종 chrome api를 사용하고 싶다고 적을 수 있는 프로퍼티 입니다. 이번 프로젝트에서는 익스텐션이 켜져있는지 꺼져있는지를 기억할 공간으로 chrome.storage.sync를 사용하엿습니다. sync는 localstorage등과 다르게 내 크롬 계정안에 있는 기억공간으로 만약 집에서 익스텐션을 키면 직장에서도 익스텐션이 켜져있는 것을 확인 할 수 있습니다.

 

(2)다음으로 만들 파일은 hello.html입니다. 익스텐션 아이콘을 클릭하면 나오는 팝업 페이지가 바로 이 파일입니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="OnButton"></button>
    <script src="hello.js"></script>
</body>
<style>
    body {
        width: 60px;
        text-align: center;
    }
</style>
</html>

버튼이 하나 있고 그 버튼을 hello.js에서 작동시키는 간단한 코드입니다. body의 크기를 지정해 주지 않으면 크기가 너무 작게 나와서 width의 값을 <style>을 통해 지정해 봤습니다.

 

(3)background.js

이 파일에서는 각종 chrome api의 리스너를 정의합니다. 예를들어 이 프로젝트에서는 익스텐션이 설치되었을 때 사용할 콜백 함수

chrome.runtime.onInstalled.addListener(() => {콜백함수}); 와

chrome.storage.onChanged.addListener((changes, namespace) => {콜백함수}); 가 있습니다.

chrome.runtime.onInstalled.addListener(() => {
    chrome.action.setBadgeText({
        text: "OFF",
    });
    chrome.storage.sync.set({ "isOn": false });
});

chrome.storage.onChanged.addListener((changes, namespace) => {
    for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
        // console.log(
        //     `Storage key "${key}" in namespace "${namespace}" changed.`,
        //     `Old value was "${oldValue}", new value is "${newValue}".`
        // );
        if (newValue == false) {
            chrome.action.setBadgeText({
                text: "OFF",
            });
        } else {
            chrome.action.setBadgeText({
                text: "ON",
            })
        }
    }
});

이 파일에서는 팝업 html의 요소에도 현재 크롬이 띄우고 있는 페이지의 요소에도 접근 할 수 없는 것 같습니다. (확실 하진 않으나 에러가 난다면 이런 이유일 것입니다.) 하지만 주석처리된 console.log가 팝업html의 console에서 나오는 것을 보면 아마도 팝업 html의 요소에는 접근 할 수 있을 지도 모르겠습니다.

 

chrome.runtime.onInstalled.addListener(() => {콜백함수}); 는  익스텐션이 설치 될 때 실행되는 콜백함수를 지정합니다.

여기서는 익스텐션의 뱃지의 text를 OFF로  초기화 시키고, storage.sync 의 내용을 {"isOn": false} 로 저장했습니다. 이 프로젝트에서 isOn이 false라면 익스텐션이 꺼져있음을 의미 합니다. isOn은 제가 적당히 이름을 지은 String입니다.

 

chrome.storage.onChanged.addListener((changes, namespace) => {콜백함수}); 는 chrome api의 storage의 내용이 변하면 실행되는 콜백함수를 지정합니다.

 

(4)scripts/hello.js 를 작성합니다.

document.querySelector("#OnButton").addEventListener("click", async function () {
    var status = await chrome.storage.sync.get(["isOn"]);
    // console.log(status.isOn)
    if (status.isOn == false) {
        document.querySelector("#OnButton").innerText = "끄기"
    } else {
        document.querySelector("#OnButton").innerText = "켜기"
    }
    await chrome.storage.sync.set({ "isOn": !status.isOn });
})

chrome.storage.sync.get(["isOn"]).then((result) => {
    // console.log(result.isOn);
    if (result.isOn == true) document.querySelector("#OnButton").innerText = "끄기";
    else document.querySelector("#OnButton").innerText = "켜기";
});

팝업 html에서도 확인할 수 있듯이 이 파일은 <script src="hello.js"></script>을 통해 import됩니다. 따라서 팝업 html을 작동시키는 파일임을 알 수 있습니다.

 

이 파일에서도 chrome api에 접근할 수 있습니다. 이프로젝트에선  먼저 팝업 html이 실행되면 button에 어떤 글씨를 적을지 결정합니다. 만약 익스텐션이 꺼져있다면 버튼텍스트를 '켜기'로 켜져있다면 버튼 텍스트를 '끄기'로 넣습니다. 만약 다시 한다면 버튼을 두개만들고 하나를 type=hidden으로 만드는게 나은것 같습니다.

 

그리고 그 버튼에 대한 리스너를 등록합니다. storage.sync는 get()과 set()을 통해서 접근 할 수 있는데 둘다 promise를 반환하는 비동기 함수이기 때문에 리스너에 등록한 함수는 async를 이용해서 동기화 해줍니다. isOn의 value가 변하면 background.js의 chrome.storage.onChanged.addListener((changes, namespace) => {콜백함수}); 가 실행되기 때문에 이 파일에서는 버튼의 글자와 storage의 상태만 변경을 해줍니다. 그후 background.js에서 리스너에의해 뱃지의 글자를 변경됩니다.

 

(5)마지막으로 scripts/content.js를 작성합니다.

// alert("'ctrl + space'로 실행버튼을 누를 수 있어요");
window.addEventListener("keydown", async function(e) {
    if (e.ctrlKey) {
        // console.log("누름")
        // console.log(e.code == "Space");
        if (e.code == "Space") {
            var status = await chrome.storage.sync.get(["isOn"]);
            // console.log("status:", status);
            if (status.isOn) {
            var 실행버튼 = document.querySelector("#run-code");
            실행버튼.click();
            }
        }
    }
})

이 파일은 현재 크롬에 켜져있는 페이지에서 작동하는 자바스크립트입니다. 프로그래머스 문제풀이 페이지에서 ctrl+space를 누르면 storage.sync의 값을 분석해서 isOn이 true면 실행버튼이 클릭되고 false면 무시하도록 만들었습니다.

 

 

2.배포

제 프로젝트의 배포과정을 설명하면 아래와 같습니다.

일단 스토어와 익스텐션 아이콘으로 사용될 4가지 크기의 아이콘을 만들어 줍니다. 프로젝트 루트폴더에서 image폴더에 해당 파일들을 저장했습니다. 이후 manifest.json에서 icon을 등록합니다.

{
    ...
    "icons": {
        "16": "images/icon-16.png",
        "32": "images/icon-32.png",
        "48": "images/icon-48.png",
        "128": "images/icon-128.png"
    },
}

이것만 해주면 이미지 등록이 완료되는 듯 합니다.

 

이제 웹스토어의 개발자 대시보드로 접속합니다.

개발자 대시보드는 여기 있습니다.

여기서 사이트가 유도하는 대로 하면 개발이 됩니다. 저 같은 경우에는 이미 개발자 등록이 되어있어서 문제가 없었지만 개발자 등록이 되어있지 않다면 6000원 정도 들것이라 생각하면 됩니다. 사이트가 유도하는대로 개발자등록을 하면 문제 없을것이라 생각합니다.

728x90
자바스크립트
프로그래머스 실행 용 크롬 확장 프로그램 제작