기술 가이드

Tampermonkey로 Inspect Element 변경을 로컬 브라우저에 영구 적용하는 방법

7 min read 웹 개발 업데이트됨 21 Oct 2025
Tampermonkey로 Inspect Element 변경을 로컬에 영구 적용하는 법
Tampermonkey로 Inspect Element 변경을 로컬에 영구 적용하는 법

소개

노트북을 들고 화면을 보는 사람

Inspect Element(요소 검사)는 웹 페이지의 앞단(HTML/CSS/JavaScript)을 실시간으로 변경해 보는 개발자 도구입니다. 일반적으로 브라우저에서 변경하면 새로고침하면 원래대로 돌아가지만, 로컬에서 동일한 변경을 항상 반영하고 싶을 때 Tampermonkey 같은 유저스크립트 매니저를 이용하면 됩니다. Tampermonkey는 특정 사이트가 로드될 때 자동으로 자바스크립트를 실행해 DOM을 수정하거나 추가 기능을 제공할 수 있습니다.

정의: 유저스크립트(userscript) — 사용자가 특정 웹사이트에서 실행하도록 작성한 작은 자바스크립트 스니펫입니다. Tampermonkey는 이러한 스크립트를 관리하고 실행하는 확장 프로그램입니다.

중요: 이 방법은 로컬 브라우저에서만 적용됩니다. 웹사이트 소스나 다른 사용자에게 영향을 주지 않습니다.

이 문서의 범위와 목적

  • 목적: Inspect Element로 한시적으로 적용한 변경을 개인 브라우저에서 지속적으로 유지하는 방법을 설명합니다.
  • 포함 내용: Tampermonkey 설치, userscript 메타데이터, 실제 예제(WhatsApp 공유 버튼 추가), SPA(싱글 페이지 앱) 대응, 보안·프라이버시 가이드, 테스트 및 운영 체크리스트.
  • 제외 항목: 서버 측 코드 변경, 다른 사용자에게 영향 주는 크랙이나 해킹 기법.

Tampermonkey란 무엇이며 어떻게 설치하나

Tampermonkey는 유저스크립트 매니저로 크롬(Chrome), 엣지(Edge), 오페라(Opera), 파이어폭스(Firefox), 사파리(Safari) 등 주요 브라우저에서 사용 가능하며 브라우저 확장 프로그램으로 동작합니다. 설치 후에는 사용자가 작성한 스크립트를 저장해 페이지가 로드될 때 자동으로 실행합니다.

설치 요약:

  1. 브라우저 확장(Extensions) 아이콘을 클릭하거나 브라우저용 스토어에서 Tampermonkey를 검색합니다.
  2. 공식 페이지에서 브라우저를 선택하고 스토어로 이동한 뒤 설치(Install)를 클릭합니다.
  3. 설치 후 브라우저 도구 모음에 Tampermonkey 아이콘이 추가됩니다.

Tampermonkey 다운로드 화면

참고: Chromium 기반 브라우저는 Chrome 스토어에서 설치하면 대부분 정상 작동합니다.

사용 전 고려사항

  • 웹사이트 정책: 타사 스크립트를 실행하는 것이 해당 사이트의 이용약관이나 보안 정책에 위배되지 않는지 확인하세요.
  • 민감한 데이터: 로그인 페이지, 결제 페이지, 개인정보를 다루는 페이지에서 임의 스크립트를 실행하는 것은 위험합니다.
  • 범위 제한: Tampermonkey의 @match 또는 @include 메타데이터로 스크립트 적용 범위를 정확히 제한하세요.
  • 신뢰성: 공개된 서드파티 유저스크립트는 신뢰되지 않은 소스의 코드가 포함될 수 있으므로 코드 리뷰를 반드시 하세요.

중요: 사용자는 자신의 로컬 환경에서만 변화를 보며, 사이트의 실제 서버나 다른 사용자 경험에는 영향을 미치지 않습니다.

Tampermonkey 시작하기

  1. 브라우저 툴바에서 Tampermonkey 아이콘을 클릭하고 대시보드로 이동합니다.
  2. “Create a new script”(새 스크립트 만들기)를 선택합니다.
  3. 기본 템플릿(메타데이터 블록)이 에디터에 표시됩니다. 이 블록은 스크립트 이름, 버전, 실행 대상, 권한 등을 정의합니다.

다음은 Tampermonkey 메타데이터 예시입니다. 실제 에디터에는 아래와 같은 주석 블록이 들어갑니다.

// ==UserScript==
// @name        New Userscript
// @namespace   http://tampermonkey.net/
// @version     0.1
// @description try to take over the world!
// @author      You
// @match       http://example.com/*
// @grant       none
// ==/UserScript==

