본문으로 건너뛰기

06. 사용자에게 전달하기 — 선택

이 장은 본인 컴퓨터에서 만든 확장을 다른 사람의 컴퓨터에서 동작하게 옮기는 이야기입니다. 한두 명에게 보여 주는 정도부터, 자동 업데이트까지 붙은 진짜 사용자군에 배포하는 것까지 범위가 다양합니다. 처음부터 어디까지 갈지 정해 두고, 본인에게 맞는 절을 따라가세요.

세 가지 배포 경로

경로어울리는 자리미리 갖춰야 할 것자동 업데이트
zip 직접 전달한 번에 한두 명extension.zip 한 개없음. 새 버전 나올 때마다 zip을 다시 보냅니다.
Chrome Web Store 등록일반 공개개발자 계정 (1회 등록비), 검수 통과있음. 스토어가 처리합니다.
self-host .crx + update_url직접 호스팅이 가능하고 자동 업데이트도 본인 손에 두고 싶은 분.pem 키, .crx 패키지, update.xml, 호스팅 자리있음. 다만 Chrome이 일반 사용자 머신에서는 기본 차단하므로 추가 절차가 따라옵니다.

처음이라면 1번이 거의 항상 충분합니다. 사용자 수가 늘거나 자동 업데이트가 정말 필요해지면 그때 2번 또는 3번을 검토합니다.

pnpm run package (또는 build-and-package 스킬)가 끝나면 저장소 루트에 DISTRIBUTION.md 파일이 새로 생깁니다. 이 장은 그 파일의 긴 호흡 동반자입니다.

1) zip 직접 전달

가장 단순한 길이고, 보통 시작점으로 정답에 가깝습니다.

pnpm run build
pnpm run package # extension.zip 을 만듭니다

zip과 함께 보낼 안내는 다음 모양이 무난합니다.

  1. 받은 zip 파일의 압축을 풉니다.
  2. 주소창에 chrome://extensions 를 입력합니다.
  3. 우측 상단의 개발자 모드 토글을 켭니다.
  4. 압축해제된 확장 프로그램을 로드합니다 를 누르고 압축 푼 폴더를 선택합니다.

받는 쪽 브라우저에는 "개발자 모드 확장 프로그램" 경고 배너가 한 번 뜹니다. 확장은 Chrome을 재시작해도 그대로 살아 있습니다. 새 버전을 보낼 때는 같은 네 단계를 다시 한 번 따라가면 됩니다. 자동 업데이트가 필요 없다면 여기서 멈춰도 충분합니다.

받는 쪽이 개발자가 아니라면 두 가지가 도움이 됩니다.

먼저, zip과 함께 위 네 단계를 짧은 설치 노트로 같이 보내세요. 짧은 화면 녹화나 스크린샷 한 장이 긴 문단보다 빠릅니다.

다음으로, zip 안에는 manifest.config.ts 에 적힌 본인 확장의 이름, 아이콘, 설명이 그대로 들어갑니다. 보내기 전에 그 세 가지가 base의 placeholder가 아니라 본인 확장의 정보로 바뀌어 있는지 한 번 더 확인하세요.

받는 사람에게 보낼 메시지 템플릿

복사해서 그대로 써도 무방합니다.

안녕하세요, [확장 이름] 베타 버전을 보내드립니다.

설치는 다음 네 단계입니다.

1. 첨부한 zip 파일의 압축을 풉니다.
2. Chrome 주소창에 chrome://extensions 를 입력합니다.
3. 페이지 우측 상단의 "개발자 모드" 토글을 켭니다.
4. "압축해제된 확장 프로그램을 로드합니다" 버튼을 누르고
방금 압축을 푼 폴더를 선택합니다.

설치가 끝나면 우측 상단 퍼즐 아이콘에서 [확장 이름] 을 핀해 주세요.
사용 중에 막히는 자리가 있으면 알려 주세요.

2) Chrome Web Store 업로드

두 가지 모드가 있습니다. unlisted (링크를 가진 사람만 설치 가능) 또는 public (검색에 노출). 어느 쪽이든 일반 사용자에게는 가장 자연스러운 설치 경험입니다. 자동 업데이트와 신뢰 배지가 같이 따라옵니다.

  1. Chrome Web Store 개발자 콘솔에 본인 Google 계정으로 가입합니다. 일회성 등록비가 있습니다.
  2. pnpm run build && pnpm run package 가 만든 extension.zip 을 업로드합니다.
  3. 권한, 아이콘, 스크린샷, 설명, 개인정보 처리방침을 채웁니다.
  4. 검수에 제출합니다. 권한이 보수적일수록 검수가 빨리 끝나는 경향이 있습니다.

