사용자 인터페이스 디자인

확장 프로그램 사용자 인터페이스는 목적이 있으며 간결해야 합니다. 확장 프로그램 자체와 마찬가지로 UI는 방해 없이 탐색 환경을 맞춤설정하거나 개선해야 합니다.

이 가이드에서는 필수 및 선택적 사용자 인터페이스 기능을 살펴봅니다. 이를 통해 확장 프로그램 내에서 다양한 UI 요소를 구현하는 방법과 시기를 파악할 수 있습니다.

모든 페이지에서 확장 프로그램 활성화

확장 프로그램의 기능이 대부분의 상황에서 작동하는 경우 browser_action을 사용합니다.

브라우저 작업 등록

"browser_action" 필드는 매니페스트에 등록됩니다.

{
  "name": "My Awesome browser_action Extension",
  ...
  "browser_action": {
    ...
  }
  ...
}

"browser_action"를 선언하면 아이콘의 색상이 유지되어 사용자가 확장 프로그램을 사용할 수 있음을 나타냅니다.

배지 추가

배지는 브라우저 아이콘 위에 최대 4자의 컬러 배너가 표시됩니다. 매니페스트에서 "browser_action"를 선언하는 확장 프로그램에서만 사용할 수 있습니다.

배지를 사용하여 확장 프로그램의 상태를 나타냅니다. Drink Water Event 샘플에서는 사용자가 알람을 성공적으로 설정했음을 나타내는 'ON' 배지가 표시되고 확장 프로그램이 유휴 상태일 때는 아무 것도 표시되지 않습니다.

배지 사용

배지 꺼짐

chrome.browserAction.setBadgeText를 호출하여 배지의 텍스트를 설정하고 chrome.browserAction.setBadgeBackgroundColor를 호출하여 배너 색상을 설정합니다 .

chrome.browserAction.setBadgeText({text: 'ON'});
chrome.browserAction.setBadgeBackgroundColor({color: '#4688F1'});

일부 페이지에서 확장 프로그램 활성화

정의된 상황에서만 확장 프로그램의 기능을 사용할 수 있는 경우 page_action을 사용하세요.

페이지 액션 선언

"page_action" 필드는 매니페스트에 등록됩니다.

{
  "name": "My Awesome page_action Extension",
  ...
  "page_action": {
    ...
  }
  ...
}

"page_action"를 선언하면 사용자가 확장 프로그램을 사용할 수 있을 때만 아이콘 색상이 지정되며, 그렇지 않으면 그레이 스케일로 표시됩니다.

활성 페이지 작업 아이콘

사용할 수 없는 페이지 작업 아이콘

확장 프로그램 활성화를 위한 규칙 정의

백그라운드 스크립트runtime.onInstalled 리스너에서 chrome.declarativeContent를 호출하여 확장 프로그램을 사용할 수 있는 시점에 관한 규칙을 정의합니다. URL별 페이지 작업 샘플 확장 프로그램은 URL에 'g'가 포함되어야 한다는 조건을 설정합니다. 조건이 충족되면 확장 프로그램이 declarativeContent.ShowPageAction()를 호출합니다.

chrome.runtime.onInstalled.addListener(function() {
  // Replace all rules ...
  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
    // With a new rule ...
    chrome.declarativeContent.onPageChanged.addRules([
      {
        // That fires when a page's URL contains a 'g' ...
        conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { urlContains: 'g' },
          })
        ],
        // And shows the extension's page action.
        actions: [ new chrome.declarativeContent.ShowPageAction() ]
      }
    ]);
  });
});

확장 프로그램 사용 또는 사용 중지

"page_action"를 사용하는 확장 프로그램은 pageAction.showpageAction.hide를 호출하여 동적으로 활성화 및 사용 중지할 수 있습니다.

Mappy 샘플 확장 프로그램은 웹페이지에서 주소를 스캔하고 팝업의 정적 지도에 위치를 표시합니다. 확장 프로그램은 페이지 콘텐츠에 따라 달라지므로 관련성 있는 페이지를 예측하는 규칙을 선언할 수 없습니다. 대신 페이지에서 주소가 발견되면 pageAction.show를 호출하여 아이콘을 색칠하고 해당 탭에서 확장 프로그램을 사용할 수 있음을 알립니다.

