바른 말씨 extension을 쓰면서 항상 아쉬웠고 구현하고자 하는 기능이 있었는데, 검사 후에 틀린 단어로 표시된 것을 어떻게 하면 제시된 해당 대치어로 쉽게 고쳐줄 수 있을까 하는 고민이었다.

처음엔 그냥 웹페이지에 표시된 틀린 단어에 마우스를 가져가면 tooltip 형태로 해당 대치어를 보여주는 방법을 구상해 보았지만, 또 막상 고치려면 수작업이 필요해서 마땅치 않았다. 그래서 구상한 것이 틀린 단어를 클릭하면 자동으로 해당 대치어로 바꿔주는 방법 쪽으로 고민해봤다.

우선 틀린 단어에 대한 대치어를 각각 따로 저장해 놓을 장소가 필요했는데, 여기엔 HTML5의 custom data attribute이 안성맞춤이다. 바른 말씨 extension에서 틀린 단어를 클릭하면 해당 대치어로 고쳐주는 것의 구현 방식(이)란 제목의 글 마저 읽기 →

Safari 5.1부터 지원하기 시작한 Popover 기능(Chrome에선 이 기능이 예전부터 있었으며 Popup이라고 불림) 덕분에 이젠 웹페이지에 있는 글뿐만 아니라 맞춤법 검사를 하고자 하는 글을 도구막대 버튼을 누르면 뜨는 작은 Popover/Popup 창에다 직접 입력해서 검사를 수행할 수 있게 되었다.

바른 말씨 Safari/Chrome 익스텐션의 검사 창 모습

겸사겸사 SafariChrome 익스텐션을 함께 갱신하게 되었는데 둘의 창 모양까지 닮았으니 Safari가 Chrome의 것을 많이 참고한 것 같지만, 그래도 개발 문서만은 Safari에게 더 후한 점수를 주고 싶다.

참고로, Safari와 Chrome의 Popovers/Popups 구현에는 약간의 차이가 있는데, Safari에선 웹페이지에서 글자를 선택하지 않은 경우에만 Popovers 창을 보여주지만, Chrome에선 popups 창 기능을 구현했을 때는 도구막대 버튼에 심어둔 onClicked event를 그냥 무시하고 무조건 Popups 창을 보여준다. 따라서 상황에 맞춰 웹페이지에서 선택한 글에 대한 검사 개시 방아쇠(trigger)로서 선택적으로 도구막대 버튼을 사용할 수 없게 되었다는 아쉬움이 있다. (이것은 manifest 파일에 popups html 파일을 지정하지 않은 채 setPopup() method를 써도 마찬가지.)

어차피 선택한 글에 대한 검사 개시의 방아쇠로 단축키(Option + Q/ㅂ) 혹은 Contextual 메뉴를 주로 쓰기 때문에 이에 따른 큰 불편은 없을 것이다.

Safari extension으로 먼저 나온 바른 말씨Google Chrome 용으로도 배포할 목적으로 개발하면서 부딪혔던 문제로, 대부분의 extension APIs와 그 구조는 서로 닮았기 때문에 코드 이전에는 별다른 어려움은 없었다. 그런데 한 가지 커다란 장벽과 마주쳤으니.

보통 extensions에 의해 페이지에 삽입되는 Content Scripts는 독립적인 sandbox 환경에서 실행되면서 원래 웹 페이지에 존재하는 스크립트와의 간섭을 걱정할 필요 없이 DOM을 만질 수 있게 되는데, 불행히도 Google Chrome extensions에선 iframes 접근이 차단되어 있어서 window.frames 값으로 undefined를 돌려준다. 이 문제는 알려진 버그로, 해결책으로 다음과 같이 Background Page에서 chrome.tabs.executeScript() 명령으로 해당 사이트의 DOM에다 직접 script tag을 생성해서 Chrome의 Sandbox 밖에서 실행되는 스크립트를 삽입해 주는 것이다.

chrome.tabs.executeScript(null, {file: 'scriptInjecting.js'}, scriptInjected);

script tag를 만들고 Sandbox를 탈출해서 실행될 스크립트를 삽입하는 scriptInjecting.js 파일의 내용은 다음과 같다.

(function(doc) {
  var s = doc.createElement('script');
  s.type = 'text/javascript';
  s.src = chrome.extension.getURL("escapedFromChromeSandbox.js");
  var x = doc.getElementsByTagName('script')[0];
  x.parentNode.insertBefore(s, x);
})(document);

이렇게 해서 삽입된 escapedFromChromeSandbox.js 파일에선 iframes의 속 내용을 들여다볼 수 있게 된다.

여기서 얻어진 정보는 가령, hidden input을 만들고 이놈의 value나 title 혹은 data 속성에다가 저장해 놓기만 하면, 나머진 종전처럼 해당 페이지의 DOM 접근이 가능한 Content Scripts에서 이곳에 저장된 정보를 읽고 message passing을 통해 background pages에 전달해주면 된다.

이 밖에도 사소한 것으로, 검사 결과를 보여주는 창을 마우스로 잡아서 이동시킬 수 있도록 하는 기능을 구현하는데, Safari에선 별문제 없던, HTML5의 Drag and Drop 기능을 빌려 쓰려 하였으나 drag시 마우스의 위치 값을 제대로 돌려받지 못하는 문제도 있어서 결국 약간 소모적일 수도 있는 Mouse events를 써야만 했다.

최근 많은 브라우저가 extensions 혹은 add-ons 형태로 사용자 입맛에 맞는 추가 기능을 제공하는 추세이고 또 각 브라우저가 가지고 있는 고유 API와 그 구현 방식도 서로의 차이점이 줄어들고 있기는 하지만, 아직은 개발자에게 혼동을 일으킬 수 있는 미묘한 차이를 보이면서 앞으로 어떤 통합된 개발 환경이 제공되었으면 하는 바람도 가지게 된다.

전부터 글을 쓸 때마다 맞춤법이 이게 맞는지 저게 맞는지 헷갈릴 때가 잦아서 웹상의 한국어 맞춤법/문법 검사기를 돌려서 확인하곤 했다.

문제는, 확인하고자 하는 글을 복사해서 맞춤법 검사기 페이지를 열어놓고 붙이는 일마저 가끔 거추장스러워서 그냥 넘어갈 때도 종종 있었다. 그런데 이런 웹페이지에서 진행되는 단순 반복되는 작업을 대신 해주는 것으로 Safari extension이 제격일 것이란 생각이 들었고, 그래서 개발을 시작한 지 일주일도 안 되어서 드디어 나의 첫 Safari extension이 완성되었다. 이름은 바른 말씨. 우연하게도 전에 만들었던 나의 widget 이름과도 비슷하다. 😀

이젠 웹페이지에 있는 글자를 마우스로 선택하고 tool bar 버튼이나 contextual 메뉴를 선택하면 바로 검사 결과를 볼 수 있으니, 개인적으로도 자주 애용할 듯하다. 역시 필요에 의한 개발의 결과물은 만족도가 더 높은 법인가 보다.

한 가지, iframe을 사용한 페이지는 문제가 발생할 소지가 많아서 작동을 막아 놓았다.
과연, 오늘부터 올리는 글의 맞춤법 고민을 한 방에 없앨 수 있을까?