본문 바로가기
개발일지/RIDI-Journals 제작기 & 설명서

[리디저널 제작기] 1. React로 크롬 확장프로그램 만들기 위한 기초 설정

by GiraffePark 2023. 4. 5.
안녕하세요. 박기린 입니다.
본 글은 [ 리디북스의 독서노트 글귀를 복사하는 크롬 확장프로그램 :  RIDI-Journals ]의 제작 과정을 적어놓은 글입니다.

 

 

프로젝트 업무 정리 방식 선정

프로젝트의 모든 업무는 '칸반 보드' 방식을 이용해서 계획 / 정리 / 실행을 하였습니다.

칸반 보드 앱으로 FirstSeed Tasks 앱을 사용했습니다.

 

 

 

칸반 보드의 업무 계획 / 상황표에 맞춰서, 모든 과정을 차례대로 Upnote에 정리했습니다.

그리고 이 Upnote의 기록을 바탕으로 블로그에 개발 과정 글을 적습니다.

 

 

 

 

 


create-react-app with TypeScript

chrome extension은 자바스크립트로 제작되어야 합니다. 그리고 자바스크립트 라이브러리를 사용할 수 있습니다.

RIDI-Journals 제작에는 React 프레임워크를 채용하였고, TypeScript로 코드 작성을 했습니다.

 

 

 

 

 


Chrome Extension의 구조 이해하기

manifest.json

 - chrome extension의 메타 데이터를 담습니다.

 

popup.html / popup.js

 - chrome 확장프로그램 아이콘을 누르면 나타나는 팝업창의 파일입니다.

 - html에는 팝업창의 UI 표시 방식을 설정하고, js에는 팝업창에서 발생하는 event를 제어합니다.

 

background.js

 - chrome API를 이용해서 팝업창과 content scripts가 메시지를 주고받을 수 있게 해주는 통로 역할을 합니다.

 

content scripts

 - chrome 브라우저의 페이지에서 실행 / 동작하는 스크립트입니다. 페이지의 DOM을 추가, 제거, 변경 등 다양한 작업을 할 수 있습니다.

 - 자바스크립트 파일이고, 여러 개의 파일을 만들 수 있습니다.

 - 각 탭 마다 1회씩만 불러와집니다.

 - chrome API를 이용해서 background.js와 팝업창으로 메시지(데이터)를 주고받을 수 있습니다.

 

 

 

 

 


V3로 manifest.json 설정하기

구글 크롬 익스텐션 공식 API 문서에 따르면, Manifest V2로 제작된 크롬 확장프로그램의 지원을 중단할 것임을 경고하고 있습니다. 따라서 Manifest V3로 크롬 확장프로그램을 제작해야 합니다.

 

 

 

{
  "name": "RIDI-Journals",
  "version": "0.0.1",
  "manifest_version": 3,
  "description": "RIDI-Journals",
  "icons": {
    "16": "logo16.png",
    "48": "logo48.png",
    "128": "logo128.png"
  },
  "permissions": ["scripting"],
  "host_permissions": ["https://ridibooks.com/reading-note/"],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  },
  "action": {
    "default_icon": "logo128.png",
    "default_popup": "popup.html",
    "default_title": "Ridi Bookmark"
  }
}
  • name : 크롬 확장프로그램의 이름을 적어줍니다.
  • version : 해당 프로그램의 버전이 몇인지를 적어줍니다.
  • manifest_version : manifest 버전을 적어줍니다. 이제부터는 V3로 만들어야 하기 때문에, 3을 적어줍니다.
  • description : 해당 프로그램의 설명을 적어줍니다.
  • icons : 해당 프로그램의 아이콘을 적어줍니다. 프로그램이 크롬 웹 스토어나 확장 프로그램 설정에서 어떤 아이콘으로 보여질 지를 결정할 수 있습니다.
  • permissions : 자바스크립트로 크롬을 조작할 때, 어디까지 기능을 사용할 수 있는 지 권한을 지정합니다.
  • host_permssions : 이 프로그램이 어떤 host(사이트)에서 사용될 지를 정한 후, 해당 사이트에서만 스크립팅이 작동하도록 권한을 지정합니다.
  • background : background.js의 위치를 지정합니다. 이때 service_worker에 background.js의 위치를 지정하고, type에 module을 적어줍니다.
  • action : 팝업창에 관한 설정을 합니다. default_icon에는 팝업창을 띄우는 파비콘을 지정합니다. default_popup에는 팝업창으로 쓰일 popup.html의 경로를 지정합니다.

 

 

 


webpack 라이브러리를 이용해서 빌드 설정하기

React는 SPA(싱글 페이지 앱)입니다. 크롬 확장프로그램은 여러 개의 html 파일(popup.html, index.html 등)과 js파일 (background.js, content scripts)를 필요로 하기 때문에, 하나의 html과 js파일로 build하는 React 방식은 크롬 확장프로그램에는 어울리지 않습니다.