(function() {
    'use strict';
    // Your code here...
})();

핵심: @match는 스크립트를 어느 URL에서 실행할지 지정합니다. 정확하게 지정하면 의도하지 않은 사이트에서 스크립트가 실행되는 위험을 줄일 수 있습니다.

예제: 게시글 끝에 WhatsApp 공유 버튼 추가하기

목표: MakeUseOf 같은 블로그의 기사 하단 공유 위젯에 WhatsApp 공유 버튼을 추가합니다. 이 예제는 구조가 단순한 정적 페이지나 클래스 기반 요소가 있는 사이트에 유용하며, SPA일 경우 추가 처리(변화 감지 등)가 필요합니다.

원리 요약:

  • 페이지 로드 시 sharing 위젯을 찾습니다.
  • 버튼 요소를 생성하고 스타일과 접근성 속성을 설정합니다.
  • 클릭 이벤트로 WhatsApp 공유 URL을 생성해 새 탭을 엽니다.

MakeUseOf 공유 위젯 예시

기본 버튼 생성 코드(예시):

// create a WhatsApp button
const Whatsapp_btn = document.createElement('button');
Whatsapp_btn.textContent = 'Share';

// add styling to the button
Whatsapp_btn.style.backgroundColor = '#075E54';
Whatsapp_btn.style.color = 'white';
Whatsapp_btn.style.border = 'none';
Whatsapp_btn.style.borderRadius = '5px';
Whatsapp_btn.style.padding = '10px';

// find existing sharing widget
const sharingDiv = document.querySelector('div.sharing.bottom');
if (sharingDiv) {
  sharingDiv.appendChild(Whatsapp_btn);
}

function generateWALink() {
  const pageURL = encodeURIComponent(window.location.href);
  return `https://api.whatsapp.com/send?text=${pageURL}`;
}

Whatsapp_btn.addEventListener('click', () => {
  const whatsappURL = generateWALink();
  window.open(whatsappURL, '_blank');
});

위 코드를 Tampermonkey 에디터에 붙여넣고 저장(Ctrl+S)하면, 해당 페이지가 로드될 때마다 버튼이 자동으로 추가됩니다. 그러나 이 기본 코드는 다음과 같은 상황에서는 부족합니다.

  • SPA(React/Vue 등)에서 동적으로 DOM이 바뀔 때 최초 로드에 공유 위젯이 없으면 버튼을 추가하지 못함
  • 여러 페이지 템플릿(클래스명이나 구조가 다른 경우)에서는 querySelector가 실패함
  • 접근성(스크린리더) 대비 속성이 없음
  • 다국어 처리나 아이콘 노출, 툴팁 등 추가 요구사항

다음 섹션에서는 더 견고한 패턴을 제시합니다.

견고한 userscript 패턴(권장)

여러 상황에서 잘 동작하게 하려면 다음 패턴을 적용하세요.

  1. 메타데이터 정확히 지정: @match, @run-at(document-idle 또는 document-end) 등
  2. 초기 DOM에서 요소가 없을 때를 대비한 MutationObserver 사용
  3. 여러 선택자(백업)를 시도하거나 텍스트 기반 탐색을 병행
  4. 접근성(aria-label, role) 및 키보드 조작 지원
  5. 오류를 콘솔에 로깅하되 사용자에게는 무해하게 동작 유지

샘플 개선 코드(옵션: 아이콘, aria, MutationObserver 포함):

// ==UserScript==
// @name        WhatsApp Share Button
// @namespace   http://tampermonkey.net/
// @version     1.0
// @description Add WhatsApp share button to article sharing widget
// @match       https://www.makeuseof.com/*
// @grant       none
// @run-at      document-idle
// ==/UserScript==

(function() {
  'use strict';

  function createWAButton() {
    const btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'tm-wa-share';
    btn.setAttribute('aria-label', 'Share via WhatsApp');
    btn.style.cssText = 'background:#075E54;color:#fff;border:none;border-radius:5px;padding:8px 12px;cursor:pointer;display:inline-flex;align-items:center;gap:8px;';

    // optional icon (emoji or inline SVG)
    const icon = document.createElement('span');
    icon.textContent = '💬';
    icon.setAttribute('aria-hidden', 'true');
    btn.appendChild(icon);

    const span = document.createElement('span');
    span.textContent = 'WhatsApp';
    btn.appendChild(span);

    btn.addEventListener('click', (e) => {
      e.preventDefault();
      const url = `https://api.whatsapp.com/send?text=${encodeURIComponent(window.location.href)}`;
      window.open(url, '_blank');
    });

    return btn;
  }

  function insertButtonIfMissing(parent) {
    if (!parent.querySelector('.tm-wa-share')) {
      parent.appendChild(createWAButton());
    }
  }

  function tryInsert() {
    const selectors = ['div.sharing.bottom', '.share-widget', '#share-buttons'];
    for (const sel of selectors) {
      const el = document.querySelector(sel);
      if (el) {
        insertButtonIfMissing(el);
        return true;
      }
    }
    return false;
  }

  // 최초 시도
  if (!tryInsert()) {
    // 동적 사이트를 위해 MutationObserver 사용
    const observer = new MutationObserver((mutations, obs) => {
      if (tryInsert()) {
        obs.disconnect();
      }
    });

    observer.observe(document.body, { childList: true, subtree: true });

    // 타임아웃: 일정 시간 후에도 못 찾으면 중단
    setTimeout(() => observer.disconnect(), 30000);
  }
})();

