DevTools 확장

DevTools 확장 프로그램은 확장 프로그램에 추가된 DevTools 페이지를 통해 DevTools 전용 확장 프로그램 API에 액세스하여 Chrome DevTools에 기능을 추가합니다.

검사된 창 및 서비스 워커와 통신하는 DevTools 페이지를 보여주는 아키텍처 다이어그램 서비스 워커가 콘텐츠 스크립트와 통신하고 확장 프로그램 API에 액세스하는 모습을 보여줍니다.
         DevTools 페이지에서는 DevTools API에 액세스할 수 있습니다(예: 패널 만들기).
DevTools 확장 프로그램 아키텍처.

DevTools 전용 확장 프로그램 API에는 다음이 포함됩니다.

DevTools 페이지

DevTools 창이 열리면 DevTools 확장 프로그램이 창이 열려 있는 동안 존재하는 DevTools 페이지 인스턴스를 만듭니다. 이 페이지에서는 DevTools API 및 확장 프로그램 API에 액세스할 수 있으며 다음 작업을 수행할 수 있습니다.

  • DevTools 창에 다른 확장 페이지를 패널 또는 사이드바로 추가하는 등 devtools.panels API를 사용하여 패널을 만들고 패널과 상호작용합니다.
  • devtools.inspectedWindow API를 사용하여 검사된 창에 관한 정보를 가져오고 검사된 창의 코드를 평가합니다.
  • devtools.network API를 사용하여 네트워크 요청에 관한 정보를 가져옵니다.
  • devtools.recorder API를 사용하여 Recorder 패널을 확장합니다.

DevTools 페이지는 확장 프로그램 API에 직접 액세스할 수 있습니다. 여기에는 메시지 전달을 사용하여 서비스 워커와 통신할 수 있는 기능이 포함됩니다.

DevTools 확장 프로그램 만들기

확장 프로그램용 DevTools 페이지를 만들려면 확장 프로그램 매니페스트에 devtools_page 필드를 추가합니다.

{
  "name": ...
  "version": "1.0",
  "devtools_page": "devtools.html",
  ...
}

devtools_page 필드는 HTML 페이지를 가리켜야 합니다. DevTools 페이지는 확장 프로그램에 대해 로컬이어야 하므로 상대 URL을 사용하여 지정하는 것이 좋습니다.

chrome.devtools API의 멤버는 창이 열려 있는 동안 DevTools 창 내에 로드된 페이지에서만 사용할 수 있습니다. 콘텐츠 스크립트 및 기타 확장 프로그램 페이지에서는 이러한 API에 액세스할 수 없습니다.

DevTools UI 요소: 패널 및 사이드바 창

브라우저 작업, 컨텍스트 메뉴, 팝업과 같은 일반적인 확장 프로그램 UI 요소 외에도 DevTools 확장 프로그램은 DevTools 창에 UI 요소를 추가할 수 있습니다.

  • 패널은 요소, 소스, 네트워크 패널과 같은 최상위 탭입니다.
  • 사이드바 창은 패널과 관련된 보조 UI를 표시합니다. Elements 패널의 Styles, Computed Styles, Event Listeners 창이 사이드바 창의 예입니다. 사용 중인 Chrome 버전과 DevTools 창이 도킹된 위치에 따라 사이드바 창이 다음 예시 이미지와 같이 표시될 수 있습니다.
Elements 패널과 Styles 사이드바 창이 표시된 DevTools 창
Elements 패널과 Styles 사이드바 창이 표시된 DevTools 창

각 패널은 자체 HTML 파일이며 다른 리소스 (자바스크립트, CSS, 이미지 등)를 포함할 수 있습니다. 기본 패널을 만들려면 다음 코드를 사용하세요.

chrome.devtools.panels.create("My Panel",
    "MyPanelIcon.png",
    "Panel.html",
    function(panel) {
      // code invoked on panel creation
    }
);

패널 또는 사이드바 창에서 실행된 JavaScript는 DevTools 페이지와 동일한 API에 액세스할 수 있습니다.

기본 사이드바 창을 만들려면 다음 코드를 사용합니다.

chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
    function(sidebar) {
        // sidebar initialization code here
        sidebar.setObject({ some_data: "Some data to show" });
});

메뉴 창에 콘텐츠를 표시하는 방법에는 여러 가지가 있습니다.

  • HTML 콘텐츠: setPage()를 호출하여 창에 표시할 HTML 페이지를 지정합니다.
  • JSON 데이터: JSON 객체를 setObject()에 전달합니다.
  • 자바스크립트 표현식: 표현식을 setExpression()에 전달합니다. DevTools는 검사된 페이지의 컨텍스트에서 표현식을 평가한 후 반환 값을 표시합니다.

setObject()setExpression()의 경우 모두 DevTools 콘솔에 표시된 대로 창에 값이 표시됩니다. 그러나 setExpression()를 사용하면 DOM 요소와 임의의 JavaScript 객체를 표시할 수 있으며 setObject()는 JSON 객체만 지원합니다.

확장 구성요소 간 통신

다음 섹션에서는 DevTools 확장 프로그램 구성요소가 서로 통신할 수 있도록 하는 유용한 방법을 설명합니다.

콘텐츠 스크립트 삽입

콘텐츠 스크립트를 삽입하려면 scripting.executeScript()을 사용합니다.

// DevTools page -- devtools.js
chrome.scripting.executeScript({
  target: {
    tabId: chrome.devtools.inspectedWindow.tabId
  },
  files: ["content_script.js"]
});

inspectedWindow.tabId 속성을 사용하여 검사된 창의 탭 ID를 가져올 수 있습니다.

콘텐츠 스크립트가 이미 삽입된 경우 메시징 API를 사용하여 스크립트와 통신할 수 있습니다.

검사된 창에서 자바스크립트 평가

inspectedWindow.eval() 메서드를 사용하여 검사된 페이지의 컨텍스트에서 JavaScript 코드를 실행할 수 있습니다. DevTools 페이지, 패널, 사이드바 창에서 eval() 메서드를 호출할 수 있습니다.

기본적으로 표현식은 페이지의 메인 프레임 컨텍스트에서 평가됩니다. inspectedWindow.eval()는 DevTools 콘솔에 입력된 코드와 동일한 스크립트 실행 컨텍스트 및 옵션을 사용하므로 eval() 사용 시 DevTools Console Utilities API 기능에 액세스할 수 있습니다. 예를 들어 SOAK는 이를 사용하여 요소를 검사합니다.

chrome.devtools.inspectedWindow.eval(
  "inspect($$('head script[data-soak=main]')[0])",
  function(result, isException) { }
);

inspectedWindow.eval()를 호출하여 콘텐츠 스크립트와 동일한 컨텍스트에서 표현식을 평가할 때 useContentScriptContexttrue로 설정할 수도 있습니다. 이 옵션을 사용하려면 eval()를 호출하기 전에 executeScript()를 호출하거나 manifest.json 파일에 콘텐츠 스크립트를 지정하여 정적 콘텐츠 스크립트 선언을 사용합니다. 컨텍스트 스크립트 컨텍스트가 로드된 후 이 옵션을 사용하여 추가 콘텐츠 스크립트를 삽입할 수도 있습니다.

선택한 요소를 콘텐츠 스크립트에 전달

콘텐츠 스크립트가 현재 선택된 요소에 직접 액세스할 수 없습니다. 하지만 inspectedWindow.eval()를 사용하여 실행하는 모든 코드는 DevTools 콘솔과 Console 유틸리티 API에 액세스할 수 있습니다. 예를 들어 평가된 코드에서 $0를 사용하면 선택된 요소에 액세스할 수 있습니다.

선택한 요소를 콘텐츠 스크립트에 전달하는 방법:

  1. 콘텐츠 스크립트에서 선택한 요소를 인수로 사용하는 메서드를 만듭니다.

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. inspectedWindow.eval()useContentScriptContext: true 옵션과 함께 사용하여 DevTools 페이지에서 메서드를 호출합니다.

    chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
        { useContentScriptContext: true });
    

useContentScriptContext: true 옵션은 setSelectedElement 메서드에 액세스할 수 있도록 표현식을 콘텐츠 스크립트와 동일한 컨텍스트에서 평가해야 한다고 지정합니다.

