3P by neo 21일전 | favorite | 댓글 1개
  • 인터넷을 탐색하던 중 흥미로운 ASCII 아트 컴포넌트를 발견함. 멋져 보였지만 구현 방법을 이해하기 어려웠음
  • 소스 코드를 확인했으나 코드가 축약(Minified)되어 있었음

축약된 코드 예시

  • 코드 일부는 다음과 같음:
    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. 문자 세트 선택:
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의 함수들을 가져오고 두 개의 문자 세트를 정의함
  • 현재 시간에 따라 문자 세트를 선택함
  • 선택된 문자 세트의 길이를 저장함
  1. 동적 문자 선택 함수:
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 함수는 입력 위치와 현재 시간에 따라 문자를 생성함
  • 위치를 조정하고 문자 세트에서 문자를 선택함
  1. 동적 콘텐츠를 표시하는 React 컴포넌트 (tT):
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의 응답:
    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 도구를 활용하는 방법을 제시함
  • 비슷한 기능을 가진 프로젝트로는 PrettierUglifyJS가 있음
Hacker News 의견
  • HumanifyJS의 저자가 LLM 기반 도구를 개발했음. 이 도구는 AST 수준에서 LLM을 사용하여 코드가 unminification 후에도 작동하도록 보장함

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

  • 일반적인 unminification이나 unobfuscation은 여전히 해결되지 않은 문제임. 과거에 의도적으로 난독화된 프로그램을 작성했는데, ChatGPT는 표면 수준에서도 이해하지 못했음

    • 예: 160바이트 길이의 Brainfuck 인터프리터를 GPT-4가 설명하려 했으나 원본 코드와 전혀 유사하지 않았음
    • 예시 코드 링크
  • 일부 개발자는 난독화를 위해 minification을 사용하기 때문에 불만을 가질 수 있음. ColdFusion의 이전 버전에서 제공된 코드 "암호화" 도구가 약한 알고리즘이었음에도 불구하고, 이를 안전하다고 생각하고 사용한 사람들이 있었음

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

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

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

  • 약 1년 전, GPT를 사용하여 악성 코드의 난독화를 시도했으나 직접 코드를 분석하는 것이 더 나았음. 최근 다시 시도했을 때는 어느 정도 이해할 수 있었음

    • 예: 페이지 로드를 감지하고, 계산을 수행하며, 악성 사이트로 리디렉션하는 로직을 파악함
    • 보고서 링크
  • LLM을 사용하여 복잡한 코드를 더 읽기 쉽게 만드는 것이 매우 해방감을 줌. 때로는 세부 사항을 놓치지만, 이는 직접 확인할 수 있음

    • 코드의 목적은 이해하지만, 특정 방식으로 작성된 이유를 이해하지 못할 때 LLM에 질문하여 새로운 통찰을 얻을 수 있음
    • 사용 예시 링크
  • unminified 코드가 minified 코드와 일치하지 않으면 유용성이 크게 감소함. 많은 경우 코드 실행 후 차이를 확인할 수 없음

  • 웹사이트의 계산 알고리즘을 알고 싶을 때 minified JS를 ChatGPT에 넣어 쉽게 파악할 수 있었음. LLM이 전체 SAAS 앱을 클론할 수 있는 미래를 상상할 수 있음

    • 예: HubSpot 클론을 만들기 위해 LLM이 브라우저와 상호작용하고 UI를 분석하며 백엔드 아키텍처를 제안할 수 있음
    • AI가 미래에 강력한 디플레이션 요인이 될 것임