Web/JS

[JS] Chrome Extension 제작 - 유데미 한글 자막, Udemy 한영 동시 자막 보기

메바동 2021. 5. 25. 22:28
728x90

무려 20일 전

 

개발자가 되고 싶은 메바동은 5월 6일 기초를 다지겠다고 Udemy에서 강의를 구매하였고, 20일 정도가 지난 지금 강의를 단 1개도 시청하지 않았다.

 

정말 대단해! 초심을 잃지 않는구만!!

 

물론 공부를 하기 싫은 마음도 있었지만 정말 큰 문제는 그게 아니었다. 정말 정말 공부를 해서 기초를 다지고 싶었고 어서 빨리 심화 과정으로 넘어가 프로젝트도 진행하고 싶었고 개발자다운 모습을 갖추고 싶었다.

 

정말 큰 문제는...

 

그렇다. 영문을 모르기 때문이다.

 

영어를 모르겠다.

어린 시절 시골에서 자랐던 메바동은 초등학생 시절 영어의 중요성을 느끼지 못하였다. 영어 시간은 단지 외계인이 나오는 프로그램을 보면서 노래를 따라 부르는 시간이었을 뿐. 그렇게 시간이 흘러 중학교에 올라가고 기초가 없던 나는 영어의 중요성을 알지만 아무것도 모르는 상태가 되었고, 아무것도 모르니 흥미가 생기지 않게 되고 그렇게 영어를 포기한 채 현재에 이르게 되었다.

 

 

강의는 구입했고, 공부는 하고 싶고, 영어는 모르겠고...

 

그래도 공부는 강의는 들어야 하니 구글에 '유데미 한글자막'을 검색하였고, 어떤 고마운 사람이 짠 코드인지 모르겠지만

 

if(typeof window.i!=='undefined'){clearInterval(window.i)} else{let lastText='';
function check(){let toEl=$('.well--container--2edq4 span');
let fromEl=$('p[data-purpose="transcript-cue-active"] span');
let currentText=fromEl.html();
if(lastText!==currentText){toEl.html(currentText)}lastText=fromEl.html()}window.i=setInterval(check,200)}

 

위 코드를 발견하게 되었다!

 

강의를 들을 수 있게 되었어!!

 

크롬의 번역 기능을 이용하여 페이지 번역을 한 다음 개발자 도구 콘솔에 저 코드를 붙여 넣으면 오른쪽의 번역된 대본 내용을 화면에 띄워주는 코드였다.

 

하지만 강의를 들을 때마다 저 코드를 붙여 넣기 하기도 귀찮고, 번역기의 성능이 완벽한 것은 아니기 때문에 나는 이런 기능을 하는 확장 프로그램이 있으면 좋겠다는 생각을 하였고...

 

생각만 하다가 시간이 흘러갔다.

 

더 적극적으로 아무것도 안하기 며칠

 

그래도 생각한 건 만들어 봐야지 라고 생각하고 만들기에 돌입하였다.

 

사실 내용은 간단했다. 그냥 화면에 버튼 하나 추가해 주고 해당 버튼을 누르면 페이지를 번역한 후 화면에 자막란을 하나 더 추가한 후 그곳에 번역된 텍스트를 넣어주면 되는 일이었다.

 

저 부분에 버튼을 추가하자

 

자연스러운 게 좋기 때문에 컨트롤 바에 아이콘을 추가해서 해당 아이콘을 누르면 번역이 되게 만들기로 하였다.

저 컨트롤 바는 DOM 로드가 끝난 후에 불러와지는 항목이기 때문에 컨트롤 바가 생긴 이후에 아이콘을 넣을 수 있도록 만들어야 했다.

 

이 부분은 예전에 포스팅한 mutation observer가 아주 유용하다. 때문에 스크립트 실행 시점을 document_end로 지정해주고

 

(() => {
  let bodyTarget = document.querySelector("body");

  let observer = new MutationObserver(() => {
    if(document.querySelector('.control-bar--control-bar--MweER') !== null) {
      let htmlText = '<button name="translate-btn" tabindex="0" type="button" class="control-bar-button--button--20ibv btn btn-text">' +
                    '  <img src="' + chrome.runtime.getURL('images/menu_icon.png') + '" />' +
                    '</button>' +
                    '<div class="sr-only" id="popper13">한글 번역</div>';
      document.querySelector('.control-bar--control-bar--MweER').insertAdjacentHTML('beforeend', htmlText);

      document.querySelector('[name="translate-btn"]').addEventListener('click', subtitleTranslate);

      observer.disconnect();
    }
  });

  let config = {
    attributes: true,
    childList: true,
    CharacterData: true,
  };

  observer.observe(bodyTarget, config);
})();

 

body에 변화가 있으면 컨트롤 바가 있는지 검사한 후 아이콘을 넣어주도록 하였다.

 

아이콘이 정상적으로 생성이 된다.

 

이런 걸 만들면서 느낀 건데 디자이너의 필요성이 절실한 것 같다. 그래도 나름 열심히 꾸며서 넣어줬다...

 

너무 이상해요

이제 다음으로는 대본을 번역하는 기능을 넣어주면 된다.