chrome.runtime.onMessage.addListener(function(req, sender) {
  chrome.storage.local.set({'address': req.address})
  chrome.pageAction.show(sender.tab.id);
  chrome.pageAction.setTitle({tabId: sender.tab.id, title: req.address});
});

확장 프로그램 아이콘 제공

확장 프로그램을 표시하려면 아이콘이 하나 이상 필요합니다. 최상의 시각적 결과를 얻으려면 PNG 형식의 아이콘을 제공해야 하지만 BMP, GIF, ICO, JPEG 등 WebKit에서 지원하는 모든 형식이 허용됩니다.

툴바 아이콘 지정

툴바와 관련된 아이콘은 매니페스트의 browser_action 또는 page_action 아래의 "default_icon" 필드에 등록됩니다. 16 딥 공간에 맞게 확장하려면 여러 크기를 포함하는 것이 좋습니다. 최소 16x16 및 32x32 크기를 사용하는 것이 좋습니다.

{
  "name": "My Awesome page_action Extension",
  ...
  "page_action": {
    "default_icon": {
      "16": "extension_toolbar_icon16.png",
      "32": "extension_toolbar_icon32.png"
    }
  }
  ...
}

모든 아이콘은 정사각형이어야 하며 그렇지 않으면 왜곡될 수 있습니다. 아이콘이 제공되지 않으면 Chrome은 툴바에 일반 아이콘을 추가합니다.

추가 아이콘 생성 및 등록

툴바 외부에서 사용하기 위해 다음 크기의 추가 아이콘을 포함합니다.

아이콘 크기아이콘 사용
16x16확장 프로그램 페이지의 파비콘
32x32Windows 컴퓨터에 이 크기가 필요한 경우가 많습니다. 이 옵션을 제공하면 48x48 옵션이 크기 왜곡으로 인해 축소되는 것을 방지할 수 있습니다.
48x48확장 프로그램 관리 페이지에 표시됨
128x128설치 시 및 Chrome 웹 스토어에 표시됨

매니페스트의 "icons" 필드 아래에 아이콘을 등록합니다.

{
  "name": "My Awesome Extension",
  ...
  "icons": {
    "16": "extension_icon16.png",
    "32": "extension_icon32.png",
    "48": "extension_icon48.png",
    "128": "extension_icon128.png"
  }
  ...
}

추가 UI 기능

팝업은 사용자가 툴바 아이콘을 클릭하면 특수 창에 표시되는 HTML 파일입니다. 팝업은 웹페이지와 매우 유사하게 작동하는데, 스타일시트와 스크립트 태그 링크를 포함할 수 있지만 인라인 자바스크립트는 허용하지 않습니다.

Drink Water Event 예시 팝업에 사용 가능한 타이머 옵션이 표시됩니다. 사용자는 제공된 버튼 중 하나를 클릭하여 알람을 설정합니다.

팝업 샘플 스크린샷

<html>
  <head>
    <title>Water Popup</title>
  </head>
  <body>
      <img src='./stay_hydrated.png' id='hydrateImage'>
      <button id='sampleSecond' value='0.1'>Sample Second</button>
      <button id='15min' value='15'>15 Minutes</button>
      <button id='30min' value='30'>30 Minutes</button>
      <button id='cancelAlarm'>Cancel Alarm</button>
    <script src="popup.js"></script>
  </body>
</html>

팝업은 매니페스트에 브라우저 작업 또는 페이지 작업 아래에 등록될 수 있습니다.

{
  "name": "Drink Water Event",
  ...
  "browser_action": {
    "default_popup": "popup.html"
  }
  ...
}

browserAction.setPopup 또는 pageAction.setPopup를 호출하여 팝업을 동적으로 설정할 수도 있습니다.

chrome.storage.local.get('signed_in', function(data) {
  if (data.signed_in) {
    chrome.browserAction.setPopup({popup: 'popup.html'});
  } else {
    chrome.browserAction.setPopup({popup: 'popup_sign_in.html'});
  }
});

도움말

도움말을 사용하여 사용자에게 브라우저 아이콘 위로 마우스를 가져가면 간단한 설명이나 안내를 제공합니다.

예시 도움말의 스크린샷

