네이버 채용 결과 확인 매크로 만들기

shinychan95·2021년 7월 22일
1
post-thumbnail

위 사진은 chrome extension의 아이콘으로 사용한 이미지이다.

 

토이 프로젝트 목적

네이버 신입공채 결과 확인을 위해 개인 정보를 매번 입력하기 귀찮다. 매크로를 만들자.

 

매크로로 만들고 싶은 동작

  1. 네이버 채용 홈페이지 접속
    • (팝업창 뜨는 경우 닫아야 한다)
  2. 오른쪽 상단 내 지원서 버튼 클릭
  3. 이름, 생년월일, 이메일, 비밀번호 입력
  4. 조회하기 버튼 클릭
  5. 리스트 중 첫번째 네이버 신입 공채: 기술 직군 옆 동그란 버튼 체크
    • (클릭하면 아래 결과확인 버튼이 생긴다)
  6. 결과확인 버튼 클릭

 

위 과정을 살펴보니 마우스의 이동이 필요한 것도 있고,
API 통신을 통해 결과를 받아 다음 페이지로 넘어가야 하는 것도 있고,
팝업창이 뜨는지 안뜨는지 조건에 따라 창을 닫기도 해야 하고,
웹 페이지 내 동적으로 버튼이 생성되기도 한다.

 

🔥 아? 결과를 요청하는 API 통신만 보내면 되지 않을까? 🔥

 

네트워크 기반 매크로 기획 과정

  1. 어떤 식으로 구현하면 좋을까? 키보드 및 마우스 동작을 순서대로 저장하여 매크로를 만들까?
  2. 키보드 및 마우스 인터럽트 데이터를 프로그램이 가져와 저장할 수 있을까? 마치 프로그램을 실행하면 키보드를 해킹해서 원격으로 사용하는 것처럼?
  3. Transport layer에 데이터를 요청할만한 API가 있나. (찾아보다 실패)
  4. 어차피 chrome을 통해 네트워크 송수신을 하니 application layer 상에서 처리하여 가볍게 만들어보자. chrome extension을 사용하자!
  5. chrome extension에서 지원하는 API 중에 request에 관련된 것이... devtools.network? webRequest?
  6. devtools.network로 할 수 있는지 살펴보다가 이 API는 단순히 request 데이터만을 가져오는 것이 아닌, devtools 내 새로운 window를 만들고, 여러 component 사이의 네트워크 요청이라는 것을 알게 됨. (삽질)
  7. 🔥결국 webRequest를 사용🔥

 

chrome.webRequest

chrome.webRequest docs link

  • 간단하게 말하면, request가 위와 같은 life cycle을 거치는데, 각 단계마다 listener를 통해 작업을 추가할 수 있다.

 

매크로에 저장할 네트워크 요청

보편적으로 사용할 수 있도록, 모든 네트워크 동작 과정을 기억하도록 만들고 싶었지만, 페이지마다 너무 다양하여 우선 xmlhttprequest만 처리하도록 필터를 추가하였다.

  1. 메인 페이지 로드
  2. 내 지원서 페이지 로드
  3. 조회하기 버튼 클릭
  4. 확인하고자 하는 지원서 클릭 후 결과 확인

 

살펴보니, Get 요청의 경우, 그저 페이지 로드 및 session id만 업데이트하므로 매크로로 저장할 필요가 없다.

 

결론적으로 xmlhttprequest만을 매크로에 저장하기로 하였다.

(파헤쳐보니, 원래 어떤 요청인지 정확하게 파악하려면 request 및 response를 묶어 request의 method, body, header 그리고 response의 header 내 Content-type까지 포함하여 종합적으로 판단해야 할 것이다.)

 

