오늘은 LLM이 있기에 가능해진 일 중 하나를 얘기해보려 한다. 바로 리버스 엔지니어링이다. 범위를 더 좁혀 말하자면 llm을 사용해서 google scholar 크롬 익스텐션 코드를 리버스 엔지니어링한 경험을 공유해보고자 한다.

문자열을 몸으로 익히는 LLM

68 69 20 6D 79 20 6E 61 6D 65 20 69 73 20 6B 79 65 6F 6E 67 74 61 65 6B 20 6F 68

이걸 인간이 보면 한번에 이해하지는 못한다. 아마 ascii 코드를 달달 외우고 있는 변태같은 사람만 해독이 가능할 것이다. 근데 llm은 이걸 그냥 하는 것 같다. (도구를 쓰지 않고 추론 한번에)

image.png

어떻게 이런걸까? 학습 데이터 중에 byte 문자열이라도 있는걸까? 물론 있겠지. 근데 극히 일부분이고 저 byte로 일반 문자열이 적힌 걸 해석하는 훈련을 직접적으로 했다고 할 수 있나? openai 동영상 중에 않녑합셊욗 엾긳절댇갑집맋셊욦 이런 걸 gpt가 도구를 써서 해석하는 영상도 있었는데, 이 특성과 관련된 걸까? 한국인, 더 넓게는 인간의 지능은 어떤 특성 덕분에 이걸 한눈에 알 수 있는걸까? 한국인은 저게 되고 ai는 저걸 한눈에 모르는 이유가 뭘까? 답은 모른다. 현 시점에서 이 세상에 지능의 작동원리를 설명할 수 있는 사람이 누가 있을까.

개인적으로 llm의 정말 흥미로운 특성 중 하나라고 생각한다. (그래서 인간과는 전혀 다른 특성의 지능이라고 생각이 든다.) 내가 llm 엔지니어는 아니지만 텍스트를 인간처럼 단어 하나하나의 의미를 정말로 추상적인 의미에서 이해하고 있는 게 아니라 토큰과 토큰 사이의 관계 (weight)로 이해하기 때문이 아닐까?

얘는 문자/단어가 아니라 흐름을 이해하고 있는 것 같다. 우리가 유명한 곡의 멜로디를 다른 버전으로 들었을 때 금방 알아차리는 것처럼 말이다. llm은 그걸 텍스트로 하고 있는 것 같은 느낌이 든다.

아무튼 이게 중요한 건 아니고, 바로 이 코드를 봐보자. 구글 검색창을 켰을 때 개발자 도구 네트워크 탭에서 아무거나 골라서 본 파일 중 일부분이다.

Qma = function (a) {
  var b = b === void 0 ? !0 : b;
  var c = [];
  String(a).replace(Pma, function (d, e, f, g, h) {
    d = f || g || h || "";
    d = b ? _.ao(d) : d;
    c.push([e, d]);
    return " ";
  });
  return c;
};
_.Y = function (a) {
  var b = function (c) {
    c = c === void 0 ? _.FP : c;
    a(c);
  };
  b.Ji = function (c) {
    c = c === void 0 ? _.FP : c;
    a(c);
  };
  b.toString = function (c) {
    c = c === void 0 ? GP : c;
    return Rma(a, c);
  };
  b.Wc = b.toString;
  b.Na = _.PA;
  b.Zn = function () {
    return (0, _.XK)(b.Wc()).Zn();
  };
  b.Ph = function (c) {
    (0, _.fs)(c, function () {
      b.Ji(_.FP);
    });
  };
  b.Rb = function () {
    var c = document.createElement("div");
    (0, _.fs)(c, function () {
      b.Ji(_.FP);
    });
    return c.childNodes.length === 1 && c.childNodes[0] instanceof Element
      ? c.childNodes[0]
      : c;
  };
  b.Mi = !0;
  return b;
};

toString, childNodes 이런거 말고는 무슨 코드인지 전혀 모르겠다. gpt에게 물어보자.

 코드는 Google Closure 기반으로 난독화된 자바스크립트 코드이며, 다음과 같은 역할을 합니다:

...

🔍  코드의 용도 추정
동적 텍스트 파싱  디코딩 (Qma)

서버에서 받은 HTML이나 템플릿 데이터를 구조화

함수 래핑  다양한 표현/실행 방법 제공 (_.Y)

a() 함수를 감싸서, 다양한 방식으로 실행하거나 문자열화 가능

: HTML 렌더링, 이벤트 지연 실행, 즉시 실행 

🧠 결론
 코드는 난독화된 Google 코드의 일부로 추정되며,

Qma(): 문자열을 파싱하고 [e, d] 형태로 가공된 데이터 배열 생성

_.Y(): 전달된 함수를 다양한 방식으로 래핑하고 실행할  있게 해주는 함수 래퍼 유틸리티

필자는 구글에서 가져온 코드라고 말도 안했다. 정말 그럴듯하게 해석해 낸다. 사실 맞는지 안맞는지는 중요하지 않다. 바이트 문자열을 ‘몸으로 익히고 있는’ llm의 특성이 여기서도 비슷하게 동작한 걸까?

