포도가게의 개발일지
Chrome extension (브라우저 확장 프로그램) 본문
반응형
Chrome extension?
- 크롬 확장 프로그램은 구글 크롬 브라우저의 기능을 확장하거나 사용자 경험을 개선하는 작은 소프트웨어예요. HTML, CSS, JavaScript 같은 웹 기술로 만들어지며, 브라우저에 설치하면 광고 차단, 탭 관리, 웹페이지 수정 같은 일을 할 수 있습니다.
- 확장 프로그램은 HTML, CSS, JS 파일을 압축한 번들로, 브라우저 UI를 커스터마이징하거나 이벤트 감지, 웹 수정 등을 할 수 있습니다.
- 스마트폰에 앱을 설치하는 것처럼 브라우저에 추가 기능을 더하는 것이라고 간단히 생각 할 수 있습니다.
개발단계
- 파일들을 하나의 디렉토리에 두고, chrome://extensions 페이지에서 load unpacked를 통해 번들링 없이 여러 파일로 테스트 가능합니다.
배포시
- chrome web store에 업로드 하거나 다른 사용자에게 공유할 때는 모든 파일을 zip 파일로 압축해야 합니다. zip 파일의 root 에는 manifest.json이 존재해야하며 최대 크기는 2GB입니다.
- 때문에 번들링을 통해 파일 크기를 줄이고 성능과 호환성을 최적화할 수 있습니다.
Manifest File
- 모든 크롬 확장 프로그램에는 확장 프로그램의 기본 정보(예: 이름, 버전, 필요한 권한 등)를 포함하는 매니페스트 파일(manifest.json)이 있습니다.
Architecture


