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) 등 주요 브라우저에서 사용 가능하며 브라우저 확장 프로그램으로 동작합니다. 설치 후에는 사용자가 작성한 스크립트를 저장해 페이지가 로드될 때 자동으로 실행합니다.
설치 요약:
- 브라우저 확장(Extensions) 아이콘을 클릭하거나 브라우저용 스토어에서 Tampermonkey를 검색합니다.
- 공식 페이지에서 브라우저를 선택하고 스토어로 이동한 뒤 설치(Install)를 클릭합니다.
- 설치 후 브라우저 도구 모음에 Tampermonkey 아이콘이 추가됩니다.
참고: Chromium 기반 브라우저는 Chrome 스토어에서 설치하면 대부분 정상 작동합니다.
사용 전 고려사항
- 웹사이트 정책: 타사 스크립트를 실행하는 것이 해당 사이트의 이용약관이나 보안 정책에 위배되지 않는지 확인하세요.
- 민감한 데이터: 로그인 페이지, 결제 페이지, 개인정보를 다루는 페이지에서 임의 스크립트를 실행하는 것은 위험합니다.
- 범위 제한: Tampermonkey의 @match 또는 @include 메타데이터로 스크립트 적용 범위를 정확히 제한하세요.
- 신뢰성: 공개된 서드파티 유저스크립트는 신뢰되지 않은 소스의 코드가 포함될 수 있으므로 코드 리뷰를 반드시 하세요.
중요: 사용자는 자신의 로컬 환경에서만 변화를 보며, 사이트의 실제 서버나 다른 사용자 경험에는 영향을 미치지 않습니다.
Tampermonkey 시작하기
- 브라우저 툴바에서 Tampermonkey 아이콘을 클릭하고 대시보드로 이동합니다.
- “Create a new script”(새 스크립트 만들기)를 선택합니다.
- 기본 템플릿(메타데이터 블록)이 에디터에 표시됩니다. 이 블록은 스크립트 이름, 버전, 실행 대상, 권한 등을 정의합니다.
다음은 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을 생성해 새 탭을 엽니다.
기본 버튼 생성 코드(예시):
// 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 패턴(권장)
여러 상황에서 잘 동작하게 하려면 다음 패턴을 적용하세요.
- 메타데이터 정확히 지정: @match, @run-at(document-idle 또는 document-end) 등
- 초기 DOM에서 요소가 없을 때를 대비한 MutationObserver 사용
- 여러 선택자(백업)를 시도하거나 텍스트 기반 탐색을 병행
- 접근성(aria-label, role) 및 키보드 조작 지원
- 오류를 콘솔에 로깅하되 사용자에게는 무해하게 동작 유지
샘플 개선 코드(옵션: 아이콘, 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/지역 규정을 확인하세요. 로컬에서 개인정보를 처리하는 스크립트는 법적 책임이 따를 수 있습니다.
테스트 케이스와 수용 기준
간단한 테스트 목록(테스트 케이스):
- 정상 케이스: 타깃 URL 로드 시 공유 위젯에 WhatsApp 버튼이 추가되는가?
- SPA 케이스: 라우팅으로 페이지가 변경될 때 버튼이 사라졌다가 재삽입되는가?
- 다수 템플릿: 선택자 A, B, C 중 어디서든 버튼이 한 번만 추가되는가?
- 접근성: 버튼에 aria-label이 있고 키보드로 포커스 가능한가?
- 비정상 상황: 위젯이 없거나 DOM 구조가 크게 변경된 경우에도 콘솔 오류 없이 안정적으로 실패하는가?
수용 기준(Критерии приёмки):
- 모든 주요 기사 페이지에서 버튼이 정상적으로 표시되어 클릭 시 WhatsApp 공유 창이 열려야 합니다.
- DOM 구조가 다른 경우에도 최소 하나의 선택자로 버튼이 추가되어야 합니다.
- 30초 내에 삽입되지 않으면 관찰을 중단하고 오류를 남기지 않아야 합니다.
운영 및 유지 보수 체크리스트
개발자용 체크리스트:
- @match 범위를 최소화했는가?
- 외부 스크립트 또는 원격 리소스를 불러오지 않는가?
- MutationObserver에 타임아웃을 넣었는가?
- aria 속성 및 키보드 접근성을 추가했는가?
- 로컬에서 테스트 후 버전 태그(@version)를 올렸는가?
파워유저용 체크리스트:
- Tampermonkey 대시보드에서 스크립트 활성화/비활성화 테스트를 했는가?
- 다른 확장과 충돌 여부(특히 다른 userscript) 확인했는가?
IT 관리자용 체크리스트:
- 조직 정책에 따라 확장 설치 허용 여부를 검토했는가?
- 배포할 필요가 있다면 내부적으로 리뷰 및 서명 프로세스를 거쳤는가?
배포 및 버전 관리 권장 방법
- 로컬에서 스크립트를 개발하고 Tampermonkey 대시보드의 “Export” 기능으로 백업합니다.
- 자체적으로 여러 스크립트를 관리한다면 Git 저장소에서 스크립트 버전을 관리하고, 변경 시 주석과 버전(@version)을 업데이트하세요.
- 공개 배포가 필요하면 브라우저 스토어 정책을 확인하고 정식 확장 개발을 검토하세요.
문제 해결 팁
- 버튼이 나타나지 않으면 콘솔에서 querySelector로 선택자가 올바른지 직접 확인하세요.
- SPA에서 삽입되지 않으면 MutationObserver를 사용하거나 페이지 라우트 이벤트를 후킹하세요.
- 스타일이 다른 버튼에 의해 가려지면 z-index를 올리거나 display 특성을 조정하세요.
소규모 방법론(미니-방법론)
- 목표 정의: 어떤 요소를 고정할지(추가/교체/숨김) 정확히 정합니다.
- 선택자 식별: 개발자 도구로 대상 컨테이너의 클래스를 찾습니다.
- 스크립트 초안: 버튼 생성, 스타일, 이벤트 핸들러를 만듭니다.
- 테스트: 정적/동적 페이지에서 동작 확인 후 예외 처리 추가합니다.
- 보안 점검: 외부 호출, 쿠키 접근 여부 점검
- 배포: 개인용이면 Tampermonkey로 저장, 조직용이면 정책에 맞게 관리
용어집(한 줄)
- userscript: 사용자가 웹페이지에서 실행하도록 작성한 커스텀 자바스크립트
- @match: Tampermonkey 메타데이터로 스크립트 실행 대상을 지정하는 패턴
- MutationObserver: DOM 변경을 비동기적으로 감지하는 웹 API
요약
Tampermonkey는 Inspect Element로 한시적으로 수정했던 UI/기능을 로컬 브라우저에서 영구적으로 유지할 때 매우 유용한 도구입니다. 올바른 메타데이터 설정, MutationObserver 같은 동적 대응 패턴, 보안·프라이버시 점검을 통해 안전하고 신뢰성 있게 userscript를 운영할 수 있습니다.
핵심 요점:
- @match로 스크립트 적용 범위를 제한하세요.
- SPA나 동적 콘텐츠에는 MutationObserver를 사용하세요.
- 타사 스크립트는 코드 리뷰 후 설치하세요.
- 민감한 데이터 처리와 관련한 법규와 회사 정책을 항상 확인하세요.
추가 리소스: Tampermonkey 공식 문서, 브라우저 개발자 도구(Elements, Console, Network) 사용법을 숙지하면 userscript 개발과 디버깅이 더 쉬워집니다.
Important: 공개되지 않은 타인의 코드나 민감한 정보를 자동으로 전송하거나 공유하는 스크립트는 절대 사용하지 마십시오.