base는 manifest.config.ts 에 의도적으로 최소 권한 셋이 적혀 있어서 검수가 비교적 잘 통과합니다. host_permissions<all_urls> 를 넣었거나 tabs 또는 scripting 을 추가했다면 각각이 왜 필요한지 설명을 같이 적어 주세요.

업로드 직전에 갖춰 두면 좋은 자료를 묶어 두면 다음과 같습니다.

  • 일관된 아이콘 셋 (16, 32, 48, 128). 보통 public/icons/ 자리에 둡니다.
  • store 등록용 스크린샷 1280×800 또는 640×400. 보통 3~5장 정도입니다.
  • 한 줄 설명과 자세한 설명. 권한이 왜 필요한지 명시. 특히 host_permissions 는 거부 사유 1순위입니다.
  • 개인정보 처리방침 페이지. 외부 백엔드를 쓴다면 필수입니다.

개발자 콘솔에 처음 들어가면 "새 항목" 버튼이 가장 눈에 띄게 보입니다. 그 버튼을 누르면 zip 업로드 다이얼로그가 뜹니다. zip이 업로드되면 좌측 메뉴에 항목 정보, 개인정보 처리방침, 결제 같은 작성 항목이 펼쳐집니다. 업로드 직후 빨간색 경고 배너가 뜬다면 manifest의 필수 필드가 빠진 상태이니, 메시지가 가리키는 필드를 manifest.config.ts 에서 채우고 다시 빌드해 업로드합니다.

:::note 스크린샷 실제 캡처는 추후 docs-screenshot 스킬로 추가됩니다. static/img/chrome-ext/beginner/distribution-01-cws-upload.png 자리. :::

판매를 염두에 둔다면 두 가지를 짚어 둡니다. 첫째, 본인 Google 계정과 본인 확장 이름으로 등록해야 합니다. base의 정체로는 등록할 수 없습니다. 둘째, Chrome Web Store는 더 이상 확장 자체에 대한 결제를 받지 않습니다. 유료로 운영하려면 본인 사이트에서 결제를 처리하고, 사용자가 라이선스 키를 옵션 페이지에 붙여 넣게 하는 패턴이 일반적입니다. base의 옵션 페이지는 그 한 줄 입력 칸을 더하기에 자연스러운 자리입니다.

3) self-host .crx 와 자동 업데이트

이 자리는 인증서가 본격적으로 등장합니다. .crx 파일은 본인의 비밀 키(.pem)로 서명된 zip입니다. 그 서명이 확장 ID를 결정하고, 그 ID가 자동 업데이트가 추적하는 핵심입니다. 이 키를 한 번 잃어버리면, 그 빌드를 설치한 모든 사용자의 자동 업데이트 경로가 같은 순간 끊깁니다. 시작하기 전에 이 한 문장을 받아들이고 들어가세요.

이 경로가 진짜로 가치 있는 자리는 한 가지뿐입니다. 자동 업데이트는 필요하지만 Web Store에는 올리고 싶지 않은 경우. 그 외에는 1번이나 2번이 거의 항상 더 쉬운 길입니다.

3-1) .pem 키 만들기와 보관

처음에는 Chrome 자체로 패킹하는 것이 가장 안정적입니다.

  1. chrome://extensions 를 열고 개발자 모드 가 켜져 있는지 확인합니다.
  2. 확장 프로그램 압축 을 클릭합니다.
  3. 첫 빌드 시에는 "확장 프로그램 루트 디렉토리" 에 본인 dist/ 폴더를 지정하고 키 필드는 비워 둡니다. Chrome이 옆에 dist.crxdist.pem 을 같이 만들어 줍니다.
  4. .pem 파일을 안전한 자리로 옮깁니다. 1Password 같은 비밀번호 관리자나 본인만 접근하는 잠긴 폴더가 무난합니다. 절대 git에 커밋하지 마세요. 시작 전에 *.pem.gitignore 에 추가해 두세요.

CLI로도 같은 일을 할 수 있습니다.

google-chrome --pack-extension=dist --pack-extension-key=key.pem

이후 빌드부터는 같은 .pem 을 다시 넘겨 줘야 합니다. 키가 바뀌면 확장 ID가 바뀌고, 사용자 입장에서는 완전히 다른 확장이 됩니다.

3-2) .crxupdate.xml 호스팅

두 파일을 사용자 브라우저가 닿을 수 있는 자리에 둡니다 (자체 서버, S3, GitHub Releases 등). update.xml 은 다음 모양입니다.