그전에 유데미에서 두 가지 조건을 충족해야 하는데

 

 

다음과 같이 자막을 하단 영역에 표시되게 하여야 하고, 우측에는 대본이 띄어져 있어야 한다.

우선 자막이 하단 영역에 표시되어야 하는 이유는, 그냥 보기 편하기 때문에....

사실 저렇게 되어 있어야 한글 자막을 넣어주기가 편했다. 그냥 그 이유뿐. 만약 이 확장 프로그램을 사용하는 사람 중에 하단 자막 말고 화면에 표시하고 싶어요!라고 요구하는 사람이 있다면 수정할 의향이 있다.

오른쪽에 대본이 표시되어야 하는 이유는 위에서 본 코드가 바로 번역된 이 대본에서 현재 부분을 가져와 화면에 표시해주기 때문이다.

 

if (document.querySelector('.well--container--2edq4') === null) {
  document.querySelector('#captions-menu').click();
  document.querySelector('[data-purpose="go-to-settings"]').click();
  document.querySelector('.menu--well-setting--2lWNm > .toggle-control-label').click();
  document.querySelector('.well--container--2edq4').click();
}

if (document.querySelector('.transcript--transcript-panel--kfMxM') === null) {
  document.querySelector('[data-purpose="transcript-toggle"]').click();
}

 

그래서 이렇게 해당 부분들이 없다면 띄어주도록 설정하였다. 저렇게 클릭 이벤트로 표시하게 한 이유는 유데미의 코드가 난독화가 되어 있고, 크롬 확장 프로그램과 페이지의 스크립트는 서로 독립적인 환경에 존재하기 때문에 클릭 이벤트를 사용하여 나타나게 해 주었다.

 

물론 잘하는 개발자는 어떻게 쓸 수 있는 방법이 있겠지?

 

잘하고 숙련된 개발자라면 어떻게 깔끔하게 이용하는 방법이 있을 테지만, 나는 모른다.

계속해서 성장하다 보면 언젠간 나도 잘하게 되겠지 그때까지 열심히 해야겠다.

 

아무튼 이렇게 아이콘을 넣고 해당 아이콘을 클릭하면 필요한 화면으로 만드는 부분까지 완성을 했는데 예상치 못한 난관에 부딪히게 되었다.

 

바로 크롬 확장 프로그램에서 크롬의 페이지 번역 기능을 이용하는 방법이 없던 것이다...

 

대체 왜!? 크롬이고 크롬이잖아!!

 

인간적으로 chrome 확장 프로그램이면 chrome의 기본 기능을 이용할 수 있게 해줘야 하는 거 아닌가?? 대체 왜 못하는 걸까??

되지도 않는 영어 실력으로 우리의 구세주 스택오버플로우도 들락날락거려보고, 당연히 크롬 확장 문서도 여러 번 살펴봤다.

 

내가 영어를 못하는 건지... 진짜 크롬에서 지원을 안 하는 건지 꼬박 하루를 해당 기능을 찾는데 날려먹었다.

 

그러다가 그래도 DOM을 수정하는 기능인데 해당 버튼을 눌렀을 때 script 이벤트가 발생하지 않을까?라는 생각으로 개발자 도구에서 스크립트가 발생 시 break point가 걸리도록 해놓고 번역 기능을 눌렀는데!!

 

짜잔!!
할렐루야~~~

 

역시나 스크립트를 이용하는 부분이 있었다! 사진에서는 translateApiKey를 혹시 몰라 가렸는데 이 부분은 chrome에서 번역 기능을 이용하면 모두 똑같은 키값을 가지고 있다.

써도 될까 싶어 노트북, 가상 머신, 집에 있는 데스크톱, 회사 컴퓨터에서 break point를 걸어 확인해 보았더니 모두 같은 값이었고, 검색도 해보니 약 5년 전에도 이 키를 이용해서 뭔가를 하는 사람들이 많았다.

또한 저 코드 자체도 크로미움의 license를 따르고 있기 때문에 BSD 라이센스로 문제 될 부분은 없어 보였다.

 

그래서 그냥 저 코드를 그대로 복사해서 google_translate.js 파일을 만들어 붙여 넣었다. 물론 저 fetchStart와 fetchEnd 값은 해당 이벤트가 발생했을 때 시간을 가져와 넣도록 바꿔주었다.

 

근데 이 코드를 이용하는데 문제가 발생해 버렸다...

 

대체 왜...

 

나는 지난번 '한국인 있나요?'는 manifest 버전 2로 만들었기 때문에 최신 버전인 manifest 버전 3으로 이번 확장을 만들고 싶었었고, 최신 버전이니 보안으로 인해 제한되는 부분도 늘어났다.

 

두둥!

 

덕분에 크롬 번역 스크립트에서 eval()을 사용하는 부분이 문제가 되었다.

해당 기능을 사용하기 위해서는 샌드박스나 서비스 워커에서 사용하는 방법밖에 없었는데 역시나 나의 미숙으로 인해 독립된 환경에서 크롬 번역 스크립트를 실행하는 방법을 찾지 못하였다.

 