이 패턴은 SPA에서 sharing 위젯이 나중에 생성되는 경우에도 버튼을 삽입합니다. 또한 여러 선택자를 시도하므로 구조가 다른 사이트에도 적용 가능성이 높습니다.

대안과 비교

  • Stylus/CSS 사용자 스타일러: CSS만으로 시각적 변경을 하려면 Stylus나 UserCSS를 사용하세요. DOM 변경(요소 추가/이벤트 바인딩)이 필요하면 userscript가 필요합니다.
  • 브라우저 개발자 도구의 Local Overrides(Chrome DevTools): 파일을 로컬에 매핑해 스타일/스크립트 파일을 덮어쓸 수 있지만 설정이 복잡하고 Tampermonkey처럼 스크립트 논리를 쉽게 작성하긴 어렵습니다.
  • 브라우저 확장 직접 개발: 더 많은 권한·배포를 원하면 브라우저 확장으로 전환하세요. 개발·유지 비용이 높습니다.

언제 Tampermonkey가 적절하지 않은가(반례):

  • 조직 정책상 확장 설치가 금지된 경우
  • 공개 배포로 다른 사용자에게 영향을 주려면 정식 확장을 개발해야 함
  • 민감한 트랜잭션(결제, 인증) 자동화는 보안상 권장되지 않음

보안 하드닝 권장사항

  • 최소 권한 원칙: @grant를 명확히 설정해 불필요한 브라우저 API 접근을 제한합니다.
  • 코드 검토: 타사 스크립트를 설치하기 전에 코드를 검토하세요. 원격 리소스를 불러오는 코드(fetch, xhr, script src 등)는 특히 주의하세요.
  • HTTPS 강제: 가능하면 @match에서 https://로 한정하고 http를 허용할 경우 위험을 인지하세요.
  • 로그 최소화: 콘솔에 민감한 정보를 출력하지 마세요.
  • 타임아웃과 예외 처리: 무한 관찰이나 무한 루프 방지를 위해 타임아웃을 두세요.

개인정보 및 규정 준수 노트

  • 개인 데이터 취급: userscript가 로그인 쿠키, 토큰, 개인 식별 정보를 읽어 외부로 전송해서는 안 됩니다.
  • 기업 환경: 회사 컴퓨터에서 사용 시 IT 정책과 GDPR/지역 규정을 확인하세요. 로컬에서 개인정보를 처리하는 스크립트는 법적 책임이 따를 수 있습니다.

테스트 케이스와 수용 기준

간단한 테스트 목록(테스트 케이스):

  1. 정상 케이스: 타깃 URL 로드 시 공유 위젯에 WhatsApp 버튼이 추가되는가?
  2. SPA 케이스: 라우팅으로 페이지가 변경될 때 버튼이 사라졌다가 재삽입되는가?
  3. 다수 템플릿: 선택자 A, B, C 중 어디서든 버튼이 한 번만 추가되는가?
  4. 접근성: 버튼에 aria-label이 있고 키보드로 포커스 가능한가?
  5. 비정상 상황: 위젯이 없거나 DOM 구조가 크게 변경된 경우에도 콘솔 오류 없이 안정적으로 실패하는가?

수용 기준(Критерии приёмки):

  • 모든 주요 기사 페이지에서 버튼이 정상적으로 표시되어 클릭 시 WhatsApp 공유 창이 열려야 합니다.
  • DOM 구조가 다른 경우에도 최소 하나의 선택자로 버튼이 추가되어야 합니다.
  • 30초 내에 삽입되지 않으면 관찰을 중단하고 오류를 남기지 않아야 합니다.

운영 및 유지 보수 체크리스트

