본문 바로가기
프로그래밍/자바스크립트

프로그래밍 「 자바스크립트 편」Chrome 확장 프로그램 개발을 위한 고급 기술: 종합 가이드

by grapedoukan 2023. 6. 17.
728x90

이 기사에서는 Chrome 확장 프로그램 개발 프로세스를 크게 향상시킬 수 있는 몇 가지 고급 개념과 방법에 대해 설명합니다. 이러한 귀중한 통찰력은 단일 소스에서 쉽게 찾을 수 없으므로 이 문서는 개발 워크플로를 단순화하는 데 유용한 참고 자료가 됩니다.

웹 페이지에서 CSS 선택기를 추출할 수 있는 웹 스크레이퍼를 만드는 방법을 안내해 드리겠습니다.

이 확장에서 필요한 기능은 다음과 같습니다.

  1. 프론트엔드 애플리케이션은 React 애플리케이션입니다. 사용자는 데이터를 스크랩해야 하는 웹사이트 URL을 입력해야 합니다.
  2. 지정된 URL로 팝업 창이 열립니다.
  3. 사용자는 드래그 가능한 봇을 볼 수 있습니다.
  4. 사용자는 봇에서 텍스트 캡처 기능을 사용하도록 설정할 수 있습니다.
  5. 그런 다음 사용자는 웹 페이지에서 다양한 HTML 요소를 선택할 수 있습니다.
  6. 사용자가 데이터를 추출하면 일부 데모 데이터가 포함된 추출된 CSS 선택기를 React 앱으로 다시 전송하여 추출된 데이터가 사용자에게 올바른지 또는 올바르지 않은지 확인해야 합니다.
  7. 사용자가 데이터가 정확하다는 것을 수락하면 CSS 선택기를 백엔드로 보내고 해당 선택기를 사용하여 데이터를 크롤링합니다.

여기서는 HTML 요소 선택에 초점을 맞추지 않고 일부 데모 데이터를 추출하고 draggable bot.these를 개발하여 dom 조작에 대한 지식을 사용하여 개발할 수 있습니다.

주로 여러 콘텐츠 스크립트 실행, 팝업 창 열기, 외부 메시징, 내부 메시징 및 두 콘텐츠 스크립트 간의 메시징 , 데이터를 프론트엔드 애플리케이션으로 다시 보내는 데 중점을 둘 것입니다.

다음 이미지는 우리가 이야기 할 프로세스의 아키텍처를 보여줍니다.

기본을 이해하는 것이 가장 중요합니다!

주제에 대해 자세히 알아보기 전에 Chrome 확장 프로그램 개발의 기본 아키텍처를 이해해야 합니다. 여기에 몇 가지 고급 주제에 초점을 맞추기 때문에 이 링크를 따라 기본 사항을 배울 수 있습니다.

이제 주제를 탐구해 보겠습니다.

계속 진행하기 전에 예제로 사용하는 확장은 Angular 또는 React와 같은 라이브러리나 프레임워크를 사용하지 않고 순전히 HTML, CSS 및 JavaScript로 작성되었다는 점에 유의하는 것이 중요합니다. 다음은 폴더 구조입니다.

기본 Chrome 웹 확장 프로그램의 폴더 구조

1. 브라우저가 웹 앱을 로드할 때 contentscript를 실행합니다.

매니페스트 파일에서 특정 URL에 대한 특정 콘텐츠 스크립트의 실행을 지정할 수 있습니다.

매니페스트 파일의 지정된 URL에서 컨텐츠 스크립트의 실행을 정의하려면 필드를 사용할 수 있습니다. 수행 방법의 예는 다음과 같습니다.content_scripts

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": ["https://localhost:3000/add-new-data"],
      "js": ["content_script_0.js"]
    }
  ],
  "permissions": [
    "tabs"
  ]
}

이 콘텐츠 스크립트를 실행하는 목적은 끝에 도달하면 명확해질 것입니다

2. 팝업 창을 열기 위해 메시지를 보냅니다. background.js

다음 패키지가 반응 앱에 설치되어 있어야 합니다.