내가 그렇지 뭐...

 

때문에 방법을 찾지 못하고 결국 manifest 버전을 2로 사용하는 방법을 택하였다.

내가 꼭 열심히 공부해서 이런 문제쯤은 아무렇지 않게 해결할 수 있도록 할 것이다. 분명 방법이 있는데 내 미숙함으로 인해 찾지 못했을 것이다. 혹시 방법을 아는 사람이 있다면 도움을 주면 좋겠다 😁

 

if (typeof window.isTranslate !== 'undefined') {
  cr.googleTranslate.revert();
  document.querySelector('.koreanSubtitle').remove();
  clearInterval(window.isTranslate);
  window.isTranslate = undefined;
} else {
  cr.googleTranslate.translate('en', 'ko');
  let lastText = '';

  let koreanSubtitle = document.createElement('span');
  koreanSubtitle.className = 'koreanSubtitle';
  koreanSubtitle.style.cssText = 'text-align: center; color: rgb(255, 255, 255); margin-top: -3rem;';
  document.querySelector('.video-player--container--YDQRW').append(koreanSubtitle);

  function check() {
    try {
      let engEl = document.querySelector('.well--container--2edq4 span');
      let fromEl = document.querySelectorAll('p[data-purpose="transcript-cue-active"] span');
      fromEl = fromEl[fromEl.length - 1];
      let korEl = document.querySelector('.koreanSubtitle');
      document.querySelector('.koreanSubtitle').style.fontSize = document.querySelector('.well--container--2edq4').style.fontSize;
      
      if (fromEl) {
        let currentText = fromEl.textContent;
  
        if (lastText !== currentText) {
          korEl.textContent = currentText;
        } lastText = fromEl.textContent;
      }
    } catch (e) {
      clearInterval(window.isTranslate);
    }
  }

  window.isTranslate = setInterval(check, 200);
}

 

그래서 해당 기능을 이렇게 구현하고 지난 포스팅에 올렸던 것처럼 웹 스토어에서 승인을 받았다!

 

 

별거 아닌 수준이지만 이렇게 공개가 되면 너무 기쁘다

 

 

하지만 당시 포스팅에 올렸던 것처럼 영어 자막과 한글 자막 사이의 간격이 너무 넓었고, 또 다음 강의로 넘어갔을 때마다 새로고침을 해주어야 하는 문제점이 있었다.

 

우선 간격은 그냥 스타일만 조절하면 되는 거라 금방 수정할 수 있었다.

문제는 다음 강의로 넘어갈 때마다 새로고침을 해주어야 하는 부분이었는데 생각해보니 나는 mutation observer를 사용하고 있었다!

아이콘을 넣어주면 mutation observer의 감시 기능을 꺼버렸는데 해당 기능을 그냥 계속 유지시키면 문제가 없는 부분이었다.

 

let href = document.location.href;

let observer = new MutationObserver(() => {
  if(document.querySelector('.control-bar--control-bar--MweER') !== null && !document.querySelector('[name="translate-btn"]')) {
    let htmlText = '<button name="translate-btn" tabindex="0" type="button" class="control-bar-button--button--20ibv btn btn-text">' +
                  '  <img src="' + chrome.runtime.getURL('images/menu_icon.png') + '" />' +
                  '</button>' +
                  '<div class="sr-only" id="popper13">한글 번역</div>';
    document.querySelector('.control-bar--control-bar--MweER').insertAdjacentHTML('beforeend', htmlText);

    document.querySelector('[name="translate-btn"]').addEventListener('click', subtitleTranslate);
  }
  
  if (href !== document.location.href) {
    href = document.location.href;
    clearTranslate();
  }
});

 

그래서 다음과 같이 url을 저장한 다음 body 부분에 변경이 있을 때마다 url을 검사해 url이 변경되었으면 다시 아이콘을 추가해주도록 바꿔 주었다. 아이콘 추가하는 if 문도 이전과 같은 조건을 경우 DOM에 변경이 있을 때마다 아이콘을 추가하게 되기 때문에 해당 아이콘이 생성되어있지 않을 경우의 조건도 추가해 주었다.

 

그리고 아이콘도 수정해 주었는데... 이렇게 보니까 이전 아이콘이 더 나은 것 같기도 하고...

 

아무튼 그렇게 해서

 

 

이렇게 간격도 마음에 들게 수정하였고, 페이지를 이동했을 때도 버튼이 생기도록 만들었다.

 

별거 아닌걸 만들었어도 너무 만족스럽다.

 

이렇게 수정한 것을 어제 크롬 웹 스토어에 업데이트하였고

 

게시 되었다!!

 

오늘 공개가 되었다!!

 

너무 신난다

 

 

유데미 강의를 한글 자막 혹은 한영 동시 자막으로 보고 싶었던 분은 크롬 확장 프로그램을 이용하시면 크롬 번역 기능을 이용해 번역된 자막을 보실 수 있습니다. 

제가 만든 확장 프로그램을 이용해 보고 싶으신 분은 크롬 웹 스토어에서 '유데미' 혹은 '유데미 한글 자막'을 검색하시면 됩니다.

728x90