우클릭/드래그 확장 프로그램(1) - 모험기
들어가며
이 글을 읽는 여러분 중 대부분은 웹서핑하던 도중, 마우스 우클릭이 되지 않거나 드래그가 막혀있는 웹사이트들을 봤던 경험이 있을 것이다. 그리고 이런 웹사이트들을 뚫기 위해 확장 프로그램을 설치하거나, 방법을 찾아 더 많은 웹사이트를 검색해 본 경험 또한 있을 것이다.
이러한 웹사이트들은 어떻게 마우스 우클릭과 드래그를 막았고, 어떤 방식으로 해당 기법을 뚫을 수 있었을까?
지금부터 하나하나 뜯어보고자 한다.
웹사이트에서 막히는 이유
기본적으로 우리가 사용하는 웹사이트에서 마우스 우클릭과 드래그가 막혀있다면, 이는 대부분 JavaScript Event
때문이다.
JavaScript Event
란? 웹 브라우저 내에서 발생하는 특정 동작 및 상황으로, 해당 상황에 알맞은 이벤트가 발생했을 시 지정된 코드가 반응하는 것을 말한다.
JavaScript Event의 정의만 읽어도 어떤 방식으로 마우스 우클릭과 드래그가 차단되는지 대충은 짐작할 수 있을 것이다. 그렇다면 대체 어떠한 Event가 사용됐길래 특정 웹사이트에서만 마우스의 동작이 막히는 것일까?
웹사이트에서 우클릭 막기
1 | <!DOCTYPE html> |
우선 다음과 같이 test_web.html
코드를 작성하여 가장 기본적인 웹사이트를 생성한다.
일반적인 웹사이트에서 우클릭을 시도하면 다음 사진과 같은 메뉴 창이 뜬다. 이는 우클릭이 막히지 않고 제대로 기능하고 있다는 것이다.
웹사이트에서 우클릭을 막기 위해서는 마우스 우클릭이 발생하고 있는 것을 알 수 있어야 한다.
이러한 기능을 담당하는 JavaScript Event는 무엇일까?
contextmenu
그림 1에서 보았던 것처럼, 일반적으로 마우스 우클릭을 시도했을 때 뜨는 메뉴 창을 Context Menu라고 부른다.
이는 JavaScript Event의 contextmenu
에서 확인할 수 있다.
contextmenu
란? 사용자가 Context Menu를 열려고 시도할 때 발생하는 이벤트로, 일반적으로 마우스 오른쪽 버튼을 누르거나 Context Menu 키(Shift + F10)를 누를 때 발생한다.
1 | addEventListener("contextmenu", (event) => { }) |
contextmenu를 사용하는 구문은 다음과 같다.
해당 JavaScript Event만 사용하면 그저 우클릭을 감지하는 흐름만 진행될 것이다. 그렇다면 우클릭을 감지하여 이를 막으려면 어떻게 코드를 작성해야 할까?
return false
첫 번째로 아주 간단한 방법이다. 그저 oncontextmenu
의 값을 false로 만들어 마우스 우클릭이 금지되게
만드는 것이다.oncontextmenu
는 contextmenu 이벤트와 기능은 같지만, HTML 속성이나 JavaScript의 핸들러 속성으로 지정되기에, return false를 사용하기 위해서는
1 | <div oncontextmenu = 'return false'> </div> // HTML |
HTML 속성과 JavaScript 핸들러 속성을 사용하여 각각의 return false 코드로 사용할 수 있다.
preventDefault()
두 번째로는 preventDefault()
메소드를 사용하여 마우스 우클릭을 막는 방법이다.
preventDefault()
란? 특정 이벤트가 발생했을 때, 기본적인 수행 동작을 막아주는 메소드이다.
이를 contextmenu 이벤트와 합쳐 사용한다면, contextmenu 이벤트가 발생했을 때(우클릭했을 때)
기본적인 동작이 막히게 되는 것이다.
1 | <script> |
preventDefault() 메소드를 JavaScript 코드로 작성한다면 다음과 같이 사용할 수 있다.
test_web.html 실습
return false 방법은 preventDefault() 방법보다 작성하긴 쉽지만, 일반적으로 JavaScript에선 preventDefault()를 더 명시적으로 사용한다기에 해당 글에서도 preventDefault() 방식으로 사용해 보려고 한다.
앞서 생성했던 test_web.html
코드에 preventDefault() 방법을 추가하여 우클릭을 막는 웹사이트로
수정해 보자.
1 | <!DOCTYPE html> |
우클릭이 막혀있다는 것을 알아보기 위해, 우클릭 시도 시 간단한 팝업 창이 나오게 코드를 추가했다.
`test_web.html` 웹사이트에서 우클릭했을 때, 'preventDefault()로 우클릭을 차단했습니다.'라는 안내 팝업 창이 나온다.
웹사이트에서 드래그 막기
성공적으로 우클릭 기능을 막았으니, 다음은 드래그를 막아보자.
dragstart
드래그를 감지하는 JavaScript Event는 바로 dragstart
이다.
dragstart
란? 사용자가 요소를 드래그하기 시작할 때 발생하는 이벤트로, 드래그하는 동안 지속적으로 발생하는drag
이벤트와 달리 처음 드래그하는 순간을 감지하여 발생한다.
1 | addEventListener("dragstart", (event) => { }) |
dragstart를 사용하는 구문은 다음과 같다.
selectstart
다만, dragstart는 이미지 영역이나 링크와 같은 드래그가 가능한 요소에서만 이벤트가 발생하고, 지금 우리가 살펴보는 주제에서는 텍스트를 드래그하는 데 중점을 두고 있으므로 해당 부분에서는 dragstart보다 selectstart
를 사용하는 것이 자연스럽다.
selectstart
란? 사용자가 새로운 선택을 시작할 때 발생하는 이벤트로, dragstart와 달리
일반적인 텍스트 문장에서도 드래그했을 시 이벤트가 발생한다.
1 | addEventListener("selectstart", (event) => { }) |
따라서 해당 글에서는 selectstart 이벤트를 기본으로 사용할 것이지만, 이미지나 또 다른 요소들을 사용한다면 dragstart 이벤트와 함께 적용하는 것이 편할 것이다. 그렇다면 이 요소들을 사용하여 드래그를 감지하고 막으려면 어떻게 코드를 작성해야 할까?
return false
사실 contextmenu와 selectstart는 둘 다 JavaScript Event이기에, Event가 들어가는 부분만 바꿔주면 코드는 거의 동일하게 가져가도 된다.
contextmenu - oncontextmenu처럼, selectstart 또한 기능은 같지만, HTML 속성이나 JavaScript
핸들러 속성으로 지정되는 onselectstart
를 사용하여 return false 값을 조정하면 된다.
1 | <div onselectstart = 'return false'> </div> // HTML |
동일하게 HTML 속성과 JavaScript 핸들러 속성을 사용하여 각각의 return false 코드로 사용할 수 있다.
preventDefault()
preventDefault() 방법도 동일하다. 이를 selectstart 이벤트와 합쳐 사용한다면, selectstart
이벤트가 발생했을 때(드래그했을 때) 기본적인 동작이 막히는 것이다.
1 | <script> |
preventDefault() 메소드를 JavaScript 코드로 작성한다면 다음과 같이 사용할 수 있다.
test_web.html 실습
앞서 우클릭을 막기 위해 수정했던 test_web.html
코드와 동일하게 preventDefault() 방법을 사용해
드래그도 막아보고자 한다.
1 | <!DOCTYPE html> |
드래그가 막혀있다는 것을 알아보기 위해, 드래그 시도 시 팝업 창이 나오게 코드를 추가했다.
다만, 해당 코드에서 우클릭 시에도 selectstart 이벤트가 발생하기에 팝업 창이 나타날 수 있다.
test_web.html
웹사이트에서 드래그를 시도했을 때, ‘preventDefault()로 드래그를 차단했습니다.’라는
안내 팝업 창이 나온다.
최종 test_web.html
1 | <!DOCTYPE html> |
앞서 우클릭과 드래그 시 팝업 창이 나오게 한 코드는 모두 삭제하고, 오로지 우클릭과 드래그 기능을 preventDefault()로 막은 최종 test_web.html
코드는 다음과 같이 작성할 수 있다.
웹사이트에서 JavaScript 뚫기
이제 우리는 웹사이트에서 JavaScript를 사용해 마우스 우클릭과 드래그를 막는 방법을 알아냈다.
그렇다면 그 많은 확장 프로그램은 어떻게 JavaScript를 뚫고 우클릭과 드래그 기능이 가능하게 만들었던
것일까?
별도의 코드 필요없이, 정말 간단하게 개발자 모드(F12)를 사용하여 JavaScript를 끄는 방법부터 설명하고자 한다.
개발자 모드를 키면 가장 먼저 보이는 화면은 아마 다음과 같을 것이다. 이제 우측의 톱니바퀴 모양을 눌러 Settings으로 들어가 Preferences 메뉴에서 맨 밑으로 내린다.
Debugger 항목의 Disable JavaScript 체크박스를 눌러 활성화하면,
웹사이트에 적용되어 있던 JavaScript가 사라져 마우스 우클릭과 드래그가 모두 제대로 적용된다.
이렇게 간단한 방법으로도 웹사이트의 JavaScript를 뚫을 수 있지만, 우리는 JavaScript Event를 사용해서 웹사이트의 우클릭과 드래그를 막은 만큼 다시 JavaScript Event를 사용하여 웹사이트를 뚫어보고자 한다.
웹사이트에서 preventDefault() 뚫기
앞서 우리는 addEventListener와 preventDefault()을 사용하여 contextmenu와 selectstart 이벤트를 등록하였으니, 이번엔 removeEventListener
를 사용하여 등록된 이벤트를 삭제할 수 있다.
1 | removeEventListener(type, listener) |
기본적인 removeEventListener 코드 구성은 다음과 같은데, 이때 필수로 포함되어야 하는 type
과 listener
를 조심해야 한다.
type
: EventListener를 제거할 이벤트 유형을 지정하는 문자열 (ex. ‘contextmenu’)listener
: 제거할 Event Handler 함수, 기존 addEventListener로 등록한 것과 동일한 함수여야 함
listener를 보면 기존 addEventListener로 등록한 것과 동일한 함수여야 한다는 조건이 있다. 다만, 우리가 기존에 작성했던 test_web.html
코드는 addEventListener를 사용할 때 함수를 지정하여 등록하지 않았기에, removeEventListener가 제대로 적용되지 않는다.
1 | <!DOCTYPE html> |
contextmenu 이벤트는 contexthandler 함수를, selectstart 이벤트는 selecthandler 함수를 지정하게끔 test_web.html
코드를 한 번 더 수정했다.
1 | document.removeEventListener('contextmenu', contexthandler); |
이제, 해당 코드의 웹사이트에서 개발자 모드(F12)를 열고 Console 창으로 이동하여 입력한다.
등록된 contexthandler
함수의 contextmenu 이벤트를 삭제하니 우클릭이 제대로 되고,
등록된 selecthandler
함수의 selectstart 이벤트를 삭제하니 드래그도 제대로 된다.
확장 프로그램 만들기
웹사이트에서 JavaScript를 뚫는 것까지 완료했지만, 웹사이트에 접속할 때마다 항상 우클릭과 드래그를 뚫기 위해 개발자 모드(F12)를 열고 Console 창에서 removeEventListener 코드를 입력하기 귀찮을 거다.
그렇기에 다음 글에서는 test_web.html
웹사이트에서 우클릭과 드래그를 하고 싶을 때 언제든 버튼을
누르기만 하면 removeEventListener 코드가 적용되는 확장 프로그램까지 만들어볼까 한다.
기본적으로 해당 글에서는 Chrome 브라우저에서 적용되는 확장 프로그램을 다룬다.
Chrome 메뉴 → 확장 프로그램 → 확장 프로그램 관리로 이동 시 chrome 확장 프로그램 사이트가 나온다.
이때, 우측 상단의 개발자 모드를 활성화하면 좌측 상단에 '압축해제된 확장 프로그램 로드' 버튼이 생기는데, 이 기능을 통해 우리가 제작한 코드도 확장 프로그램으로 사용이 가능해진다.
그렇기에 다음 글에서는, JavaScript 코드와 chrome 확장 프로그램 개발자 모드를 통해 웹사이트에서 마우스 우클릭과 드래그 차단 기능을 뚫는 프로그램을 개발해 보고자 한다.
마치며
🔗 test_web.html 웹사이트
우클릭과 드래그를 막고, Event Handler 함수 지정까지 완료한 test_web.html
코드를
웹사이트로 배포했다.
이 글을 읽는 여러분 모두가 직접 체험해 볼 수 있으며, 해당 글의 실습을 따라 해보며 JavaScript를
쉽게 익힐 수 있는 기회가 되길 바란다.
참고자료
mdn. (n.d.). Introduction to events. https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/Events
mdn. (n.d.). Element: contextmenu event. https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event
mdn. (n.d.). GlobalEventHandlers.oncontextmenu. https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event
mdn. (n.d.). Event: preventDefault() method. https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault
mdn. (n.d.). HTMLElement: dragstart event. https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragstart_event
mdn. (n.d.). Node: selectstart event. https://developer.mozilla.org/en-US/docs/Web/API/Node/selectstart_event
mdn. (n.d.). EventTarget: removeEventListener() method. https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
chrome for developers. (n.d.). Hello World extension. https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world?hl=en
chrome for developers. (n.d.). Inject scripts into the active tab. https://developer.chrome.com/docs/extensions/get-started/tutorial/scripts-activetab?hl=en
chrome for developers. (n.d.). The “activeTab” permission. https://developer.chrome.com/docs/extensions/develop/concepts/activeTab?hl=en
chrome for developers. (n.d.). Content scripts. https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts?hl=en