유저 스크립트 소개

유저 스크립트는 모던 브라우저 확장browser extension과 비슷한 기능을 갖춘 자바스크립트 코드 스니펫snippet입니다. 브라우저 확장이 광고 차단이나, 다크모드 프로그램 처럼 특정 웹 서비스의 UI를 수정하는 소프트웨어라면, 유저스크립트는 이보다 작은 규모로 1~2줄 정도의 복잡하지 않은 가벼운 수정을 위해 주로 쓰입니다.

본 글은 유저스크립트 사용에 대해서 실제 사례와 함께 예시 코드를 소개합니다. 유저 스크립트를 사용하려면 유저 스크립트 매니저라는 브라우저 확장의 도움이 필요합니다. 하지만 브라우저마다 다른 설치와 사용 방법에 대해서는 약간 주제에 벗어난 내용으로 자세히 다루지 않습니다.

설치와 사용법은 여러 유저스크립트 매니저의 공식 홈페이지에서 확인 가능합니다. 브라우저마다 지원 여부가 다르니 참고 바랍니다.

보통 어떤 작업을 하는가

자바스크립트로 DOM에 직접 접근이 가능한 것을 활용해서 유저스크립트를 통해 웹 브라우징 자동화도 할 수 있습니다.

UI를 수정하는 예제 : just-news

적용 이전적용 이후
1_left1_right

<그림1> ‘just-news’ 유저 스크립트 프로젝트

just-news’는 국내 오픈소스 커뮤니티에서 가장 많은 기여자를 보유한 유저 스크립트 프로젝트입니다. (저도 기여했어요!) 국내 인터넷 뉴스 사이트에서 광고 같은 불필요한 정보를 제거하고 기사 본문으로만 이뤄진 페이지로 재구성합니다. 페이지 로딩이 덜 돼도, 기사 전문을 다 읽어 들이면 전용 리더 뷰로 대체하는 강력한 본문 파서를 가진 것이 특징입니다.

반복하는 입력을 한번만 수행하기 : 카카오페이 PC 결제

QR코드로 결제카톡 메세지로 결제
2_left1_right

<그림2> 데스크톱 카카오페이 결제 시스템

카카오페이 결제를 데스크톱에서 이용하려면 아래 4단계 절차를 매번 거쳐야 합니다.

  1. QR코드를 스캔하거나 탭을 전환해, 전화번호와 생년월일 기재를 유도한다.
  2. 카카오톡 QR 스캔 기능으로 카카오페이 QR 코드 인식이 안되어 사용자가 당황한다1
  3. QR 코드 리더 앱을 통해(안드로이드 사용자는 별도의 앱 설치 시간이 소요된다) 1~2초간 기다려 URL 정보를 얻는다. 혹은 상단 오른쪽 탭으로 전환해 전화번호와 생년월일을 입력하고, 카카오톡 메시지로 링크를 받는다.
  4. 결제 비밀번호나 지문 인식을 통해 결제를 마무리한다.

안드로이드 사용자는 QR 코드 스캔을 다른 앱으로 해야 하는 것에 불편함을 느낄 법 하고, 전화번호와 생년월일을 매번 입력하는 대안책도 번거로워 보였습니다

다행히 해당 웹 서비스는 SPA로 만들어져 있었습니다. 숨겨진 입력 폼 엘리먼트 값을 <코드1> 유저스크립트로 채우면 번거롭게 입력하는 일을 더는 하지 않아도 됩니다.

// ==UserScript==
// @name   kakao-pg
// @version 1
// @match https://pg-web.kakao.com/v1/*/info
// @match https://pg-web.kakao.com/v1/*/info#none
// ==/UserScript==

window.onload = () => {
  document.querySelector('#userPhone').value = '0101234567'
  document.querySelector('#userBirth').value = 840301
  document.querySelector('.btn_payask').click()
}

<코드1> kakao-pg.user.js

<코드1>을 통해 팝업 폼에 아무런 정보를 직접 입력하지 않아도 카카오톡으로 결제할 내역을 보내는 모습

<코드1>을 통해 팝업 폼에 아무런 정보를 직접 입력하지 않아도 카카오톡으로 결제할 내역을 보내는 모습

제주대 로그인 개선

저는 제주대학교 학생으로 하영드리미라는 학적 관리 서비스, 이러닝 웹 사이트 이 두 교내 웹 서비스를 사용하고 있습니다. 사용성에 큰 불편함을 느끼고 있었는데 마치 정부/공기관의 웹 서비스처럼 UI가 덜 직관적이라 그렇게 느껴졌습니다.

하영드리미는 교내 공용 컴퓨터에서도 접속할 수 있어, 시간제한을 두고자 세션 인증 방식을 쓰고 있습니다. 세션 인증 방식은 접속 시간에 제한을 두어 일정 시간 응답이 없으면 세션을 끊도록 설정하는 방식으로 잠시 다른 탭을 보다가 돌아오면 로그인이 풀려 다시 학번과 비밀번호를 수기로 입력해야 했는데, 저는 개인 컴퓨터를 사용하고 있어 불편함을 크게 느꼈습니다.

<그림3> 하영드리미 세션 만료

<그림3> 하영드리미 세션 만료

하영드리미의 로그인 페이지는 /frame/index.do라는 라우터를 사용하고, 메인 페이지는 /frame/main.do 라는 라우터를 사용하고 있습니다. 저는 세션이 만료돼 /frame/index.do 페이지로 리디렉션Redirection될 때, 리디렉션된 로그인 페이지의 전송 버튼을 클릭하는 <코드 2>를 작성했습니다.