참조 패널의 window 가져오기

devtools 패널에서 postMessage()를 호출하려면 window 객체에 대한 참조가 필요합니다. panel.onShown 이벤트 핸들러에서 패널의 iframe 창을 가져옵니다.

extensionPanel.onShown.addListener(function (extPanelWindow) {
    extPanelWindow instanceof Window; // true
    extPanelWindow.postMessage( // …
});

삽입된 스크립트에서 DevTools 페이지로 메시지 전송

<script> 태그를 추가하거나 inspectedWindow.eval()를 호출하는 등 콘텐츠 스크립트 없이 페이지에 직접 삽입된 코드는 runtime.sendMessage()를 사용하여 DevTools 페이지에 메시지를 보낼 수 없습니다. 대신 삽입된 스크립트를 중개자 역할을 할 수 있는 콘텐츠 스크립트와 결합하고 window.postMessage() 메서드를 사용하는 것이 좋습니다. 다음 예에서는 이전 섹션의 백그라운드 스크립트를 사용합니다.

// injected-script.js

window.postMessage({
  greeting: 'hello there!',
  source: 'my-devtools-extension'
}, '*');
// content-script.js

window.addEventListener('message', function(event) {
  // Only accept messages from the same frame
  if (event.source !== window) {
    return;
  }

  var message = event.data;

  // Only accept messages that we know are ours. Note that this is not foolproof
  // and the page can easily spoof messages if it wants to.
  if (typeof message !== 'object' || message === null ||
      message.source !== 'my-devtools-extension') {
    return;
  }

  chrome.runtime.sendMessage(message);
});

다른 대체 메시지 전달 기술은 GitHub에서 확인할 수 있습니다.

DevTools가 열리고 닫힐 때 감지

DevTools 창이 열려 있는지 추적하려면 onConnect 리스너를 서비스 워커에 추가하고 DevTools 페이지에서 connect()를 호출합니다. 각 탭에서 자체 DevTools 창을 열 수 있으므로 여러 연결 이벤트를 수신할 수 있습니다. DevTools 창이 열려 있는지 추적하려면 다음 예와 같이 연결 및 연결 해제 이벤트를 계산합니다.

// background.js
var openCount = 0;
chrome.runtime.onConnect.addListener(function (port) {
    if (port.name == "devtools-page") {
      if (openCount == 0) {
        alert("DevTools window opening.");
      }
      openCount++;

      port.onDisconnect.addListener(function(port) {
          openCount--;
          if (openCount == 0) {
            alert("Last DevTools window closing.");
          }
      });
    }
});

DevTools 페이지는 다음과 같이 연결을 생성합니다.

// devtools.js

// Create a connection to the service worker
const serviceWorkerConnection = chrome.runtime.connect({
    name: "devtools-page"
});

// Send a periodic heartbeat to keep the port open.
setInterval(() => {
  port.postMessage("heartbeat");
}, 15000);

DevTools 확장 프로그램 예시

이 페이지의 예는 다음 페이지에서 가져온 것입니다.

  • Polymer Devtools 확장 프로그램 - 호스트 페이지에서 실행되는 여러 도우미를 사용하여 DOM/JS 상태를 쿼리하고 맞춤 패널로 다시 보냅니다.
  • React DevTools 확장 프로그램 - 렌더기의 하위 모듈을 사용하여 DevTools UI 구성요소를 재사용합니다.
  • Ember Inspector - Chrome 및 Firefox용 어댑터가 포함된 공유 확장 프로그램 코어입니다.
  • Coquette-inspect - 디버깅 에이전트가 호스트 페이지에 삽입된 깔끔한 React 기반 확장 프로그램입니다.
  • 샘플 확장 프로그램에는 설치하고 사용해 보고 학습할 가치가 있는 확장 프로그램이 더 있습니다.

추가 정보

확장 프로그램이 사용할 수 있는 표준 API에 관한 자세한 내용은 chrome.* API웹 API를 사용합니다.

의견 보내기 의견과 제안은 API를 개선하는 데 도움이 됩니다.

샘플에서 DevTools API를 사용하는 예를 확인할 수 있습니다.