"@types/chrome": "^0.0.212",
chrome.runtime.sendMessage(editorExtensionId, { 
  url: "www.example.com"
}, function(response) {
  if (!response.success) {
    setCompetitor(null);
  }

});

위의 코드는 Chrome API를 사용하여 URL이 포함된 객체와 함께 확장 프로그램에 메시지를 보내는 방법을 설명합니다.

3. 팝업 창을 열고 초기 콘텐츠 스크립트를 실행합니다.

메시지가 React App 에서 전송되었으므로 이를 확장 프로그램으로 가져오려고 합니다. 크롬 확장의 통신 부분은 백그라운드.js 파일에 의해 완전히 처리됩니다. 외부 통신 또는 내부 통신 (두 콘텐츠 스크립트 간, 팝업과 콘텐츠 스크립트 간). 그래서 우리는 외부 자원에서 오는 메시지를 들어야 합니다.

chrome.runtime.onMessageExternal.addListener(function (request, sender, sendResponse) {
  var tab_id;
  if (request.url) {
    chrome.windows.create({ url: request.url, type: 'popup' }, function (window) {
      tab_id = window.tabs[0].id;
    });
...

위는 외부 메시지를 듣고 팝업 창을 만드는 방법입니다. 이제 열린 창에서 해당 페이지의 콘텐츠 스크립트를 실행해야 합니다.

chrome.runtime.onMessageExternal.addListener(function (request, sender, sendResponse) {
  var tab_id;
  if (request.url) {
    chrome.windows.create({ url: request.url, type: 'popup' }, function (window) {
      tab_id = window.tabs[0].id;
    });
    chrome.tabs.onUpdated.addListener(function (tabId, info) {
      if (tabId == tab_id && info.url) {
        chrome.scripting.insertCSS(
          {
            target: { tabId: tab_id },
            files: ['styles/contentScript_1.style.css'],
          },
          () => {
            chrome.scripting.executeScript({
              target: { tabId: tab_id },
              files: ['content-scripts/contentScript_1.js'],
            });
          }
        );
      }
    });
  }

위의 코드 스니펫은 Chrome 확장 프로그램에서 외부 메시지에 대한 리스너를 설정합니다. 비어 있지 않은 URL 속성이 있는 외부 메시지가 수신되면 팝업 역할을 하는 단일 탭이 있는 새 창이 만들어집니다. 창에 있는 첫 번째 탭의 ID는 변수에 저장됩니다. 그런 다음 코드는 탭의 업데이트, 특히 URL의 변경 내용을 수신 대기합니다. 저장된 ID와 일치하는 탭에서 URL 업데이트가 발생하면 코드는 CSS 및 JavaScript 파일을 탭에 삽입합니다. 이렇게 하면 수신된 URL을 기반으로 탭의 모양과 동작을 동적으로 수정할 수 있습니다.

4. 해당 콘텐츠 스크립트에서 다른 콘텐츠 스크립트를 실행합니다.

콘텐츠 스크립트 내에서 다른 콘텐츠 스크립트를 실행하는 것은 봇의 기능에서 유용한 기능입니다. 봇의 주요 기능 중 하나는 텍스트 캡처 옵션으로, 텍스트 캡처 처리 전용의 다른 콘텐츠 스크립트를 호출하여 트리거할 수 있습니다. 이 프로세스는 현재 콘텐츠 스크립트와 파일 간의 조정을 통해 수행됩니다.background.js

텍스트 캡처 콘텐츠 스크립트의 실행을 시작하기 위해 현재 콘텐츠 스크립트는 다음 코드 조각을 사용하여 백그라운드.js 파일에 메시지를 보냅니다.

chrome.runtime.sendMessage({ message: 'EXCONTENT', content: clonedHtmlContent }, function (response) {
  return true;
});

위의 코드가 하는 일은 Content 와 함께 백그라운드.js 메시지를 보내는 것입니다.

이것이 우리가 백그라운드에서 그 메시지를 듣는 방법입니다. 여기서 우리는 내부 conmmunication 이후 onMessage를 사용했습니다.

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.message === 'EXCONTENT') {
    // Code to handle the execution of the new content script in the same tab
    // ...
  }
});

이 코드는 콘텐츠 스크립트에서 들어오는 메시지를 캡처하는 데 사용하는 이벤트 수신기를 설정합니다. 지정된 메시지 유형('EXCONTENT')의 메시지가 수신되면 해당 코드 블록이 실행되어 필요한 작업을 수행할 수 있습니다.chrome.runtime.onMessage.addListener

5. 데이터를 React 프론트엔드 애플리케이션으로 다시 보내고 해당 애플리케이션의 데이터에 액세스하여 백엔드 API와 함께 보냅니다.

이것은 우리가 첫 번째 단계에서 언급 한 콘텐츠 스크립트의 존재를 요구하는 지점입니다. 현재 우리는 백그라운드.js 파일 내에 데이터를 보유하고 있으며 우리의 목표는 이를 React 애플리케이션으로 전송하는 것입니다. 이를 위해서는 원하는 URL(https://localhost:3000/rout)에 해당하는 탭을 쿼리하고 해당 탭으로 데이터를 보내야 합니다.

  chrome.tabs.query({ url: 'http://localhost:3000/{route}', discarded: false }, function (result) {
      if (result.length === 1) {
        var tab = result[0];
//we execute the content script again from here also to verify its running not to loss the data
        chrome.scripting.executeScript({
          target: { tabId: tab.id },
          files: ['content-scripts/{main-name}.js'],
        }, () => {
          chrome.tabs.sendMessage(
            tab.id,
            { data: request.data},
            function (response) {
              sendResponse(response);
              return true;
            }
          );

//this code closes the current popup window which is not needed anymore.
          chrome.windows.getCurrent(function (currentWindow) {
            chrome.windows.remove(currentWindow.id);
          });
        });

      }
    });
}

(교차 출처 정책으로 인해 사용할 수 없습니다.)

6. 데이터를 가져와 React 애플리케이션으로 보내기

이제 애플리케이션의 URL에서 실행 중인 콘텐츠 스크립트는 이 메시지를 수신하고 데이터를 가져와야 합니다.여기에서 이 데이터로 사용자 지정 이벤트를 만들어 반응 앱으로 보내야 합니다.


chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  // Check if the message is what you're expecting
  if (message.type === 'data') {
    const data = message.data;
    // Process the data or perform any necessary operations
    // Create a Custom Event and dispatch it to the React app
    const event = new CustomEvent('myCustomEvent', { detail: data });
    document.dispatchEvent(event);
  }
});

