본문으로 바로가기

파일의 IT 블로그

  1. Home
  2. 웹/Chrome Extension
  3. [크롬 확장프로그램] 타입스크립트로 개발하는 방법 (크롬 확장프로그램 + 타입스크립트 개발환경 구축) - manifest v3

[크롬 확장프로그램] 타입스크립트로 개발하는 방법 (크롬 확장프로그램 + 타입스크립트 개발환경 구축) - manifest v3

· 댓글개 · KRFile

이미지 출처 : https://betterprogramming.pub/creating-chrome-extensions-with-typescript-914873467b65

안녕하세요 파일입니다. 기본적으로 크롬 확장프로그램이란 크롬 안에서 우리가 작성한 자바스크립트를 원하는 시점에 실행시킴으로써 사이트를 원하는대로 커스텀 하는 도구입니다. + 자바스크립트를 실행시키는 것 이외에도 웹 요청을 차단하거나, 응답을 조작하거나 CSS를 삽입하거나 매우 여러가지 행위의 것을 할 수 있습니다. 말 그대로 브라우저의 기능을 확장하는 것 입니다.

 

자바스크립트를 사이트에서 실행시켜야 하므로 크롬 확장프로그램 개발은 당연히 자바스크립트로 합니다. (사이트에서 실행할 자바스크립트를 작성해야 하기 때문에)

 

비슷한 종류로 유저 스크립트를 실행시켜주는 확장프로그램인 Tamper Monkey가 존재합니다. 하지만 훨씬 구조적인 기능을 제공하는게 크롬 확장프로그램이기 때문에 개인적으로 간단한 확장 개발은 Tamper Monkey로 실행시키고, 조금 복잡한 프로그램을 개발할때는 크롬 확장프로그램으로 만들어 개발하고 있습니다.

 

물론 오늘은 크롬 확장프로그램에 대한 이야기를 할 것이 아니라 크롬 확장프로그램을 개발 시 타입스크립트로 개발하는 방법을 소개해드리고자 합니다. 솔직히 자바스크립트 자체가 너무 너무 마음에 안들기 때문에 크롬 확장프로그램을 타입스크립트로 개발하는 방법을 찾아봤는데 구글링 해봐도 국내글엔 마땅한 정보가 안나오더라구요. 해외에서 괜찮은 글을 찾아서 이 내용을 다듬고 소스를 조금 수정하여 정리한 글입니다.

 

개발환경 구축

npm init -y

프로젝트로 사용할 폴더를 하나 만들고 VSCode로 연다음에 터미널에 해당 명령어를 입력해서 npm으로 패키지를 관리할  수 있도록 준비합니다.

 

mkdir chrome_extension_typescript_project
cd chrome_extension_typescript_project
npm init -y
code .

 

또는 터미널 환경이라면 mkdir 을 이용하여 폴더를 만드셔도 됩니다. 

 

작업이 끝났으면 다음과 같이 폴더에 package.json이  생성됩니다.

 

npm i --save-dev webpack webpack-cli
npm i --save-dev copy-webpack-plugin
npm i --save-dev typescript ts-loader
npm i --save-dev @types/chrome
npm i --save-dev glob

이후 다음 명령어를 통해 필요한 패키지를 설치합시다.

webpack은 HTML 패키징용이고, 나머지는 타입스크립트 및 크롬 확장 개발에 필요한 타입 정의가 포함된 코드를 설치하는 부분입니다. (typescript, ts-loader, @types/chrome)

 

{
  "compilerOptions": {
    "strict": true,
    "module": "commonjs",
    "target": "es6",
    "esModuleInterop": true,
    "sourceMap": true,
    "rootDir": "src",
    "outDir": "dist/js",
    "noEmitOnError": true,
    "typeRoots": ["node_modules/@types"]
  }
}

설치가 끝났으면 같은 경로에 tsconfig.json을 만들고 위 내용을 그대로 붙여넣기 합니다.

 

const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
const { glob } = require("glob");

module.exports = {
  mode: "production",
  // entry: {
  // background: path.resolve(__dirname, "..", "src", "background.ts"),
  // },
  entry: glob
    .sync("../src/**/*.ts", { cwd: __dirname })
    .reduce(function (obj, element) {
      const dir = element
        .replace("..\\src\\", "")
        .replace("../src/", "")
        .replace(".ts", "");
      obj[dir] = element;
      return obj;
    }, {}),
  output: {
    path: path.join(__dirname, "../dist"),
    filename: "[name].js",
  },
  resolve: {
    extensions: [".ts", ".js"],
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new CopyPlugin({
      patterns: [{ from: ".", to: ".", context: "public" }],
    }),
  ],
};

webpack 폴더에 webpack.config.js 를 만들고 위 내용을 그대로 붙여넣기 합니다.

참고로 해당 코드는 src 폴더에 있는 모든 ts 파일을 재귀적으로 탐색하면서, 이 파일을 js로 컴파일 하라는 webpack 명령이 들어간 코드입니다. (제가 직접 작성함)

 

추가적으로 public 폴더에 있는 내용을 컴파일 시 그대로 output 폴더로 복사하는데 여기에 manifest.json 파일을 저장할 겁니다. 일단은 뇌빼고 계속 계속 따라해봅시다.

 

 

"scripts": {
    "build": "webpack --config webpack/webpack.config.js",
    "dev": "webpack --watch --config webpack/webpack.config.js"
  }

아까 만들어졌던 package.json 을 열고 scripts 부분을 다음과 같이 변경합니다.

build 명령어로 타입스크립트로 작성한 크롬 확장프로그램을 빌드할 수 있고, dev 모드로 개발하면 hot reloading 이 적용된 상태로 개발할 수 있습니다. (작업하면서 파일을 저장할 때마다 계속 실시간으로 빌드해줌)

 

