NOMO.asia
1.
Greasemonkey 4 확장기능은 57.0 에서 GM_setValue 함수를 지원하지 않는다.
2.
1번을 해결한 이후 나타난 문제는 exportFunction 함수가 undefined 라고 나오는 문제이다. 

최근 Firefox 57.0 버전으로 업데이트 했는데, 몇몇 유저스크립트가 작동하지 않아서 확인해보니 아래 두가지가 문제였다.

1. Greasemonkey 4 확장기능은 57.0 에서 GM_setValue 함수를 지원하지 않는다.

GM_setValue 함수는 확장기능이 관리하는 저장소에 유저 설정, 캐시 데이터 등 값을 저장하기 위하여 쓰인다.
그런데 Greasemonkey 4 에서는 해당 함수를 지원하지 않는다고 한다. 정확히는 GM dot 함수로 바뀌었다.

Greasemonkey 4 Announcement (https://www.greasespot.net/2017/09/greasemonkey-4-for-script-authors.html)
위 문서를 참고해보니 기존의 GM_ 함수는 동기식이었고, 이것을 비동기식으로 바꾸기 위하여 작업을 한 결과가 GM dot 함수라고 한다. GM.setValue 처럼 GM 에 dot(.)을 붙인 함수의 형태로 쓴다는데, 그냥 함수만 바꾸면 되는 것은 아니고 사용법까지 달라지니 위 문서를 참조하는 것이 좋겠다. 제공되는 polyfill.js 를 이용하여 기존 유저스크립트 또는 다른 Userscript 엔진과도 호환성을 유지하는 방법도 나와있다.
async 와 await 에 대해서는 이 문서 에 예제가 잘 나와있다.

개발자 입장에서 근본적인 해결 방법은 코드 수정이겠지만, 만약 당신이 단순한 유저스크립트 사용자라면 Greasemonkey 확장기능의 사용 대신에 violentmonkey 확장기능을 사용하면 기존의 GM_setValue 함수를 지원하므로 간단히 해결할 수 있다.


2. 1번을 해결한 이후 나타난 문제는 exportFunction 함수가 undefined 라고 나오는 문제이다. 

(exportFunction 함수를 어디에, 왜 사용하는지는 http://nomo.asia/340 를 참고)
Firefox 57.0 에서 지원하지 않는 것인지 아니면 Violentmonkey 에서 지원하지 않는 것인지는 확인해보지 않았다. 일단 위의 Greasemonkey 4 Announcement 문서에서는 unsafeWindow 보다 cloneInto and exportFunction 를 사용하라고 설명하고 있는 것 같은데 왜 안 되는지는 잘 모르겠다.


$(document).ready(function(){

unsafeWindow.fB = function() {

            // 새로운 function 내용

 console.log("fB was hijacked!");

 };

})



출처: http://nomo.asia/340 [이름없음]

참고로 당시 상황은 아래와 같았다.

  1. Userscript 를 적용할 페이지에서 로드하는 js 파일 내에 fA, fB 라는 이름의 함수(function) 가 존재한다.
  2. fA 함수의 내부에서는 fB를 호출한다.
  3. 내가 Userscript를 이용하여 덮어씌우고 싶은(Override) 함수는 fB 함수이다.

Chrome 은 그냥 아래와 같이 하면 잘 됐었다.

1
2
3
4
5
6
$(document).ready(function(){
    unsafeWindow.fB = function() {
            // 새로운 function 내용
    console.log("fB was hijacked!");
    };
})


Firefox 는 위와 같이 하면 안 돼서 아래와 같은 방법을 썼었다.

1
2
3
4
5
6
7
8
9
10
11
12
$(document).ready(function(){
    newfB = function() {
        // 새로운 function 내용
        console.log("fB was hijacked!");
    };
    unsafeWindow.fB = exportFunction (newfB, unsafeWindow);
    newfA = function() {
        newfB(); // fB 를 newfB로 대체한다.
        console.log("fA was hijacked!");
    };
    unsafeWindow.fA = exportFunction (newfA, unsafeWindow);
})

$(document).ready(function(){

unsafeWindow.fB = function() {

            // 새로운 function 내용

 console.log("fB was hijacked!");

 };

})



출처: http://nomo.asia/340 [이름없음]

Chrome 의 경우 별 문제가 없다. 아래와 같이 하면 문제 없이 작동한다. 내가 바꾸고싶은 함수는 fB 뿐이므로 fB의 내용만 바꿔주었다.


$(document).ready(function(){

unsafeWindow.fB = function() {

            // 새로운 function 내용

 console.log("fB was hijacked!");

 };

})


run-at : document-start 조건을 추가하였으므로, document ready 내에 hijacking 코드를 추가해주어야 제대로 적용된다.



출처: http://nomo.asia/340 [이름없음]


$(document).ready(function(){

unsafeWindow.fB = function() {

            // 새로운 function 내용

 console.log("fB was hijacked!");

 };

})



출처: http://nomo.asia/340 [이름없음]


$(document).ready(function(){

unsafeWindow.fB = function() {

            // 새로운 function 내용

 console.log("fB was hijacked!");

 };

})



출처: http://nomo.asia/340 [이름없음]


해결 방법은, 그냥 Chrome 처럼 하면 잘 된다. 이게 Firefox 57.0 이라서 그런건지 Greasemonkey 와 Violentmonkey 의 차이인지는 모르겠지만, 또는 내 코드가 바뀌어서 그런건지는 모르겠지만 Chrome 의 경우처럼 하면 잘 된다. 다만 기존에 브라우저별 호환성을 위해 분기를 해놓았었는데 해당 부분을 아래와 같이 수정했다.

1
2
3
4
5
6
if( (web_browser === 'firefox') && (typeof exportFunction === 'function') ){
    // Firefox 57.0 미만 & Greasemonkey 용 코드
}
else {
    // Chrome 및 Firefox 57.0 이상 & Violentmonkey 용 코드
}

여전히 Firefox 57.0 미만 버전을 사용하는 사용자도 있을 수 있기 때문에, exportFunction 함수가 정의되어 있으면 기존 분기를 사용하도록 설정했다.


이 글이 도움이 되셨다면? 커피 한 잔을 후원해주세요~ Buy Me A Coffee