React 애플리케이션에서 Custom Event를 수신하고 적절하게 처리해야 합니다. 우리는 할 수 있습니다 이벤트 리스너 적절한 구성 요소, 예를 들어 이와 같은 기본 구성 요소.App

import React, { useEffect } from 'react';

function App() {
  useEffect(() => {
    const handleCustomEvent = (event) => {
      const data = event.detail;
      // Handle the data received from the content script
      console.log(data);
      // Perform any necessary actions with the data
    };

    // Add an event listener for the Custom Event
    document.addEventListener('myCustomEvent', handleCustomEvent);

    // Clean up the event listener when the component unmounts
    return () => {
      document.removeEventListener('myCustomEvent', handleCustomEvent);
    };
  }, []);

  return (
    <div>
      {/* Your React app content */}
    </div>
  );
}

export default App;

위의 모든 사항에 대해 외부 또는 내부 통신을 위해 manifest.json 파일의 권한을 부여해야 합니다.

{
  "name": "Scraper",
  "version": "0.1.0",
  "permissions": [
    "tabs",
    "scripting",
    "activeTab",
    "alarms",
    "declarativeContent"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["http://localhost:3000"],
      "js": ["content-scripts/{main}.js"]
    }
  ],
  "icons": {
    "128": "assets/robot.png"
  },
  "manifest_version": 3
}

그래서 이것은 우리 기사의 끝을 표시합니다. Chrome 확장 프로그램을 만들기 위한 고급 기술에 대한 아이디어를 얻으셨기를 바랍니다.

728x90