8월 11, 2026

#끄적끄적_4_Tampermonkey활용 하기

항상 템퍼몽키 사용 중 코드를 변경하는게 귀찮았다.

당연 모바일에서는 더더욱 귀찮았고. 관리가 힘들었다.

그러다가 떠오른생각! 동적으로 코드를 가져와서 적용하면 어떨까?

document-start를 적용하여 문서 시작시 바로 누구보다 빠르게 홈서버에 올려둔 js를 가져와 동적으로 적용하면 서버에 코드 수정하여 업로드하면 모든 템퍼몽키에서 적용이된다.

(function() {
    'use strict';

    const CACHE_KEY = "";
    const scriptUrl = "";

    // 스크립트 실행 함수
    const runScript = (code) => {
        try {
            new Function(code)();
            console.log("스크립트 실행 완료");
        } catch (e) {
            console.error("원격 스크립트 실행 오류:", e);
        }
    };

    // 외부 스크립트가 호출할 통신 API 노출
    unsafeWindow.TM_API = {
        request: (params) => {
            return new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    ...params,
                    onload: (res) => resolve({ status: res.status, response: res.response, headers: res.responseHeaders }),
                    onerror: reject
                });
            });
        }
    };
    console.log("[Bridge] TM_API 통신 창구 개설 완료");

    // 1. 캐시 확인
    const cachedCode = GM_getValue(CACHE_KEY);

    if (cachedCode) {
        // [캐시 있음] 즉시 실행
        console.log("캐시된 스크립트 실행");
        runScript(cachedCode);
    }

    // 2. 최신본 확인 및 업데이트 (캐시 유무와 상관없이 항상 수행)
    GM_xmlhttpRequest({
        method: "GET",
        url: scriptUrl + "?t=" + new Date().getTime(),
        onload: function(response) {
            if (response.status === 200) {
                const newCode = response.responseText;

                // 캐시가 없었거나, 캐시와 내용이 다를 경우 업데이트
                if (!cachedCode || newCode !== cachedCode) {
                    console.log("최신 스크립트 저장 및 적용");
                    GM_setValue(CACHE_KEY, newCode);

                    // 캐시가 없었다면 이제 실행
                    if (!cachedCode) {
                        runScript(newCode);
                    } else {
                        // 이미 실행중인 스크립트가 있다면 사용자에게 알리거나 재실행 고려
                        console.log("스크립트가 업데이트되었습니다. 새로고침 시 적용됩니다.");
                    }
                }
            }
        },
        onerror: function(err) {
            console.error("원격 스크립트 업데이트 실패:", err);
        }
    });
})();

TM_API는 cors 우회를 위해 적용해두었다. 저렇게 해두면 이미 캐시된 js가 있으면 바로 적용하고 이후 새로운 js를 가져와 캐시에 저장해둔다.

이후 새로고침되면 다시 캐시된걸 가져오니. 2번 정도 새로고침하면 최신 js가 적용 되는거고. 만들어둔 TM_API를 이용하면 cors를 우회해 다운로드나 전송 등이 가능해진다.

// async/await 사용 예시
async function fetchExternalData() {
    try {
        const response = await TM_API.request({
            method: "GET",
            url: "https://example.com", // CORS나 HTTP 도메인도 통신 가능
            headers: {
                "Accept": "application/json"
            }
        });

        console.log("응답 상태 코드:", response.status);
        console.log("받은 데이터:", response.response);
    } catch (error) {
        console.error("통신 실패:", error);
    }
}

fetchExternalData();
// .then() 사용 예시
TM_API.request({
    method: "POST",
    url: "http://my-http-backend.com", // HTTPS 페이지 내에서도 HTTP 주소로 전송 가능
    headers: {
        "Content-Type": "application/json"
    },
    data: JSON.stringify({
        username: "user123",
        score: 100
    })
}).then(res => {
    console.log("저장 완료:", res.response);
}).catch(err => {
    console.error("에러 발생:", err);
});

이런식으로 사용이 가능하다.

이렇게 하면 pc에서 js코드 수정 후 홈 서버에 업로드하고 모바일에서 새로고침 2-3회 하면 수정된 js코드가 적용되는걸 볼 수 있다.