다만 새로운 타입스크립트 파일을 추가하거나 해서 파일 구조에 변화가 생기면 dev 모드로 개발하고 있더라도, 빌드 정보를 다시 새로고침 하기 위해 현재 작업을 중단하고 명령어를 다시 입력해서 새롭게 build 또는 dev 명령어를 다시 입력해줘야 합니다.

 

{
  "name": "chrome_extension_typescript_only",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config webpack/webpack.config.js",
    "dev": "webpack --watch --config webpack/webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/chrome": "^0.0.243",
    "copy-webpack-plugin": "^11.0.0",
    "ts-loader": "^9.4.4",
    "typescript": "^5.1.6",
    "webpack": "^5.88.2",
    "webpack-cli": "^5.1.4"
  },
  "dependencies": {
    "glob": "^10.3.3"
  }
}

scripts 부분을 수정했다면 대략 package.json 은 이런 모양새가 됩니다.

 

{
  "name": "Google Color Changer",
  "version": "1.0",
  "description": "This extension will run multiple scripts after the site has loaded.",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["https://www.google.com/*", "https://www.google.co.uk/*"],
      "js": ["content.js"]
    }
  ]
}

public 폴더를 만들고 manifest.json 에 다음 코드를 붙여넣기 합니다.

테스트로 작성한 코드인데 구글에 접속하면 배경색을 주황색으로 바꿔주는 확장프로그램 입니다.

 

참고로 js에는 content.ts 로 쓰면 안되고 content.js로 써야 합니다. 구글 크롬 확장프로그램 자체가 자바스크립트로만 동작하기 때문입니다. 어짜피 웹팩써서 빌드하면 타입스크립트로 다 바껴서 포장되니깐 걱정안하셔도 됩니다.

 

코드 작성시에만 content.ts로 적고 manifest.json 엔 content.js로 적어야 합니다.

 

// Redefine 오류를 피하기 위해 반드시 스크립트들은 namespace로 감싸야 한다.
// content script들은 변수를 서로 공유하지 않는 듯 함.

namespace App {
  console.log("content script loaded");
  // body는 일반적으로 null이 될 수 없기 때문에 !를 붙임
  document.querySelector("body")!.style.backgroundColor = "Orange";
}

이제 가장 중요한 컨텐츠 스크립트 부분인데 src 폴더에 content.ts를 작성하도록 합니다. 내용은 간단히 DOM에 접근해 웹 페이지의 색상을 오렌지색으로 바꾸는 코드입니다.

 

아까 전에 웹팩으로 src 폴더에 있는 모든 ts 파일을 js 파일로 컴파일 하라고 지시했으므로 앞으로 코딩시에는 삽입하고 싶은 백그라운드 및 컨텐츠 스크립트를 src 폴더에 ts 파일로 작성해주시면 됩니다.

 

참고로 컨텐츠 스크립트 작성시 모든 스크립트를 서로 다른 namespace명으로 감싸줘야 합니다.  크롬 확장프로그램 개발 중 여러개의 타입스크립트 파일이 있을때, 이 코드들을 namespace 로 감싸지 않으니 변수명이나 함수명이 겹치면 redefine 오류가 발생했습니다.

 

그러나 확인해본 결과 크롬 확장프로그램의 컨텐츠 스크립트 파일들 끼리는 서로 변수와 함수를 공유하지 않는 것으로 확인했습니다.

 

따라서 타입스크립트의 재정의 오류를 피하기 위해 네임스페이스로 감싸는 선택을 했습니다. 

더 좋은 방법이 있거나 혹시 제가 확인한 내용이 틀린 부분이 있다면 댓글로 알려주세요.

 

어쨌던 앞으로 코드를 작성하실땐 src 폴더 안에다 ts 파일로 만들어 하시고, 되도록 전부 namespace로 묶어서 작업해주세요. (파일마다 다 다른 네임스페이스 명으로 묶어서 작업하라는 뜻 ex - a.ts -> namespace A , b.ts -> namespace B, ...) 

 

혹시라도 컨텐츠 스크립트들 끼리 변수명이나 함수명이 공유되는 상황이 온다면 같은 namespace 명을 사용해서 타입스크립트(더 정확히는 VSCode)가 중복 변수명을 감지할 수 있도록 도와주면 됩니다.

 

npm run build
npm run dev

이제 세팅은 끝났고 위 명령어 중 하나를 이용해 빌드하면 됩니다. 저는 그냥 npm run build로 바로 빌드했습니다. dev 명령어는 핫 리로딩 작동이 궁금하신 분들만 보세요.

 

빌드 완료 시 dist 폴더가 생성되며 이 dist 폴더가 바로 크롬 확장프로그램 설치 파일이 되게 됩니다.

 

압축해제된 확장 프로그램을 로드합니다. 를 통해서 아까 빌드된 dist 폴더를 열어서 만든 확장프로그램을 설치합니다.

 

구글 접속시 색상이 오렌지 색으로 변함을 알 수 있습니다 ㅎㅎ

 

다운로드

https://github.com/pgh268400/Chrome_Extension_TypeScript_Only

 

GitHub - pgh268400/Chrome_Extension_TypeScript_Only: Boilerplate for developing Chrome extension with TypeScript

Boilerplate for developing Chrome extension with TypeScript - GitHub - pgh268400/Chrome_Extension_TypeScript_Only: Boilerplate for developing Chrome extension with TypeScript

github.com

 

위 과정이 귀찮으신 분들은 여기와서 파일 받고 [블럭*npm i*] 명령어만 실행시킨 후 사용하시면 됩니다.

SNS 공유하기
💬 댓글 개
이모티콘창 닫기
울음
안녕
감사해요
당황
피폐

이모티콘을 클릭하면 댓글창에 입력됩니다.