아무튼! 필자는 몇 달 전에 긱뉴스에서 llm이 이렇게 minified code를 정말 잘 해석해낸다는 글을 보았던 상태였다. (원 게시글을 찾아보려 했는데 못 찾겠다…)

리버스 엔지니어링

그러던 중 문라이트 개발하다가 논문 안에서 인용을 얻는 알고리즘 때문에 정말 골치가 아팠었다. pdf 특성상 정말 데이터가 어떻게 들어올지 모른다. 문자열이 문자열 이렇게 들어올 수도 있고, 이렇게 따로 들어올 수도 있고, 이렇게 들어올 수도 있다. (인용 형식이 다양하다는 것을 표현하기 위해 비유한 것이다)

ㅁㅈㅏㅇㅕ

   

문라이트는 이걸 해석하는 일을 잘 못했다. 논문 1페이지에 [1]번 인용이 있다고 하면 reference 섹션에서 [1]번 인용 문자열을 가져오지 못하고 [2]번이나 [3]번 인용을 가져오는 일이 많았다.

문라이트가 크롬 익스텐션이고, 구글 스칼라 또한 크롬 익스텐션이다. 근데 인용 파싱 면에서 구글 스칼라는 정말 차원이 달랐다. ㅋㅋㅋ 아니 어떻게 이러지? 출발선이 같은데… 똑같은 pdf에서 어떻게 이렇게 정확하게 파싱하지? 구글은 신이야 이랬었다.

그래서 구글 스칼라의 동작 원리를 파해쳐 보기로 했다. 코드를 그대로 베껴와서 문라이트에 붙이고 기능 출시하는 건 저작권 위반 + 크롬 웹스토어 이용약관 위반 및 이것저것 위반이지만, 내부적으로 어떻게 동작하는 지 보고 우리 코드로 다시 짜서 벤치마킹해오는 것이 목표였다. (물론 법적으로 허용되는 범위 내에서)

필자 스스로 너무 대단한 발견을 했다고 느끼지도 않고 너무 설레발 치는 것도 아니지만, 그래도 방법을 공개하면 악용될 여지가 있을 것 같아 자세한 방법은 공개하지 않겠다. 믿거나 말거나 필자는 구글 스칼라 익스텐션의 pdf 분석 핵심 로직 10000줄에 해당하는 내용을 6~70% 정도 해독하는 데 성공했다. 70%라는 말은 해당 로직이 너~무 복잡해서 이해가 안돼서 중간에 포기해서 그렇다. 코드 자체는 다 읽을 수 있을 정도로 바꿀 수 있었다.

결국 그 방식이 스케일이 너무 커서 문라이트에 당장 적용할 수 있는 방법은 없었고, 벤치마킹해서 적용하지는 못했다. 그치만 느낀 점이 있다면 이전에 필자에게 불가능했던 js 리버스 엔지니어링이 llm으로 가능해졌다는 것이다.

리버스 엔지니어링이 모두에게 불가능하다고 말하는 건 당연히 오만이라고 생각한다. 대충 80에서 100시간 걸렸던 것 같은데, 같은 시간이 있더라도 정말 천재들은 ai 없이도 저 10000줄을 쉽게 해독해낼 수도 있을 것 같다. 필자에게는 llm 없이는 불가능한 일이다. 물론 무한한 시간이 있다면 가능하겠지.

불가능한 일과 가능한 일

필자는 불가능과 가능의 범위를 일반적인 범위보다 좀 더 좁은 의미로 이해하고 사용하는 것 같다. ‘무한한 시간이 있다면 가능한 일’은 허상이라고 생각한다. 그런 식으로 생각하면 암호를 탈취하는 일도, 원숭이가 셰익스피어를 치는 일도 가능하다고 생각한다.

저 예시라면 당연히 불가능한거 아닌가 할 수 있겠지만, 시간 제약을 좀 더 둬서 100시간 안에 못하는 일이라고 하면 애매한 게 많다. 결국 본인의 자원으로 그 일을 할 수 없는 상태라면, 한정된 시간, 한정된 노력으로 못한다고 생각이 든다면 그건 불가능한 일이라고 판단해야 한다고 생각한다. (뭔가 이것도 문라이트 하면서 더 강하게 굳혀진 마인드긴 하다 ㅋㅋ)

이런 의미에서 js 리버스 엔지니어링은 필자에게는 정말 불가능한 행위였다. llm 없이 언제 그걸 다 뜯어보고 있나? 100줄의 코드의 흐름을 어떻게 이해한다고 한들 그게 10000줄짜리 코드에서 어떤 역할을 하고 있는지 어떻게 알아볼 수 있을까? llm은 난독화된 코드로부터, 자기가 학습한 전 세계 코드 중에 비슷한 패턴을 찾아줄 수 있는 이 세상에 존재하는 유일한 지능이기 때문에 이걸 하며 정말 시대가 변했구나 하는 생각이 새삼 들었다.

