크롬 익스텐션 컴포넌트끼리 통신하는 방법 - 개발기

Broccolism·2022년 7월 31일
3

dev-story

목록 보기
6/9
post-thumbnail
post-custom-banner

매주 깃허브 이슈를 복사해서 일정한 형식으로 붙여넣는 노가다 작업을 하게 되었다. 이슈가 5개를 넘어갈 때 즈음.. 왜 이걸 내가 직접 하고 있지? 라는 생각이 들었다.

Copy Machine

개발 기간: 2일

copy machine

하는 일은 간단하다.
1. 사용자는 깃허브 issue 페이지에 들어가서 익스텐션을 켠다.
2. 그 페이지에 있는 이슈를 긁어서
3. 일정한 포맷으로 만들어 보여준다.
이제 이슈 개수 * 2 (이슈 링크와 이름) 번 복붙하던걸 1번만 복붙해도 된다.

크롬 익스텐션 컴포넌트

구성

  • background: 익스텐션 켜질 때 같이 실행되면서 브라우저에서 발생하는 이벤트를 감지한다.
  • content script: 크롬 익스텐션 컴포넌트 중, DOM에 접근할 수 있는 유일한 곳이다.
  • popup: 익스텐션 아이콘을 누르면 뜨는 그 팝업창.
  • options page: 익스텐션 관리 페이지.

크롬 익스텐션의 구성. 자세한 설명은 구글 크롬 익스텐션 공식 문서에 잘 나와있다.

큰 그림

요구사항을 다시 살펴보자.

  1. 사용자는 깃허브 issue 페이지에 들어가서 익스텐션을 켠다.
  2. 그 페이지에 있는 이슈를 긁어서 --> DOM 접근 필요
  3. 일정한 포맷으로 만들어 보여준다.

그런데 크롬 익스텐션 컴포넌트 중 DOM에 접근할 수 있는건 content-script뿐이다. 즉, content-script에서 긁어온 내용을 잘 가공해서 popup 으로 보내야 한다. 그래서 어떻게 통신하는지 찾아봤는데 잘 안 나와서 아래에 정리했다.

데이터는 다음과 같은 방향으로 흐른다:

  • DOM -> content script -> background -> popup

글로벌 저장소

  • background.js는 익스텐션이 켜져있는 동안 계속 살아있기 때문에 이곳에 글로벌 변수를 관리하기로 했다.

A background page is loaded when it is needed, and unloaded when it goes idle. Some examples of events include:

  • The extension is first installed or updated to a new version.
  • The background page was listening for an event, and the event is dispatched.
  • A content script or other extension sends a message.
    Another view in the extension, such as a popup, calls runtime.getBackgroundPage.

(https://developer.chrome.com/docs/extensions/mv2/background_pages/)

컴포넌트끼리 통신하기

// 보내는 쪽
chrome.runtime.sendMessage("message");

// 받는 쪽
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
	console.log(message);
});

content script -> background

// content-script.js
chrome.runtime.sendMessage({ "key": "value" });

// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    console.log(message);
});

injected script -> content script

// inject-script.js
window.postMessage({ "key": "value" });

// content-script.js
window.addEventListener("message", function (event) {
  const valueFromInjectScript = event.data.key;

background -> popup (엄밀히 말하자면 통신은 아님)

// popup.js
const background = chrome.extension.getBackgroundPage();
// 이후 이 변수를 통해 backround에 정의된 값을 가져올 수 있음.
const valueInBackground = background.valueName;

주의할 점

브라우저는 자바스크립트만 알아듣기 때문에

타입스크립트로 개발했다면 이를 JS로 바꿔주는 작업이 필요하다. 그래도 이걸 해주는 보일러플레이트 코드가 많이 돌아다니고 있으니 활용하면 될 것 같다. 내가 만들 익스텐션은 그렇게 복잡하지 않아서 그냥 바닐라 JS로 개발했다.

클립보드 복사 기능

크롬 익스텐션에서 클립보드 복사 기능을 구현하려면 이벤트 핸들러를 등록해야 한다. popup.html에서 바로 onclick 프로퍼티를 설정해주는게 안된다. 보안 정책 때문에 스크립트를 실행할 수 없다는 에러가 뜬다. 이것 때문에 마지막에 많이 헤맸다. 😇

DON'T (어차피 실행이 안된다)

popup.html
<button onclick="() => navigator.clipboard.writeText(text)">복사하기</button>

DO

popup.html
<button id="copy-button">복사하기</button>
popup.js
const copyToClipboard = (text) => {
  navigator.clipboard.writeText(text);
}
const copyButton = document.getElementById('copy-button');

copyButton.addEventHandler("click", copyToClipboard);

참고

profile
설계를 좋아합니다. 코드도 적고 그림도 그리고 글도 씁니다. 넓고 얕은 경험을 쌓고 있습니다.
post-custom-banner

0개의 댓글