<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='YOUR_EXTENSION_ID'>
<updatecheck codebase='https://example.com/path/to/my-extension.crx'
version='1.0.0' />
</app>
</gupdate>

YOUR_EXTENSION_ID 자리에는 첫 패킹 시 Chrome이 보여준 ID가 들어갑니다. chrome://extensions 의 확장 카드에서도 같은 ID를 확인할 수 있습니다.

3-3) manifest에 update_url 추가

manifest.config.tsupdate_url 을 더하면 빌드된 manifest.json 에 그대로 반영됩니다. Chrome이 자체 일정으로 그 URL을 폴링하면서 새 버전을 받아 갑니다.

{
"update_url": "https://example.com/path/to/update.xml"
}

새 버전을 풀 때는 다음 흐름을 반복합니다. manifest.config.tsversion 을 올리고, 다시 빌드하고, 같은 키로 다시 패킹하고, 같은 URL의 .crx 를 새 파일로 덮어쓰고, update.xmlversion 도 같은 숫자로 갱신합니다.

3-4) Chrome의 외부 .crx 차단 우회

기본 정책으로 Chrome은 외부에서 받은 .crx 의 일반 사용자 머신 설치를 차단합니다. 이 자리를 풀어내야 합니다. 회사 환경이라면 group policy의 ExtensionInstallForcelist 같은 자리에 ID와 update_url 을 등록해 자동 설치되게 할 수 있습니다. 그 외 일반 소비자에게는 self-host .crx 가 어색한 선택이 됩니다. 일반 사용자가 주된 사용자라면 2번 Web Store가 거의 항상 정답입니다.

이 자리의 더 자세한 내용은 전문가용 distribution 에 있습니다. enterprise policy 등록을 어디에 어떻게 적는지, ID와 도메인을 결정할 때 어떤 ADR이 따라붙는지가 거기 정리돼 있습니다.

키 관리와 잘못됐을 때

.pem 키 경고는 한 줄이지만 잃어버리면 거의 회복 불가에 가깝고, 판매 중이라면 손실이 훨씬 큽니다.

  • git에 커밋하지 마세요. 키를 만들기 전에 *.pem.gitignore 에 먼저 추가합니다.
  • 비밀번호 관리자에 사본을 한 부 더 둡니다. 노트북이 망가지면 그 사본이 마지막 키입니다.
  • 정말로 키를 잃어버렸다면 새 키를 만들고, 새 ID로 새 확장을 출시한 다음, 기존 사용자에게 다시 설치해 달라고 안내해야 합니다. 신뢰가 깎이는 자리이니 키 보관은 첫날부터 1순위로 다루세요.

판매 전에 한 번 더 짚을 것

이 base는 goldtagworks 로부터 라이선스를 받은 상업 템플릿입니다. 그 위에서 본인이 만든 확장은 본인이 정한 라이선스 조건으로 자유롭게 빌드하고 판매할 수 있습니다. 본인 사용자는 goldtagworks와는 아무 관계도 가지지 않습니다. 사용자에게 보이는 것은 본인의 확장뿐입니다.

다만 base 자체의 사용에 두 가지 제약이 있습니다.

  • chrome-ext-base 의 소스 코드나 이 매뉴얼을 누군가에게 재배포하지 마세요. base 위에서 만든 본인의 확장만 배포합니다.
  • 본인 작업 사본에는 LICENSECOMMERCIAL-LICENSE.md 를 그대로 둡니다. 빌드 산출물 dist/ 안에까지 포함시킬 필요는 없습니다. 사용자에게 가는 것은 본인 확장이지 base가 아닙니다.

본인 확장의 배포 라이선스는 본인이 정합니다. 자주 보이는 선택지는 All Rights Reserved (독점, 유료 확장에서 흔함), MIT (개방), Apache 2.0 (특허 양도가 포함된 개방) 정도입니다. 어떤 쪽으로 갈지 정했다면 본인 확장의 README와 파일별 헤더에 명시합니다. base 자체의 사용 조건은 LICENSECOMMERCIAL-LICENSE.md 에 정리돼 있습니다.

다음

여기까지가 base가 가정하는 모든 배포 경로입니다. 흐름이 한 번 익숙해졌다면 LICENSEpackage.json 이 본인 확장 정보로 바뀌어 있는지 한 번 더 확인합니다.

배포 도중 막히는 자리가 있다면 05-troubleshooting 에서 시작하고, 자동 생성된 DISTRIBUTION.md 도 옆에 두고 같이 보세요.