DevTools 확장

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

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

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

DevTools 페이지

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

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

DevTools 확장 프로그램 만들기

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

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

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

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

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

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

  • 패널은 요소, 소스, 네트워크 패널과 같은 최상위 탭입니다.
  • 측면 패널은 패널과 관련된 보조 UI를 표시합니다. 요소 패널의 스타일, 계산된 스타일, 이벤트 리스너 창은 사이드바 창의 예입니다. 사용 중인 Chrome 버전과 DevTools 창이 도킹된 위치에 따라 사이드바 창이 다음 예시 이미지와 같이 표시될 수 있습니다.
Elements 패널과 Styles 사이드바 창이 표시된 DevTools 창
Elements 패널과 Styles 사이드바 창을 보여주는 DevTools 창

각 패널은 자체 HTML 파일이며 여기에는 다른 리소스 (JavaScript, 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()에 전달합니다.
  • JavaScript 표현식: 표현식을 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를 사용하여 콘텐츠 스크립트와 통신할 수 있습니다.

검사된 창에서 JavaScript 평가

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

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

콘텐츠 스크립트는 현재 선택된 요소에 직접 액세스할 수 없습니다. 그러나 inspectedWindow.eval()를 사용하여 실행하는 모든 코드는 DevTools 콘솔 및 Console Utilities API에 액세스할 수 있습니다. 예를 들어 평가된 코드에서 $0를 사용하여 선택한 요소에 액세스할 수 있습니다.

선택한 요소를 콘텐츠 스크립트에 전달하는 방법은 다음과 같습니다.

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

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. useContentScriptContext: true 옵션과 함께 inspectedWindow.eval()를 사용하여 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를 사용하는 예시는 샘플에서 확인할 수 있습니다.