네이버 사다리와 함께 했던 워크숍 (2)
취미로 하는 개발

네이버 사다리와 함께 했던 워크숍 (2)

지난 1편에 이어 계속 진행...!

 

https://nookpi.tistory.com/197

 

본격적으로 사다리게임 핵심 로직이 들어있는 js 파일을 분석해 보자.

https://ssl.pstatic.net/sstatic/fe/sfe/ladder-game/ladders_230912.js

 

내가 개인적으로 minify 로직을 통해 난독화된 코드를 볼 때 염두에 두는 부분은 다음과 같다.

  • 난독화 된 코드는 기본적으로 읽고 해석하기 어렵기 때문에, 상수와 같이 바꿀 수 없는 지점을 찾는 게 우선이다.
  • IDE의 도움을 받아 코드의 형태를 정리하는 것은 큰 도움이 된다.
  • 어떤 역할을 하는 변수/함수인지 유추되었다면, 이름을 바꿔두는 것이 좋다.
  • class 혹은 prototype 메서드의 이름은 난독화 대상에서 빠지는 경우가 많아, 메소드 명을 참고하는 것이 도움이 된다.

코드를 복사해서 IDE에 넣고 줄 바꿈을 해보니 7000줄이 넘는 코드가 나온다.

겁먹지 말고 상수부터 찾아보자. 우리가 알 수 있는 상수는 뭐가 있을까? 우선 1편에서 확인했듯, 모듈의 동작 방식은 특정 id를 가진 캔버스를 찾아 렌더링을 하는 것으로 유추된다.

 

그렇다면 캔버스의 아이디를 먼저 찾아보자.

    var t = (window.LadderGame = function () {
        (o = document.getElementById('ladders_canvas')),
          (nhn.search.ladders.images = nhn.search.ladders.images || {}),
          (nhn.search.ladders.ss = nhn.search.ladders.ss || {}),
          this.handleComplete();
      }),

 

'laddeers_canvas'로 찾은 캔버스 객체는 o라는 변수에 할당되고 있다.

o의 이름을 canvasElement로 바꾸고 사용하는 곳을 찾아보자.

 

canvasElement를 사용하는 코드들을 보니 익숙한 네이밍의 함수들이 보이는데? 살짝 함수들을 접어서 네이밍을 살펴보자.

아주 직관적이다

네이밍이 이렇게 중요하다. C는 유저의 클릭 이벤트를 받고 사다리를 실질적으로 그리는 등, 코어 로직을 담고 있는 것으로 보인다.

내 이목을 끄는 부분은 사다리를 실질적으로 그리는 drawladder 함수였다. 카멜 케이스가 아닌 부분은 오타인 것 같다.

 

사다리를 만들 때 내가 원하는 대로 만들 수 있으면 그다음 로직은 굳이 건드릴 필요도 없다.

사다리 시작시 빈 텍스트가 없으면 사다리를 그린다

makeLoadder? 이것도 makeLadder의 오타인가? 아무래도 사람이 하는 일이다 보니 오타가 없을 수 없다. 일단 눈에 거슬리니 함수 이름을 makeLadder로 바꿔주고 내부 로직을 보자.

 

제대로 찾은 것 같다! 그런데 여기서 사다리 결과를 어떻게 확인하지...?

위에서 찾은 메서드 중 handleViewResultClick을 확인해 보자.

handlerViewResultClick: function (t) {
  d(0, a), (b = !0), I && I.remove(), (I = null);
  const e = u.ladderItems.length;
  T = [];
  for (let i = 0; i < e; i++) T.push(u.ladderItems[i].itemLineNum);
  u && (u.remove(), u.destroy(), (u = null)), (c = new k());
}

 

좋아... 딱 보니 모르겠다...

그래도 중요한 힌트가 몇 가지 있는 것 같은데, 일단 결과를 보여주는 페이지로 이동하는 버튼이니 만큼 cleanup 로직들이 섞여있는 것이 보이고 T = []에 결과를 넣는 부분이 눈에 띈다.

 

사다리의 줄 개수만큼 반복문을 돌면서 결과를 넣어주는 것 같다.

그렇다면 ladderItems 내부에 결과가 있을 가능성이 높다. 디버거로 테스트를 해보자.

 

일단 몇 번째 줄에 해당하는지 보이고

itemTargetText.text 에는 사다리 아래쪽 텍스트가 보이고, nameTargetText.text에는 사다리 위쪽의 텍스트가 보인다.

실제 사다리 결과와 동일하다

이제 laddersItems에 결과를 넣어주는 부분만 찾으면 된다!

해당 코드는 아까 봤던 drawladder 메서드 안에 위치해 있는데, 전체 코드는 다음과 같다.

 

사다리 게임이 어떻게 동작하는지 핵심 로직에 대해 파악했으니 이제 수정 방법도 간단하다.

const success = this.ladderItems.some(item => {
  const name = item.nameTargetText.text;
  const target = item.itemTargetText.text;
  return name === "목표 이름" && target === "목표 키워드";
});

// 목표 이름이 목표 키워드에 할당되는 사다리 조합이 나올때까지 실행

if (!success) {
  this.drawladder();
  return;
}

 

좋아! 다 좋은데... 이걸 어떻게 티가 안 나게 적용하지?

사다리 게임을 하자고 네이버를 켜서 소스 탭에서 끄적끄적 수정할 수는 없는 노릇이다.

 

다음 편에서 계속.