본론 그리고 모든 작업 과정 정리

  • 지원서 결과 확인을 위해 매크로를 만들고자 했다.

    • 시작 지점부터 끝 지점까지 XMLHttpRequest 및 쿠키들을 저장하려고 시도
    • 단순 document request는 인증을 위한 쿠키나 그런 것들이 없기 때문에 생략
  • chrome.webRequest의 life cycle에 따라, 각 부분에 listener 설정

    • onBeforeRequest에서 Request Body에 대한 내용 추적
    • onSendHeaders에서 Request Header에 대한 내용 추적
    • onResponseStarted에서 Response에 대한 내용 추적
  • 필요한 내용들은 chrome.storage.sync를 통해 저장

  • 🔥문제 발생 - requseBody 내 ArrayBuffer🔥

    • 결과 반환에 대한 Request의 body 부분이 json serialize가 되지 않아, 저장 불가
    • 아래와 같이 내부 ArrayBuffer 형태로 되어 있다.
  • 문제 해결을 위해 ArrayBuffer를 String으로 변환하여 저장하고, 해당 포맷을 가진 request body의 경우 매크로 실행 시 다시 ArrayBuffer로 변환하도록 설정

  • 🔥문제 발생 - 똑같은 format 요청인데 오류🔥

    • 오류가 발생한다는 결과 반환.
    • ArrayBuffer → String → ArrayBuffer 변환 과정에서 오류가 있는지 체크해보았다.
    • 변환 과정에서 String.fromCharCode 을 사용하는데, 혹시 이 메소드가 UTF-16 코드 유닛의 시퀀스로부터 문자열을 생성해 반환하는 메소드라서 오류가 난 건 아닐까 생각이 들어, 1바이트 기준의 변환이 있는지 확인했지만, 결론적으로 내부 모든 바이트의 값이 같음.
    • [[Int8Array]] 모든 값들은 똑같은데, 위 사진에서 [[ArrayBufferData]] 값이 달라서 현실적으로 불가능한걸까. 잠시 포기.
  • 혹시나 하는 마음에 chrome DevTools로 수작업으로 로그인 시 받은 application key 관련 쿠키 및 session id 쿠키를 지우고, 결과 반환 request를 동작시켜보았더니 정상적으로 결과를 받아온다.

  • 또 혹시나 하는 마음에 postman으로 똑같이 쿠키를 지우고, requestBody가 아닌 params에 값들을 추가하여 요청을 보냈더니 정상적으로 결과가 반환됨.

  • 🔥결론적으로 - body에 데이터 담기 vs param에 데이터 담기🔥

    • requestBody에 데이터를 넣어 요청하는 경우, chrome.webRequest.onBeforeRequest.addListener 의 details 객체에 requestBody 내에 아래 사진과 같이 데이터가 담기게 된다.

    • 하지만, params에 데이터를 담아 요청하는 경우, chrome.webRequest.onBeforeRequest.addListener 의 details 객체에 requestBody 내에 아래 사진과 같이 데이터가 담기게 된다.

  • 즉, requestBody에 대한 parsing을 진행할 때, format을 보고 body에 담긴 데이터인지 param에 담긴 데이터인지 확인해야 한다. 또한 Fetch API의 경우 (최대한 찾아본 결과) params를 따로 지원하지 않고, URL에 담을 수 있는데, 또 URL에 담으면, chrome.webRequest.onBeforeRequest.addListener 의 details 객체에 requestBody 없이 url에 데이터가 담기게 된다.

 

만든 결과물 및 충격적인 사실

  • 첫번째 Background 아래 버튼은 getting started를 참고하며 추가한 배경 바꾸는 버튼이다.
  • 두번째 기록하고자 하는 네트워크 송수신의 시작 지점에서 Macro 아래 버튼을 킨 채 동작을 수행하고, 종료 지점에서 버튼을 끄면 된다.
  • Click 버튼의 경우, 기록된 매크로를 실행한다.
  • Check 버튼의 경우, 저장된 매크로 데이터를 console에 보여준다.

 

충격적인 사실

사실 이렇게 만들 필요가 없었다.

동작 과정 내 모든 xmlhttprequest들을 매크로로 저장하도록 만들었다. 왜냐하면, 인증으로 얻은 쿠키나 세션 등이 모두 필요할 것이라 생각했다.

하지만, 결론적으로 마지막 결과 확인 요청에서 params로 보내지는 데이터는 unique한 값이고, 이 요청을 보낼 때 application key나 session 데이터가 없어도 결과가 반환된다.

즉, 웹페이지 접속 및 로그인 관련 과정 없이 params unique한 값을 가진 채로 postman으로 요청 하나만 보내도 결과 확인 가능하다.

 

💻 Github Link

나를 힘들게 한 키워드,

  • devtools.network
  • ArrayBuffer, JSON serialize
  • DevTools Network 내 info VS webRequest details 내 info
    (type, body 및 데이터 간의 간극으로 인해 방향 수없이 수정)
profile
개발자로 일하는 김찬영입니다.

0개의 댓글