도움말은 매니페스트의 "default_title" 필드 browser_action 또는 page_action에 등록됩니다.

{
"name": "Tab Flipper",
  ...
  "browser_action": {
    "default_title": "Press Ctrl(Win)/Command(Mac)+Shift+Right/Left to flip tabs"
  }
...
}

browserAction.setTitlepageAction.setTitle를 호출하여 도움말을 설정하거나 업데이트할 수도 있습니다.

chrome.browserAction.onClicked.addListener(function(tab) {
  chrome.browserAction.setTitle({tabId: tab.id, title: "You are on tab:" + tab.id});
});

특수한 언어 문자열은 국제화로 구현됩니다. 다음과 같이 _locales라는 폴더 내에 언어별 메시지를 보관할 디렉터리를 만듭니다.

  • _locales/en/messages.json
  • _locales/es/messages.json

각 언어의 messages.json 내부에 있는 메일의 서식을 지정합니다.

{
  "__MSG_tooltip__": {
      "message": "Hello!",
      "description": "Tooltip Greeting."
  }
}
{
  "__MSG_tooltip__": {
      "message": "Hola!",
      "description": "Tooltip Greeting."
  }
}

현지화를 사용 설정하려면 메시지 대신 도움말 필드에 메시지 이름을 포함합니다.

{
"name": "Tab Flipper",
  ...
  "browser_action": {
    "default_title": "__MSG_tooltip__"
  }
...
}

검색주소창

사용자는 검색주소창을 통해 확장 프로그램 기능을 호출할 수 있습니다. 매니페스트에 "omnibox" 필드를 포함하고 키워드를 지정합니다. 검색주소창 새 탭 검색 샘플 확장 프로그램은 'nt'를 키워드로 사용합니다.

{
  "name": "Omnibox New Tab Search",\
  ...
  "omnibox": { "keyword" : "nt" },
  "default_icon": {
    "16": "newtab_search16.png",
    "32": "newtab_search32.png"
  }
  ...
}

사용자가 검색창에 'nt'를 입력하면 확장 프로그램이 활성화됩니다. 사용자에게 이를 알리기 위해 제공된 16x16 크기의 아이콘을 회색으로 조정한 후 확장 프로그램 이름 옆의 검색주소창에서 아이콘을 표시합니다.

활성 검색주소창 확장 프로그램

확장 프로그램은 omnibox.onInputEntered 이벤트를 수신 대기합니다. 트리거되면 확장 프로그램은 사용자 항목에 대한 Google 검색이 포함된 새 탭을 엽니다.

chrome.omnibox.onInputEntered.addListener(function(text) {
  // Encode user input for special characters , / ? : @ & = + $ #
  var newURL = 'https://www.google.com/search?q=' + encodeURIComponent(text);
  chrome.tabs.create({ url: newURL });
});

컨텍스트 메뉴

매니페스트에서 "contextMenus" 권한을 부여하여 새 컨텍스트 메뉴 옵션을 추가합니다.

{
  "name": "Global Google Search",
  ...
  "permissions": [
    "contextMenus",
    "storage"
  ],
  "icons": {
    "16": "globalGoogle16.png",
    "48": "globalGoogle48.png",
    "128": "globalGoogle128.png"
  }
  ...
}

16x16 아이콘이 새 메뉴 항목 옆에 표시됩니다.

컨텍스트 메뉴 아이콘

백그라운드 스크립트에서 contextMenus.create를 호출하여 컨텍스트 메뉴를 만듭니다. 이 작업은 runtime.onInstalled 리스너 이벤트 아래에서 실행해야 합니다.

chrome.runtime.onInstalled.addListener(function() {
  for (let key of Object.keys(kLocales)) {
    chrome.contextMenus.create({
      id: key,
      title: kLocales[key],
      type: 'normal',
      contexts: ['selection'],
    });
  }
});
const kLocales = {
  'com.au': 'Australia',
  'com.br': 'Brazil',
  'ca': 'Canada',
  'cn': 'China',
  'fr': 'France',
  'it': 'Italy',
  'co.in': 'India',
  'co.jp': 'Japan',
  'com.ms': 'Mexico',
  'ru': 'Russia',
  'co.za': 'South Africa',
  'co.uk': 'United Kingdom'
};

