← EonsFlow

확장을 새로 받을 때마다 설정이 초기화되는 이유 — manifest key 로 ID 고정하기

2026년 8월 31일

새 버전 zip을 받아 다른 폴더에 풀었더니 저장해 둔 설정이 전부 사라졌습니다. 확장 목록에는 같은 확장이 두 개로 보입니다. 버그가 아니라 확장 ID가 바뀌었기 때문이고, 저장소는 ID 단위로 나뉘어 있습니다.

압축해제 로드 확장의 ID는 폴더 경로에서 나옵니다

웹스토어에 올린 확장은 개발자가 등록한 키에서 ID가 나오므로 항상 같습니다. 그런데 압축해제된 확장을 로드하는 방식은 다릅니다. manifest에 key가 없으면 크롬은 로드한 폴더의 절대 경로를 해시해서 ID를 계산합니다.

설치 경로결과
C:\tools\myext\ID aaaa…
D:\download\myext\ID bbbb… (다른 확장으로 인식)
C:\tools\myext-v2\ID cccc… (또 다른 확장)

경로 한 글자만 달라도 다른 확장이 됩니다. 버전 번호를 폴더명에 넣는 습관이 있다면 업데이트할 때마다 매번 새 확장이 생기는 셈입니다.

저장소가 ID 단위로 격리됩니다

chrome.storage.local은 확장별로 완전히 분리된 공간입니다. ID가 바뀌면 이전 데이터에 접근할 방법이 없습니다. 파일이 지워진 게 아니라 다른 확장이 됐으니 남의 데이터가 된 것입니다.

사용자 입장에서는 그냥 "새 버전 받았더니 API 키랑 설정이 다 날아갔다"로 보입니다. 한동안 "폴더를 옮기지 마세요"라는 안내문으로 버텼는데, 근본 해결이 아니었습니다.

manifest 의 key 필드로 고정합니다

ID를 경로가 아니라 키에서 유도하도록 바꾸면 됩니다. 먼저 서명용 키 쌍을 만듭니다.

# 개인키 생성 (이 파일은 절대 배포에 포함하지 않는다)
openssl genrsa -out key.pem 2048

# 공개키를 DER 로 뽑아 base64 로 인코딩
openssl rsa -in key.pem -pubout -outform DER | openssl base64 -A

출력된 문자열을 manifest에 넣습니다.

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0.0",
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A…"
}

이제 어느 경로에 풀어도 ID가 같습니다. 참고로 확장 ID는 공개키 DER의 SHA-256 해시 앞 16바이트를 4비트씩 끊어 a~p로 매핑한 값이라, 배포 전에 미리 계산해 둘 수도 있습니다. OAuth 리디렉션 주소처럼 ID가 필요한 설정을 먼저 준비해야 할 때 유용합니다.

key 를 넣는 그 업데이트 한 번은 여전히 초기화됩니다

당연한 이야기인데 놓치기 쉽습니다. key가 없던 시절의 ID와 key로 계산된 ID는 다릅니다. 즉 이 수정을 배포하는 버전에서 기존 사용자 설정은 한 번 더 날아갑니다. "이번 업데이트 후 설정을 다시 입력해 주세요"를 미리 공지해야 하고, 가능하면 그 전에 설정을 내보내는 기능을 먼저 배포하는 편이 낫습니다.

개인키(.pem)는 배포물에 넣지 마세요

manifest에 들어가는 건 공개키입니다. key.pem이 zip에 섞여 들어가면 누구나 같은 ID의 확장을 서명할 수 있게 됩니다. 배포 스크립트에서 확장 폴더 바깥에 두고, 포장 결과물에 포함되지 않는지 확인하는 단계를 넣어 두는 게 안전합니다.

덧붙여, 확장 폴더에 언더스코어로 시작하는 이름을 두지 마세요

배포 스크립트나 메모 파일을 확장 폴더 안에 _build.ps1처럼 두면 크롬이 "확장 프로그램을 로드하지 못했습니다"로 거부합니다. _로 시작하는 최상위 항목은 크롬이 예약해 두고 있습니다. 로컬에서는 멀쩡하다가 배포본에서만 터지는 유형이라, 포장 전에 한 번 확인해 두면 좋습니다.

정리하면

압축해제 로드 배포를 계속할 생각이라면 key는 선택이 아니라 필수입니다. 없으면 "폴더를 옮기지 마세요"라는 지킬 수 없는 약속에 계속 기대게 됩니다.

정리

이 글은 EonsFlow가 크롬 확장을 만들며 겪은 내용을 정리한 것입니다. 같은 맥락으로 hidden 속성을 걸었는데 요소가 계속 보입니다도 정리해 두었습니다.