0 투표
javascript 난독화 방법 알려주세요.

1 답변

0 투표

맞아요. 다만 난독화(obfuscation)는 “복잡하게 만들기”일 뿐, 암호화/DRM처럼 완전한 보호는 아니고 의지만 있으면 결국 분석됩니다. 그래서 보통은 번들링 + 최소화(minify) + 난독화 + 서버로 로직 이동 + 배포/운영 설정을 같이 묶어서 합니다.

아래는 “웹(브라우저)에서 돌아가는 JS/TS” 기준으로, 실제로 많이 쓰는 방법들입니다.


1) 제일 기본: 번들 + 최소화(=가성비 최고)

  • Webpack / Vite / Rollup / esbuild 중 하나로 번들링
  • Terser로 압축/난독화(변수명 변경 포함)

(A) Vite 사용 시 (권장/간단)

Vite는 기본적으로 빌드에서 minify를 해줍니다.

  • vite.config.ts
import { defineConfig } from "vite";

export default defineConfig({
  build: {
    minify: "terser",
    terserOptions: {
      compress: true,
      mangle: true,
      format: { comments: false },
    },
    sourcemap: false, // 배포 시 소스맵 끄기(아래 참고)
  },
});

(B) Webpack 사용 시

  • webpack.config.jsTerserPlugin 설정
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  // ...
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: true,
          mangle: true,
          format: { comments: false },
        },
        extractComments: false,
      }),
    ],
  },
};

이것만 해도 소스 읽기 난이도는 확 올라가고, 용량/로딩도 좋아집니다.


2) 더 “난독화”답게: javascript-obfuscator(강도 ↑, 부작용도 ↑)

Terser보다 더 공격적으로 꼬는 방식입니다(문자열 암호화, control-flow flattening 등).

설치

npm i -D javascript-obfuscator

(A) 빌드 결과물(dist)에 후처리로 적용 (가장 안전한 편)

npx javascript-obfuscator dist --output dist-obf \
  --compact true \
  --control-flow-flattening true \
  --control-flow-flattening-threshold 0.6 \
  --string-array true \
  --string-array-threshold 0.75 \
  --dead-code-injection false \
  --self-defending false \
  --debug-protection false

추천 포인트

  • control-flow-flattening / string-array가 체감 난독화에 가장 큽니다.
  • dead-code-injection, self-defending, debug-protection호환성/성능/오탐 이슈가 생길 수 있어 보통은 꺼두고 시작합니다.

(B) 설정 파일로 관리(권장)

obfuscator.json

{
  "compact": true,
  "controlFlowFlattening": true,
  "controlFlowFlatteningThreshold": 0.6,
  "stringArray": true,
  "stringArrayThreshold": 0.75,
  "simplify": true,
  "deadCodeInjection": false,
  "selfDefending": false,
  "debugProtection": false,
  "renameGlobals": false
}

실행:

npx javascript-obfuscator dist --output dist-obf --config obfuscator.json

3) 소스노출 관점에서 “진짜 중요한 것” 3가지

1) 소스맵(sourcemap) 관리

  • 배포에서 sourcemap: false가 기본.
  • 에러 추적(Sentry 등) 때문에 소스맵이 필요하면:

    • 소스맵은 서버/스토리지에만 업로드하고
    • 웹에 공개로 배포하지 않기
    • 업로드 후 로컬/배포 경로의 .map 파일은 제거

2) “보호하고 싶은 로직”은 가능하면 서버로

브라우저에 내려가는 순간, 결국은 노출됩니다.

  • 가격정책/정책판정/치트방지/검증 로직 등은 서버에서 최종 판정 구조로.

3) 비밀값(키/토큰)을 프론트에 넣지 않기

난독화로 숨길 수 없습니다.

  • API Key는 서버 프록시 또는 권한이 제한된 공개키(도메인 제한 등)만 사용.

4) 상용 보호 쪽에서 많이 같이 하는 것들(현실적인 조합)

  • 라이선스/구독 기반이면:

    • 서버에서 라이선스 검증 → 기능 토글/만료 처리
    • 빌드에 워터마크(고객사별 식별자) 삽입
  • 배포 보안:

    • 코드 서명/무결성 체크(가능한 범위 내)
    • CDN 캐시/헤더 설정(맵 파일 차단 등)

5) 추천 “출발점” (성능/안정/보호 밸런스)

  1. 번들링 + Terser 최소화로 먼저 배포
  2. 그래도 부족하면 빌드 산출물에 javascript-obfuscator를 “후처리”로 추가
  3. 문제 생기면 옵션을 조금씩 켜고 끄며 튜닝 (특히 flattening/threshold)

원하는 방향이 (1) 프론트 웹앱, (2) 라이브러리/SDK 배포, (3) Node 서버 코드, (4) 모바일(React Native 등) 중에 어디에 더 가까워요? 그거에 맞춰 권장 툴체인(Vite/webpack) + 옵션 세트(성능/호환성 중심 vs 난이도 중심)로 딱 맞게 구성 예시를 더 구체적으로 잡아줄게요.

구로역 맛집 시흥동 맛집
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
...