Contents Scripts
- 콘텐츠 스크립트는 크롬 확장 프로그램에서 웹페이지의 DOM(Document Object Model)과 상호작용할 수 있는 유일한 부분
- 콘텐츠 스크립트는 높은 권한이 필요한 작업을 수행하기 위해 확장 프로그램의 다른 부분(보통 백그라운드 서비스 워커)으로 메시지를 보내야 합니다.
- 페이지 DOM에 접근할 수 있고, 페이지에 직접 UI를 표시할 수 있으며, 다른 구성 요소로 메시지를 보낼 수 있습니다.
- Chrome API에 접근할 수 없습니다.
- 콘텐츠 스크립트는 웹페이지의 맥락에서 실행되는 파일로, 페이지의 세부 사항을 읽고 수정하며 부모 확장 프로그램과 정보를 교환할 수 있습니다.
- 격리된 세계(isolated world)에서 실행되어 페이지의 JavaScript 환경과 다른 확장과의 충돌을 방지합니다. 하지만 이는 모든 확장 API 직접 접근을 막으며, 외부 콘텐츠 처리 시 XSS(Cross-Site Scripting) 공격 위험 때문에 fetch() 등을 주의해야 하며, eval()이나 문자열 기반 setTimeout은 보안상 금지됩니다 (Manifest V3에서 특히 엄격)
- 2022년 main world mode가 추가되었습니다.(isolate와 다르게 동일한 렉시컬환경을 통해 page script의 변수에 접근 가능해집니다.)
- 이로 인해 복잡한 통신 없이도 직접적인 상호작용이 가능해져 개발 편의성이 증대
Background Service Worker
- 서비스 워커는 백그라운드에서 실행되며, 확장 프로그램이 권한을 가진 모든 Chrome API(예: 탭, 북마크, 저장소)에 접근할 수 있습니다.
- 어떤 웹페이지의 DOM과도 상호작용할 수 없으며, UI를 표시할 수 없습니다(예: 알림 제외).
- 확장 프로그램의 다른 부분으로부터의 이벤트에만 응답할 수 있으며, 제한된 시간 동안만 실행된 후 종료됩니다(bootstrap -> idle -> die).
- 주요 역할은 다른 구성 요소, Chrome API, 그리고 백엔드 서버 간의 메시지를 중계하는 "중앙 허브"입니다.
- naming 변화: background page(V2) -> service worker(V3)
- 확장 설치(onInstalled), 메시지 수신(onMessage), 탭 변경(onUpdated) 등의 이벤트에 반응하며, 지속적이지 않으므로 이벤트 기반 프로그래밍이 필수입니다.
- 콘텐츠 스크립트로부터 메시지를 받아 API 호출 후 결과를 반환하거나, 외부 서버(예: fetch()로 API 호출)와 통신합니다.
- 이벤트 후 30초 이내에 작업을 완료해야 하며, 5분 동안 이벤트가 없거나 하나의 이벤트/API 호출이 5분 이상 걸리면 자동/강제 종료됩니다. 필요 시 chrome.alarms API로 주기적 깨우기를 사용할 수 있지만, 남용 시 확장이 비활성화될 수 있습니다.
- 웹페이지 DOM 접근이나 UI 표시가 불가능하므로, 콘텐츠 스크립트나 팝업과 연동해야 합니다.
- 종료 시 글로벌 변수가 사라지므로, 데이터 지속성을 위해 chrome.storage API, IndexedDB, 또는 CacheStorage를 사용하세요.
Offscreen
- 오프스크린(Offscreen)은 Chrome 확장 프로그램에서 사용자에게 보이지 않는 숨겨진 페이지를 의미합니다. 확장 프로그램의 핵심 로직을 담당하는 서비스 워커(Service Worker)가 직접 수행할 수 없는 특정 작업, 특히 DOM(Document Object Model)에 접근해야 하는 작업을 처리하기 위해 사용
- 하지만 사용자에게는 보이지 않는 iframe이나 숨겨진 창과 유사하게 작동합니다.
- 서비스 워커는 DOM 접근이 필요한 작업을 오프스크린 문서에 "위임"합니다. 즉, 서비스 워커가 오프스크린 문서에 명령을 보내면, 오프스크린 문서가 그 명령을 수행하고 결과를 서비스 워커로 다시 보냅니다.
통신
- 각 컴포넌트는 격리된 환경에서 실행되기 때문에 직접적으로 변수나 함수를 공유할 수 없습니다. 따라서 메시지 전달(Message Passing)이라는 방법을 통해 통신하게 됩니다.
- 일회성 요청 (One-time Requests)
- 한 번 메시지를 보내고 한 번 응답을 받으면 끝나는 간단한 통신에 적합합니다. 대부분의 경우에 이 방법을 사용합니다.
- chrome.runtime.sendMessage(): 확장 프로그램의 어떤 컴포넌트에서든 다른 컴포넌트로 메시지를 보낼 때 사용합니다.
- chrome.tabs.sendMessage(): 서비스 워커나 팝업 등에서 특정 탭의 콘텐츠 스크립트로 메시지를 보낼 때 사용합니다. (콘텐츠 스크립트가 특정 탭에 주입되어 있기 때문에 tabs API를 사용합니다.)
- chrome.runtime.onMessage.addListener(): 메시지를 받는 쪽에서 메시지를 수신하기 위해 사용하는 이벤트 리스너입니다.
- 장기 연결 Long-lived Connection
- 여러 번 메시지를 주고받아야 하거나, 지속적인 통신 채널이 필요한 경우에 사용합니다.
- chrome.runtime.connect(): 확장 프로그램 컴포넌트 간에 연결을 설정합니다.
- chrome.tabs.connect(): 특정 탭의 콘텐츠 스크립트와 연결을 설정합니다.
Popup pages, Side panel, option page
- 팝업 (Popup): 사용자가 확장 프로그램 아이콘을 클릭했을 때 나타나는 작은 UI 창입니다.
- 옵션 페이지 (Options Page): 확장 프로그램의 설정을 변경하는 페이지입니다.
Devtool page
Comments