글로벌 Google 검색 컨텍스트 메뉴 예에서는 locales.js의 목록에서 여러 옵션을 만듭니다 . 확장 프로그램에 컨텍스트 메뉴가 2개 이상 포함되어 있으면 Chrome에서 이를 자동으로 단일 상위 메뉴로 축소합니다.

여러 컨텍스트 메뉴가 접힙니다

명령어

확장 프로그램은 특정 명령어를 정의하고 이를 키 조합에 결합할 수 있습니다. 매니페스트의 "commands" 필드에 하나 이상의 명령어를 등록합니다.

{
  "name": "Tab Flipper",
  ...
  "commands": {
    "flip-tabs-forward": {
      "suggested_key": {
        "default": "Ctrl+Shift+Right",
        "mac": "Command+Shift+Right"
      },
      "description": "Flip tabs forward"
    },
    "flip-tabs-backwards": {
      "suggested_key": {
        "default": "Ctrl+Shift+Left",
        "mac": "Command+Shift+Left"
      },
      "description": "Flip tabs backwards"
    }
  }
  ...
}

명령어를 사용하여 새 브라우저 단축키 또는 대체 브라우저 단축키를 제공할 수 있습니다. Tab Flipper 샘플 확장 프로그램은 백그라운드 스크립트commands.onCommand 이벤트를 수신 대기하고 등록된 각 조합의 기능을 정의합니다.

chrome.commands.onCommand.addListener(function(command) {
  chrome.tabs.query({currentWindow: true}, function(tabs) {
    // Sort tabs according to their index in the window.
    tabs.sort((a, b) => { return a.index < b.index; });
    let activeIndex = tabs.findIndex((tab) => { return tab.active; });
    let lastTab = tabs.length - 1;
    let newIndex = -1;
    if (command === 'flip-tabs-forward')
      newIndex = activeIndex === 0 ? lastTab : activeIndex - 1;
    else  // 'flip-tabs-backwards'
      newIndex = activeIndex === lastTab ? 0 : activeIndex + 1;
    chrome.tabs.update(tabs[newIndex].id, {active: true, highlighted: true});
  });
});

명령어를 통해 확장 프로그램과 특별히 함께 작동하는 키 바인딩을 만들 수도 있습니다. Hello Extensions 예에서는 팝업을 여는 명령어를 제공합니다.

{
  "name": "Hello Extensions",
  "description" : "Base Level Extension",
  "version": "1.0",
  "browser_action": {
    "default_popup": "hello.html",
    "default_icon": "hello_extensions.png"
  },
  "manifest_version": 2,
  "commands": {
    "_execute_browser_action": {
      "suggested_key": {
        "default": "Ctrl+Shift+F",
        "mac": "MacCtrl+Shift+F"
      },
      "description": "Opens hello.html"
    }
  }
}

확장 프로그램은 browser_action를 정의하므로 백그라운드 스크립트를 포함하지 않고 팝업 파일을 여는 명령어에 "execute_browser_action"를 지정할 수 있습니다. page_action를 사용하는 경우 "execute_page_action"로 대체할 수 있습니다. 브라우저 명령어와 확장 프로그램 명령어를 동일한 확장 프로그램에서 사용할 수 있습니다.

페이지 재정의

확장 프로그램은 방문 기록, 새 탭 또는 북마크 웹페이지를 맞춤 HTML 파일로 재정의하고 대체할 수 있습니다. 팝업과 마찬가지로 특수 로직과 스타일을 포함할 수 있지만 인라인 JavaScript는 허용하지 않습니다. 단일 광고 확장은 가능한 3개 페이지 중 하나만 재정의하도록 제한됩니다.

매니페스트의 "chrome_url_overrides" 필드에 재정의 페이지를 등록합니다.

{
  "name": "Awesome Override Extension",
  ...

  "chrome_url_overrides" : {
    "newtab": "override_page.html"
  },
  ...
}

페이지를 재정의할 때 "newtab" 필드를 "bookmarks" 또는 "history"로 대체해야 합니다.

<html>
  <head>
  <title>New Tab</title>
  </head>
  <body>
    <h1>Hello World</h1>
  <script src="logic.js"></script>
  </body>
</html>