// ==UserScript==
// @name   dreamy
// @match https://dreamy.jejunu.ac.kr/frame/index.do*
// ==/UserScript==
window.onload = () => {
  if (document.getElementsByName('frmLogin').length) {
    document.querySelector('#userid').value = 1234567890
    document.querySelector('#password').value = 'password'
    document.querySelector('#act_lgn').click()
  }
}

<코드2> dreamy.user.js

<코드2>을 통해 갑자기 로그인 페이지로 이동하면 로그인 폼을 채워주고 전송 버튼을 대신 눌러준다.

가벼운 웹 서비스 코드 패치 : 온라인 강의 접속 개선하기

제주대학교 학생은 이러닝 영상 콘텐츠를 수강하려면 HTTPS를 벗어나서 일부러 HTTP 프로토콜 주소를 통해 접속해야 했습니다. 왜냐하면 모던 브라우저는 HTTPS 위에 HTTP 콘텐츠가 섞인 브라우징을 허용하지 않기 때문에 HTTP로 서빙되고 있는 영상 콘텐츠가 차단이 되어 볼 수 없기 때문입니다.

<그림4> Mixed active content 차단 보안 정책으로 차단된 임베딩 콘텐츠

<그림4> Mixed active content 차단 보안 정책으로 차단된 임베딩 콘텐츠

그렇지만 저는 강의보다 출석 기능을 활용하려고 이러닝 사이트에 HTTPS로 접속하는 빈도가 높았습니다. 간혹 수강해야 하는 온라인 강의를 들을 때마다 평소 사용하던 HTTPS에서 ‘S’를 직접 빼내야 해서 번거롭게 느껴졌습니다. 이런 수고를 줄이기 위해, 차단되는 비디오 소스를 새 창을 열어 보여주는 유저 스크립트를 <코드3>과 같이 작성했습니다.

const regex = RegExp('^http://common.jejunu.ac.kr/em/[a-zA-Z0-9]*$')
const frame = document.querySelector('iframe#bodyFrame')

const INTERVAL = 100
const trigger = setInterval(async () => {
  if (regex.test(frame.src)) {
    open(
      frame.src,
      '_blank',
      'width=' + window.innerWidth + ', height=' + window.innerHeight
    )
    clearInterval(trigger)
  }
}, INTERVAL)

<코드3> elearning.user.js

<그림5> 비보안 임베딩 콘텐츠를 <코드3>의 도움을 받아 새 창에서 연 모습

<그림5> 비보안 임베딩 콘텐츠를 <코드3>의 도움을 받아 새 창에서 연 모습

정규식으로 캡처한 common.jejunu.ac.kr/em/\* 패턴이 iframe#body 선택자의 src 값과 일치하면 새 창으로 열게 작성했습니다. 동기적인 흐름으로는 src 값 캡처가 안 되서 비동기 구문을 사용했습니다. 다른 학생도 같은 문제를 겪고 있을 것 같아 확장 기능으로 만들어 교내 커뮤니티에 공유했습니다.2

유저 스크립트 저장소

지금까지 소개한 예시처럼 직접 프로그래밍을 할 수도 있지만 다른 사용자가 이미 만들어둔 유저스크립트를 위 목록에서 찾을 수 있습니다.

마무리

2019년 12월 1일, 평가원 사이트의 허점으로 수험생 312명의 수능 성적표가 예상보다 일찍 공개되었다. 그리고 2주가 채 지나지 않아 소스 보기 기능을 차단한 웹 브라우저를 국내 기업에서 개발한다는 소식을 듣게 되었다. (프로그래머의 실수를 보이지 않게 하기 위해서라고…?) 나는 차의 보닛을 용접하고 출고하는 것과 같은 발상이라 생각해서 납득하기 어려웠다.

저는 웹 서비스의 사용성을 방치하는 것은 미리 예방할 수 있는 일을 숨기는 것과 비슷하다고 생각합니다. 하지만 일회성 외주처럼 더 손을 쓸 수가 없는 여러 사업적인 배경이 있을 수 있기에 무조건 비평하는 것은 올바르지 않다고 직업으로 프로그래밍을 경험하면서 느끼고 있는 중입니다.

제가 느낀 사용성에 대한 아쉬움이 유저스크립트를 접하였고, 또한 이 주제로 글을 쓰게 된 계기가 되었습니다. 앞으로도 저는 유저 스크립트의 도움을 받아 웹 서비스를 사용할 생각입니다.

2022년 2월 수정

마이크로소프트웨어 표지마이크로소프트웨어 잡지에 기고한 원래 자료 - 첫 두 페이지마이크로소프트웨어 잡지에 기고한 원래 자료 - 다음 페이지

이 글은 자동화 특집을 다룬 마이크로소프트웨어 399호에 “유저스크립트로 학교 생활 속 불편함 줄이기"라는 제목으로 기고한 내용 중 일부입니다. 내용 중에 사이드 프로젝트 이야기가 있는데 주제에 벗어난다는 느낌을 받아서, 이번에 유저스크립트에 대한 소개와 예시 코드를 중심으로 다시 글을 다듬었습니다.

잡지에 기고하고 얼마 지나지 않아 비슷한 내용으로 “실용적인 웹 프로그래밍”이라는 무료 강의를 인프런에 올리게 되었는데, 이미 본문에서 소개한 카카오페이 자동화를 직접 실습해보는 과정을 영상으로 남겼습니다. 혹시나 더 친절한 설명을 듣고 싶다면 해당 커리큘럼을 참고 바랍니다.


  1. 마소 399호가 발행된 2020년 2월까지만 해도 카카오페이 QA 코드 인식을 지원하지 않았습니다. 현재는 카카오앱으로 카카오페이 QR 스캔이 가능한 것으로 확인했습니다. ↩︎

  2. 크롬 웹 스토어 링크. 이게 일반 사용자를 대상으로 한 내 첫 배포 경험이었다. 😊  ↩︎