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 창이 열려 있는 동안 해당 창 내에 로드된 페이지에서만 사용할 수 있습니다. 콘텐츠 스크립트 및 기타 확장 프로그램 페이지는 이러한 API에 액세스할 수 없습니다.

브라우저 네임스페이스 및 DevTools 확장 프로그램

Chrome 148에서 도입된 browser 네임스페이스devtools_page를 선언하는 확장 프로그램에서 사용 중지됩니다. 선택 해제는 DevTools 페이지뿐만 아니라 확장 프로그램 API가 실행되는 모든 스크립트 컨텍스트를 포함하여 전체 확장 프로그램에 적용됩니다. 이러한 확장 프로그램 전체에서 chrome.*를 계속 사용하세요.

이유는 webextension-polyfill과의 호환성 격차입니다. chrome.devtools.* API는 콜백 전용이며 아직 Promise를 기본적으로 반환하지 않으므로 DevTools 확장 프로그램은 일반적으로 폴리필을 사용하여 래핑합니다. 폴리필은 호스트가 이미 작업을 완료했다고 가정하고 browser가 정의될 때마다 래핑을 건너뜁니다. Chrome에서 이러한 확장 프로그램에 browser를 사용 설정하면 폴리필이 no-op되고 chrome.devtools.* 호출이 Promise 반환을 중지합니다. browser를 사용 중지하면 폴리필이 계속 래핑할 수 있습니다.

동일한 선택 해제는 이러한 확장 프로그램의 다른 Chrome 148 메시지 API 변경사항도 사용 중지합니다. 다음을 포함합니다. Promise 응답runtime.onMessage 제한은 DevTools API가 Promise를 기본적으로 지원하면 해제됩니다.

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

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

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

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

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 콘솔 유틸리티 API 기능에 액세스할 수 있습니다. 예를 들어 HTML 문서의 <head> 섹션 내에서 첫 번째 스크립트 요소를 검사하는 데 사용합니다.

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

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

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

콘텐츠 스크립트는 현재 선택된 요소에 직접 액세스할 수 없습니다. 하지만 inspectedWindow.eval()을 사용하여 실행하는 모든 코드는 DevTools 콘솔 및 콘솔 유틸리티 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 객체에 대한 참조가 필요합니다. 패널의 iframe 창을 panel.onShown 이벤트 핸들러에서 가져옵니다.

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

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

콘텐츠 스크립트 없이 페이지에 직접 삽입된 코드(예: <script> 태그 추가 또는 inspectedWindow.eval() 호출)는 DevTools 페이지에 메시지를 보낼 수 없습니다.runtime.sendMessage() 대신 삽입된 스크립트를 중개자 역할을 할 수 있는 콘텐츠 스크립트와 결합하고 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를 사용하는 예를 확인할 수 있습니다.