개발자용 체크리스트:

  • @match 범위를 최소화했는가?
  • 외부 스크립트 또는 원격 리소스를 불러오지 않는가?
  • MutationObserver에 타임아웃을 넣었는가?
  • aria 속성 및 키보드 접근성을 추가했는가?
  • 로컬에서 테스트 후 버전 태그(@version)를 올렸는가?

파워유저용 체크리스트:

  • Tampermonkey 대시보드에서 스크립트 활성화/비활성화 테스트를 했는가?
  • 다른 확장과 충돌 여부(특히 다른 userscript) 확인했는가?

IT 관리자용 체크리스트:

  • 조직 정책에 따라 확장 설치 허용 여부를 검토했는가?
  • 배포할 필요가 있다면 내부적으로 리뷰 및 서명 프로세스를 거쳤는가?

배포 및 버전 관리 권장 방법

  • 로컬에서 스크립트를 개발하고 Tampermonkey 대시보드의 “Export” 기능으로 백업합니다.
  • 자체적으로 여러 스크립트를 관리한다면 Git 저장소에서 스크립트 버전을 관리하고, 변경 시 주석과 버전(@version)을 업데이트하세요.
  • 공개 배포가 필요하면 브라우저 스토어 정책을 확인하고 정식 확장 개발을 검토하세요.

문제 해결 팁

  • 버튼이 나타나지 않으면 콘솔에서 querySelector로 선택자가 올바른지 직접 확인하세요.
  • SPA에서 삽입되지 않으면 MutationObserver를 사용하거나 페이지 라우트 이벤트를 후킹하세요.
  • 스타일이 다른 버튼에 의해 가려지면 z-index를 올리거나 display 특성을 조정하세요.

소규모 방법론(미니-방법론)

  1. 목표 정의: 어떤 요소를 고정할지(추가/교체/숨김) 정확히 정합니다.
  2. 선택자 식별: 개발자 도구로 대상 컨테이너의 클래스를 찾습니다.
  3. 스크립트 초안: 버튼 생성, 스타일, 이벤트 핸들러를 만듭니다.
  4. 테스트: 정적/동적 페이지에서 동작 확인 후 예외 처리 추가합니다.
  5. 보안 점검: 외부 호출, 쿠키 접근 여부 점검
  6. 배포: 개인용이면 Tampermonkey로 저장, 조직용이면 정책에 맞게 관리

용어집(한 줄)

  • userscript: 사용자가 웹페이지에서 실행하도록 작성한 커스텀 자바스크립트
  • @match: Tampermonkey 메타데이터로 스크립트 실행 대상을 지정하는 패턴
  • MutationObserver: DOM 변경을 비동기적으로 감지하는 웹 API

요약

Tampermonkey는 Inspect Element로 한시적으로 수정했던 UI/기능을 로컬 브라우저에서 영구적으로 유지할 때 매우 유용한 도구입니다. 올바른 메타데이터 설정, MutationObserver 같은 동적 대응 패턴, 보안·프라이버시 점검을 통해 안전하고 신뢰성 있게 userscript를 운영할 수 있습니다.

핵심 요점:

  • @match로 스크립트 적용 범위를 제한하세요.
  • SPA나 동적 콘텐츠에는 MutationObserver를 사용하세요.
  • 타사 스크립트는 코드 리뷰 후 설치하세요.
  • 민감한 데이터 처리와 관련한 법규와 회사 정책을 항상 확인하세요.

추가 리소스: Tampermonkey 공식 문서, 브라우저 개발자 도구(Elements, Console, Network) 사용법을 숙지하면 userscript 개발과 디버깅이 더 쉬워집니다.

공유 위젯을 검사하는 모습

WhatsApp 공유 버튼 예시

WhatsApp 링크 공유 스크린샷

Important: 공개되지 않은 타인의 코드나 민감한 정보를 자동으로 전송하거나 공유하는 스크립트는 절대 사용하지 마십시오.

공유하기: X/Twitter Facebook LinkedIn Telegram
저자
편집

유사한 자료

iPhone 사진 파일 크기 줄이는 방법 — 저장·공유 최적화
사진 관리

iPhone 사진 파일 크기 줄이는 방법 — 저장·공유 최적화

iPhone 중요 배터리 메시지 원인·해결 가이드
아이폰 가이드

iPhone 중요 배터리 메시지 원인·해결 가이드

CentOS 7에 Apache Cassandra 설치 가이드
데이터베이스

CentOS 7에 Apache Cassandra 설치 가이드

Trakkboard로 데스크톱에서 Google Analytics 보기
도구

Trakkboard로 데스크톱에서 Google Analytics 보기

Linux에서 .sh 파일 설치하는 방법
가이드

Linux에서 .sh 파일 설치하는 방법

iPad 분할 키보드 해결법
iPad 팁

iPad 분할 키보드 해결법