필자는 원래 ai 회의론자에 가까웠다. ai는 코딩 어느정도 잘하는 거 아는데 근데 뭐? 결국 컨텍스트를 전달하는 건 사람 몫이야. 컨텍스트를 들고 있는 사람이 제일 잘해. ai는 그거 아직 못해. 그러니까 개발자 10명을 1명으로 대체하게 할 수는 있어도 ai 하나가 사람 한명을 완전히 대체하지는 못해 이런 입장이었다. 사실 저 부분에 대해서는 지금도 비슷한 생각이기는 하지만, ai의 능력을 다른 관점에서 생각해 보게 되었다.

혹자는 이러한 llm의 능력에 대하여 의심하고 이 세상에 ai로 진짜 돈을 벌고 있는 비즈니스 모델이 없다하는 ai 회의론을 펼치지만, 필자는 뭔가 이번 이벤트로 ai 회의론자 입장에서 벗어났다고 해야 하나… 리버스 엔지니어링을 가능하게 한 걸로는 세상을 바꾸기는 어렵겠지만 이것을 불가능을 가능으로 바꾸게 한 것으로 더 넓게 생각해 보면 정말 세상을 바꿀 수 있다는 생각을 갖게 했고, 필자의 가치관에 변화를 준 것 같아 이렇게 포스팅까지 해봤다.

바이브 코딩은 hype?

뭔가 요즘 핫한 키워드인 바이브 코딩도 비슷한 느낌이다. 코딩에 국한되지 않고 기획, 마케팅, 모든 부분에서 llm이 해줄 수 있는 건 전문가 수준이 아니라 그저 그런 수준이다. 이제 여기서 더 잘하는 건 더이상 지능의 문제가 아닌 컨텍스트의 문제라고 생각한다. 1년 2년이 지나도 뭔가 더 잘할 것 같지는 않다.

근데 이 바이브 코딩으로 인해서 불가능한 일이 가능해져 버렸다. 직장 다니는 rn 모르고 js도 안 써본 사람이 한 달 안에 앱 출시하기. ai가 없을 때에는 새벽까지 자신을 갈아넣을 자신이 있는 사람 제외하고는 정말 불가능해 보이지만 이제는 퇴근 후 자기 전까지 시간을 갈아넣을 수 있는 사람에게는 진짜 가능해져 버린 시대이다.

조금 더 극단적으로 가보자면 일정 트래픽 이하로는 서비스 간 기술적 장벽이 완전히 무너졌다고 생각한다. (저번에 올린 네트워크 책 읽으면서 든 생각이다.) 문외한인 사람도 ai한테 타사 서비스 주고 어떻게 동작하냐고 물어보면 잘 설명해준다. 물론 완전히 구조를 파악하지는 못할 것이고, 똑같이 구현해달라 하면 어느정도 비슷한 수준으로 구현할 것이다.

개발자는 이거 정말 못한다 프로덕션에서는 못 써요~ 라고 할 수 있지만 대부분의 개발자는 확장성을 먼저 생각하는 경향이 있다. 우리(개발자)의 생각의 기저에는 유저가 이 행동을 하면 기능이 깨질 것이고, 100명만 더 들어와도 서비스가 다운될 것이다 라는 전제가 깔려 있어서 그렇다. 모두 유효한 생각이고 중요하다. 근데 타협볼 여지는 많다. 유저 입장에서는 백그라운드에서 어떻게 돌아가는지는 상관없고 돌아가는 것처럼 보이기만 하면 된다. 10명이 쓸 서비스라면 11명까지 버티는 서비스만 만들어도 충분하다. 스케일링은 그다음에 해도 된다. 그러한 상황이 오면 또 ai한테 물어보면 된다.

코딩 말고 조금 더 넓게 가보면? 사람에게 인지부하가 드는 일을 제외하면 그 일을 해낼 수 있는 난이도가 말도 안되게 낮아졌다고 생각한다. 갑자기 이상한 말 써서 이해가 안된다면 개발할 때 일반적으로 구현하는 작업 중에 엣지 케이스 고려하고 ux로 풀어내는 일을 인지부하가 많이 드는 일로 비유해 보겠다. 이 일을 제외한 나머지 부분은 ai가 다 알아서 해줄 수 있다. 혹은 그 분야에 숙련된 개발자라면 생각 안하고 정말 빠르게 구현이 가능하다. 개발자라면 분명히 경험해 봤을 것이다. 근데 엣지 케이스 고려하는 것 같이 인지부하가 많이 드는 일은 누가 해도 오래 걸린다. 뭔가 O(log n)과 O(n)의 차이랄까…?

마음만 먹으면 모든 일을 해내는 데 있어서 필요한 자원이 사람의 인지부하의 정도에 정확히 비례하게 되는 날이 머지 않았다는 말과 동일하다. 앞으로의 발전이 정말 기대가 된다. 그래서 필자는 최근 사업을 해보고 싶다는 생각이 들었다. 이 부분은 더 얘기하면 너무 길어져서 여기에서 컷하겠다.

마무리

원래 쓰던 글 성격이랑 다르게 야밤에 평소 파편화돼있던 필자의 생각을 마구 배설해 보았다. 블로그 들어와서 여기까지 보는 사람이 있는지는 모르겠지만 긴 글 읽어줘서 감사하다.