에버노트 웹 클리퍼 익스텐션의 동작 방식 분석

발생일: 2014.11.30

키워드: Evernote Web Clipper, 에버노트 웹 클리퍼, 크롬 익스텐션, 크롬 확장

문제:
어느덧 네이버 영어사전 크롬 익스텐션 사용자가 45,000명이 되었다.
사용자가 많아진 만큼 개선 요청이나 문의가 많이 들어오는데, 몇몇 분들이 특정 사이트에서 사전이 보이지 않는다고 문의를 하셨다.

문제가 발생하는 페이지들은 frameset 으로 구성되어있는 경우였다.
사전은 페이지에 엘리먼트를 직접 삽입하는 방법으로 구현했는데, 이 페이지엔 엘리먼트를 삽입할 수 없기 때문이다.

근데, 에버노트 웹 클리퍼 익스텐션은 요 문제를 해결하고 있더라. (난 이 익스텐션이 너무너무 좋다 +_+b)
<html> 노드 바로 아래로 <iframe> 을 삽입하는 방법인데,
이렇게 하면 스타일이 중복되는 것도 막을 수 있고, 프레임셋에서의 렌더링 이슈도 해결할 수 있을 것 같다.

헌데 테스트해보려고 아래처럼 태그를 구성해봐도 <iframe>이 렌더링되지 않는다.

  <html>
  <frameset>
    <frame src=“”>
    <frame src=“”>
  </frameset>
  <iframe></iframe>
  </html>


음… 어떻게 만든 거지…


해결책:

크롬 익스텐션의 소스를 다운로드 받을 수 있는 익스텐션이 있다!

에버노트 웹 클리퍼 익스텐션 소스를 다운로드 받은 뒤에, 어떻게 구현했는지 자세히 살펴봤다.

1. content_scripts 를 document_start 시점에 실행하는데, 이 때 <iframe> 엘리먼트를 미리 만들어둔다.
(그다지 중요한 건 아니지만) 페이지가 렌더링 된 이후에, 힙 스냅샷을 찍어보면 아래 이미지처럼 Detached DOM 으로 <iframe> 이 포함되어 있는 걸 확인할 수 있다.


2. 익스텐션의 브라우저 액션 버튼을 누르면, 만들어뒀던 iframe 을 documentElement 에 추가한다…
아이코.. 왜 documentElement를 생각하지 못하고 있었을까..

  document.documentElement.appendChild(iframe);


3. 에버노트 익스텐션을 닫으면, 역시 부모 노드에서 iframe 을 삭제(detach)한다.


한 줄 요약:
최상위 프레임에서 document.documentElement 에 추가하면 된다. 


영어사전을 만들 때엔, 어떤 프레임에 사전 엘리먼트를 보여줄 지에 대해 고민을 많이 했었다.
현재는 가장 사이즈가 큰 프레임에 사진 레이어를 띄우는 식인데,
위 방법처럼 하면 프레임 사이즈에 관계 없이 사전을 고정 위치에 띄워줄 수 있다. +ㅁ+b

그래도 몇 가지 고려해야할 게 있는데, 에버노트 익스텐션은 이미 잘 해결해뒀더라~

1. 어떤 프레임에 툴바(사전)을 렌더링할 것인가?
  최상위 프레임에 한다.
  content_scripts 를 추가할 때, `document_start` 시점에 <iframe> 생성 코드를 실행하도록 한다.
  컨텐트 스크립트는 기본적으로 메인 프레임에만 실행되기 때문에, 최상위 프레임에 <iframe> 엘리먼트가 생성된다. 

2. 최상위 프레임이 아닌 다른 프레임엔 어떻게 스크립트를 추가하나?
  각 프레임에서 필요한 스크립트는 `document_end` 시점에 `all_frames: true` 옵션을 줘서, 모든 프레임에 추가한다.
  이 스크립트는 각 프레임에 필요한 스크립트를 로드하는 역할을 한다.
  최상위 프레임인지 여부는 `window === window.parent` 여부로 확인하면 된다.

3. 최상위 프레임과 나머지 프레임과의 통신은 어떻게 할 것인가?
  백그라운드 통해 이벤트를 주고 받는 식으로 처리한다.
  

일단은 이 정도까지.
코드 보니 여러 상황을 고려하고 고민한 흔적이 많더라.
크롬 이외의 브라우저에 대한 처리, 사파리 그리스몽키와 동시에 사용하기 위한 처리나, pdf 뷰어나 gmail 에서의 동작 등 특정 상황을 위해 별도로 구현해놓은 코드도 있었다.

덕분에 많이 배웠다. 열심히 써줘야지~
에버노트 느무 좋다. ㅎㅎㅎ


카테고리

분류 전체보기 (711)
About me. (6)
Daylogs (676)
영어공부 (0)
My works - 추억 (29)
비공개 (0)