# OpenAI는 코드 복원(Unminifying)에 놀라운 성능을 보임

> Clean Markdown view of GeekNews topic #16529. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=16529](https://news.hada.io/topic?id=16529)
- GeekNews Markdown: [https://news.hada.io/topic/16529.md](https://news.hada.io/topic/16529.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2024-08-30T09:51:53+09:00
- Updated: 2024-08-30T09:51:53+09:00
- Original source: [glama.ai](https://glama.ai/blog/2024-08-29-reverse-engineering-minified-code-using-openai)
- Points: 3
- Comments: 1

## Topic Body

- 인터넷을 탐색하던 중 흥미로운 ASCII 아트 컴포넌트를 발견함. 멋져 보였지만 구현 방법을 이해하기 어려웠음  
- 소스 코드를 확인했으나 코드가 축약(Minified)되어 있었음  
  
#### 축약된 코드 예시  
- 코드 일부는 다음과 같음:  
  ```javascript  
  const { floor: ra, abs: KE, min: QE } = Math,  
    O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"],  
    G7 = Date.now() % 3 ? O5[1] : O5[0],  
    V5 = G7.length,  
    JE = { fps: 60 };  
  ```  
  
#### ChatGPT에게 코드 설명 요청  
- ChatGPT에게 "코드를 설명해 달라"고 요청함  
- ChatGPT의 응답:  
  > 제공된 코드는 상당히 복잡하지만, 각 부분과 기능을 이해하기 쉽게 설명하겠습니다.  
  
##### 개요  
- JavaScript를 사용하여 여러 함수와 컴포넌트를 정의함  
- React 애플리케이션에서 동적 텍스트 콘텐츠를 생성함  
- ASCII 아트 또는 미리 정의된 문자 세트를 사용한 시각적 효과를 생성함  
  
##### 주요 컴포넌트와 함수  
1. **문자 세트 선택:**  
  ```javascript  
  const { floor: ra, abs: KE, min: QE } = Math;  
  const O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"];  
  const G7 = Date.now() % 3 ? O5[1] : O5[0];  
  const V5 = G7.length;  
  ```  
  - `Math`의 함수들을 가져오고 두 개의 문자 세트를 정의함  
  - 현재 시간에 따라 문자 세트를 선택함  
  - 선택된 문자 세트의 길이를 저장함  
  
2. **동적 문자 선택 함수:**  
  ```javascript  
  function eT(e, t, n, r) {  
    const i = t.time * 8e-5;  
    const s = QE(t.cols, t.rows);  
    const o = t.metrics.aspect * 0.2;  
    const l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s };  
    const u = ra(KE(YE(l) - i) * V5 + (ra(e.x / 1) % 2) * 2) % V5;  
    return G7[u];  
  }  
  ```  
  - `eT` 함수는 입력 위치와 현재 시간에 따라 문자를 생성함  
  - 위치를 조정하고 문자 세트에서 문자를 선택함  
  
3. **동적 콘텐츠를 표시하는 React 컴포넌트 (`tT`):**  
  ```javascript  
  const tT = () => {  
    const e = j.useRef(null);  
    const [t, n] = j.useState({ height: null, width: null });  
    j.useEffect(() => {  
      function r() {  
        n({ height: window.innerHeight, width: window.innerWidth });  
      }  
      if (typeof window < "u") {  
        n({ height: window.innerHeight, width: window.innerWidth });  
        window.addEventListener("resize", r);  
        return () => window.removeEventListener("resize", r);  
      }  
    }, []);  
    j.useEffect(() => {  
      const r = e.current;  
      if (!r) return;  
      const i = 12;  
      const s = ra(t.width / i) * 1.6;  
      const o = ra(t.height / i);  
      const l = { aspect: s / o };  
      const u = setInterval(() => {  
        let c = "";  
        for (let d = 0; d < o; d++) {  
          for (let f = 0; f < s; f++) c += eT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() });  
          c += `  `;  
        }  
        r.textContent = c;  
      }, 1e3 / JE.fps);  
      return () => clearInterval(u);  
    }, [t]);  
    return a.jsx("div", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("div", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) });  
  };  
  ```  
  - 이 React 컴포넌트는 주기적으로 `div` 요소의 콘텐츠를 동적으로 생성된 문자로 업데이트함  
  - 창 크기에 따라 열과 행의 수를 계산하고 `div`를 문자로 채움  
  
#### TypeScript로 변환된 코드  
- ChatGPT에게 TypeScript로 변환된 코드를 요청함  
- ChatGPT의 응답:  
  ```typescript  
  import React, { useEffect, useRef, useState } from 'react';  
  const selectedCharacterSet = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ";  
  const characterSetLength = selectedCharacterSet.length;  
  
  const calculateCharacter = (  
    x: number,  
    y: number,  
    cols: number,  
    rows: number,  
    aspect: number,  
    time: number,  
  ): string => {  
    const timeFactor = time * 0.000_08;  
    const size = Math.min(cols, rows);  
    const aspectRatio = aspect * 0.2;  
    const position = {  
      x: ((4 * (x - cols / 6.25)) / size) * aspectRatio,  
      y: (5 * (y - rows / 4)) / size,  
    };  
    const index = Math.floor(  
      Math.abs(  
        Math.cos(position.x * position.x - position.y * position.y) - timeFactor,  
      ) * characterSetLength + (Math.floor(x) % 2) * 2,  
    ) % characterSetLength;  
    return selectedCharacterSet[index];  
  };  
  
  type Size = {  
    height: null | number;  
    width: null | number;  
  };  
  
  const AsciiArtGenerator: React.FC = () => {  
    const textRef = useRef(null);  
    const [size, setSize] = useState({ height: null, width: null });  
  
    useEffect(() => {  
      const handleResize = () => {  
        setSize({ height: window.innerHeight, width: window.innerWidth });  
      };  
      handleResize();  
      window.addEventListener('resize', handleResize);  
      return () => {  
        window.removeEventListener('resize', handleResize);  
      };  
    }, []);  
  
    useEffect(() => {  
      const element = textRef.current;  
      if (!element || !size.width || !size.height) return undefined;  
  
      const cols = Math.floor(size.width / 12) * 1.6;  
      const rows = Math.floor(size.height / 12);  
      const aspectRatio = cols / rows;  
  
      const intervalId = setInterval(() => {  
        let content = '';  
        for (let y = 0; y < rows; y++) {  
          for (let x = 0; x < cols; x++) {  
            content += calculateCharacter(x, y, cols, rows, aspectRatio, Date.now());  
          }  
          content += '\n';  
        }  
        element.textContent = content;  
      }, 1_000 / 60);  
  
      return () => {  
        clearInterval(intervalId);  
      };  
    }, [size]);  
  
    return (  
      
    );  
  };  
  
  export default () => {  
    return ;  
  };  
  ```  
  
#### GN⁺의 정리  
- 이 글은 축약된 코드를 이해하고 복원하는 방법을 설명함  
- ChatGPT를 사용하여 복잡한 코드를 설명하고 TypeScript로 변환하는 과정을 보여줌  
- 코드 복원과 이해를 돕기 위해 AI 도구를 활용하는 방법을 제시함  
- 비슷한 기능을 가진 프로젝트로는 `Prettier`와 `UglifyJS`가 있음

## Comments



### Comment 28427

- Author: neo
- Created: 2024-08-30T09:51:53+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=41389185) 
- HumanifyJS의 저자가 LLM 기반 도구를 개발했음. 이 도구는 AST 수준에서 LLM을 사용하여 코드가 unminification 후에도 작동하도록 보장함
  - [HumanifyJS GitHub 링크](https://github.com/jehna/humanify)

- JS minification은 기계적이고 비교적 간단함. 수동으로 수행하기에는 번거롭지만, 변환 자체는 제한적이어서 일부 노트로 식별자를 추적하며 읽을 수 있음

- 일반적인 unminification이나 unobfuscation은 여전히 해결되지 않은 문제임. 과거에 의도적으로 난독화된 프로그램을 작성했는데, ChatGPT는 표면 수준에서도 이해하지 못했음
  - 예: 160바이트 길이의 Brainfuck 인터프리터를 GPT-4가 설명하려 했으나 원본 코드와 전혀 유사하지 않았음
  - [예시 코드 링크](https://gist.github.com/lifthrasiir/596667#gistcomment-4751211)

- 일부 개발자는 난독화를 위해 minification을 사용하기 때문에 불만을 가질 수 있음. ColdFusion의 이전 버전에서 제공된 코드 "암호화" 도구가 약한 알고리즘이었음에도 불구하고, 이를 안전하다고 생각하고 사용한 사람들이 있었음

- 제목에 OpenAI 대신 ChatGPT나 gpt-4를 사용하는 것이 더 적절할 수 있음

- 이 작업은 인간보다 우수한 지적 성능의 예임. LLM은 unminification을 이해하고 있으며, 이 특정 주제에서는 인간보다 우수함

- LLM은 텍스트 변환에 뛰어남. 이것이 그들의 핵심 강점임

- 약 1년 전, GPT를 사용하여 악성 코드의 난독화를 시도했으나 직접 코드를 분석하는 것이 더 나았음. 최근 다시 시도했을 때는 어느 정도 이해할 수 있었음
  - 예: 페이지 로드를 감지하고, 계산을 수행하며, 악성 사이트로 리디렉션하는 로직을 파악함
  - [보고서 링크](https://chatgpt.com/share/f51fbd50-8df0-49e9-86ef-fc972bca6ba9)

- LLM을 사용하여 복잡한 코드를 더 읽기 쉽게 만드는 것이 매우 해방감을 줌. 때로는 세부 사항을 놓치지만, 이는 직접 확인할 수 있음
  - 코드의 목적은 이해하지만, 특정 방식으로 작성된 이유를 이해하지 못할 때 LLM에 질문하여 새로운 통찰을 얻을 수 있음
  - [사용 예시 링크](https://chatgpt.com/share/f51fbd50-8df0-49e9-86ef-fc972bca6ba9)

- unminified 코드가 minified 코드와 일치하지 않으면 유용성이 크게 감소함. 많은 경우 코드 실행 후 차이를 확인할 수 없음
  - [인코딩 문제 관련 스레드 링크](https://chatgpt.com/share/f51fbd50-8df0-49e9-86ef-fc972bca6ba9)

- 웹사이트의 계산 알고리즘을 알고 싶을 때 minified JS를 ChatGPT에 넣어 쉽게 파악할 수 있었음. LLM이 전체 SAAS 앱을 클론할 수 있는 미래를 상상할 수 있음
  - 예: HubSpot 클론을 만들기 위해 LLM이 브라우저와 상호작용하고 UI를 분석하며 백엔드 아키텍처를 제안할 수 있음
  - AI가 미래에 강력한 디플레이션 요인이 될 것임