그래서 React 프로젝트임에도 불구하고 여러 개의 파일로 쪼개서 build를 할 수 있는 webpack을 사용합니다.

 

 

$ yarn add customize-cra react-app-rewired copy-webpack-plugin react-app-rewire-multiple-entry --dev

 

프로젝트 경로의 터미널에 위 코드를 입력해서, 패키지를 추가해줍니다.

customize-cra, react-app-rewired : webpack을 재정의합니다.

copy-webpack-plugin : public 폴더를 build 폴더로 복사합니다.

react-rewire-multiple-entry : 여러 페이지(html)를 build할 수 있게 해줍니다.

 

 

 

패키지 설치가 완료되면, 프로젝트의 root경로에 아래의 코드가 담긴 js파일을 추가합니다.

const {
  override,
  overrideDevServer,
  addWebpackPlugin,
} = require("customize-cra");
const CopyPlugin = require("copy-webpack-plugin");
const RewireMultipleEntry = require("react-app-rewire-multiple-entry");

const multipleEntry = RewireMultipleEntry([
  {
    entry: "src/popup/index.tsx",
    template: "public/popup.html",
    outPath: "/popup.html",
  },
]);

const devServerConfig = () => (config) => {
  return {
    ...config,
    devMiddleware: {
      writeToDisk: true,
    }
  };
};

const copyPlugin = new CopyPlugin({
  patterns: [
    { from: "src/script/background.js", to: "" },
    { from: "src/script/getDom.js", to: "" },
    { from: "src/script/pressButton.js", to: "" },
  ],
});

module.exports = {
  webpack: override(addWebpackPlugin(copyPlugin), multipleEntry.addMultiEntry),
  devServer: overrideDevServer(devServerConfig()),
};

 

 

const multipleEntry = RewireMultipleEntry([
  {
    entry: "src/popup/index.tsx",
    template: "public/popup.html",
    outPath: "/popup.html",
  },
  // {
  //   entry: "src/page/index.tsx",
  //   template: "public/index.html",
  //   outPath: "/index_1.html",
  // },
]);

RewireMultipleEntry()를 이용해서 여러 개의 tsx파일을 각각 html 페이지로 만들 수 있습니다.

추후 크롬 익스텐션의 setting 페이지를 제작할 때 유용하게 쓰입니다.

 

 

 

const copyPlugin = new CopyPlugin({
  patterns: [
    { from: "src/script/background.js", to: "" },
    { from: "src/script/getDom.js", to: "" },
    { from: "src/script/pressButton.js", to: "" },
  ],
});

CopyPlugin()을 이용해서, 각종 스크립팅 js 파일들을 build 파일에 넣어줄 수 있습니다.

이 안에 background.js와 content script로 쓰일 js 파일들의 경로를 입력해줍니다.

 

 

 

 

Chrome에 실행 확인 용 임시파일 업로드

코딩 결과물을 직접 확인하기 위해서는 크롬에 직접 업로드해서 확장 프로그램을 작동해야 합니다.

 

 

프로젝트 파일 경로의 터미널에서

$ npm run build

위 코드를 입력합니다.

 

 

 

그러면 위와 같은 build 폴더와 파일이 생성됩니다.

 

 

 

chrome://extensions

이제 chrome 브라우저를 켜서, 위 주소를 입력하고 들어갑니다.

 

 

 

 

그러면 확장 프로그램 페이지에 들어가집니다.

우측 상단의 개발자 모드를 킨 후, '압축해제된 확장 프로그램을 로드합니다.' 버튼을 클릭합니다.

 

 

 

 

 

그리고 아까 생성한 build 폴더를 선택합니다.

 

 

 

 

 

그럼 위처럼 확장프로그램이 chrome 브라우저에 설치가 됩니다.

 

 

 

 

 

그러면 이렇게 직접 build한 확장프로그램이 크롬에서 실행되는 것을 확인할 수 있습니다.

React는 hot reload가 큰 장점이지만, 크롬 확장프로그램을 만들 때는 퇴색이 됩니다. 코드를 수정하면, build 후 다시 chrome 브라우저에 수정한 build 폴더를 업로드해야 합니다.

 

 

 

 

 


@types/chrome 모듈 설치

chrome 확장프로그램을 제작할 때는, chrome API를 사용합니다. 이 API를 TypeScript에서 사용하기 위해선, @types/chrome 모듈을 설치해야 합니다.

(@types/chrome : https://www.npmjs.com/package/@types/chrome)

 

 

설치 전에는 TypeScript 파일에서 chrome object를 사용하면 vscode에서 오류가 뜨지만,

 

 

 

설치가 끝나면 바로 오류메시지가 사라집니다.

반응형