코드난독화로 역공학과 소프트웨어 도용의 비용 높이기

코드난독화의 유형과 한계, 모바일 앱·게임·기업용 소프트웨어에서 역공학과 라이선스 우회를 어렵게 만드는 적용 관점을 정리한다.

2026-08-14 · 최초 발행 2025-05-23

소스는 같고 해석만 어려워진다

코드난독화(Code Obfuscation)는 프로그램의 기능을 바꾸지 않으면서 원본 코드의 읽기와 이해를 의도적으로 어렵게 만드는 방법이다. 역공학(Reverse Engineering)으로 취약점을 찾거나 코드를 가져가려는 시도에 드는 비용을 높이는 데 쓰인다.

보호 대상은 알고리즘과 비즈니스 로직에만 한정되지 않는다. 라이선스 검증 로직, 내부 동작 원리, 보안 검증 루틴처럼 분석되었을 때 공격에 활용될 수 있는 코드도 대상이 된다. 공격 표면을 줄이고 지적재산권을 보호하려는 목적이 여기에서 만난다.

읽는 방식을 흐트러뜨리는 기법

구획 난독화: 코드의 외형을 바꾼다

구획 난독화(Layout Obfuscation)는 코드의 물리적 구조와 표현을 손봐서 가독성을 낮춘다. 변수나 함수 이름을 의미 없는 식별자로 바꾸고, 주석·들여쓰기·줄바꿈을 제거하거나 불필요한 코드를 넣는 방식이 여기에 속한다.

// 원본 코드
function calculateTotalPrice(items) {
  let total = 0;
  for (let i = 0; i < items.length; i++) {
    total += items[i].price * items[i].quantity;
  }
  return total;
}

// 난독화 코드
function a(b) {
  let c = 0;
  for (let d = 0; d < b.length; d++) {
    c += b[d].e * b[d].f;
  }
  return c;
}

데이터 난독화: 값과 구조의 의미를 감춘다

데이터 난독화(Data Obfuscation)는 프로그램이 다루는 데이터 구조를 변형한다. 하나의 변수를 나누거나 여러 변수를 합치고, 문자열과 상수 값을 인코딩하거나 배열을 재구성해 값의 의미를 바로 읽기 어렵게 만든다.

// 원본 코드
int securityKey = 12345;

// 난독화 코드
int a = 100;
int b = 23;
int securityKey = (a * b) + 45;

집합 난독화: 프로그램 구조를 다시 엮는다

집합 난독화(Aggregation Obfuscation)는 함수, 클래스, 상속 관계처럼 코드의 구조적 특성을 바꾼다. 함수 인라인, 함수 분할·병합, 클래스 구조 재구성, 상속 관계 변경이 대표적이다. 실행 결과는 같아도 흐름을 따라가며 구조를 파악하는 작업은 더 복잡해진다.

// 원본 코드
public int calculateSum(int a, int b) {
    return a + b;
}

// 난독화 코드 (함수 분할)
public int calculateSum(int a, int b) {
    int temp1 = processA(a);
    int temp2 = processB(b);
    return combine(temp1, temp2);
}

private int processA(int a) {
    return a * 1;
}

private int processB(int b) {
    return b * 1;
}

private int combine(int x, int y) {
    return x + y;
}

제어 난독화: 실행 경로를 복잡하게 만든다

제어 난독화(Control Obfuscation)는 제어 흐름을 복잡하게 구성해 로직의 의도를 파악하기 어렵게 한다. 불필요한 조건문, 루프 변환, goto 문이나 switch-case의 활용, 가상 함수 호출 체인이 여기에 포함된다.

// 원본 코드
int result = 0;
for (int i = 0; i < 10; i++) {
    result += i;
}

// 난독화 코드
int result = 0;
int i = 0;
while (true) {
    if (i >= 10) break;
    switch (i % 3) {
        case 0: result += i; i++; continue;
        case 1: i++; result += (i-1); continue;
        case 2: result += i; i++; continue;
    }
}

예방 난독화: 분석 환경 자체를 의식한다

예방 난독화(Preventive Obfuscation)는 디버깅과 분석 도구의 사용을 방해하는 기법을 묶는다. 안티 디버깅 코드, 자체 수정 코드, 환경 감지 로직, 체크섬 검증이 대표적이다.

// 디버거 감지 코드 예시
bool isDebuggerPresent() {
    volatile int counter = 0;
    clock_t start = clock();
    for(int i=0; i<1000000; i++) {
        counter++;
    }
    clock_t end = clock();
    double elapsed = ((double)(end - start)) / CLOCKS_PER_SEC;
    return elapsed < 0.1; // 너무 빠르면 디버거 사용 의심
}

변환부터 실행 파일까지의 경로

원본 소스코드전처리기난독화 종류 선택구획 난독화데이터 난독화집합 난독화제어 난독화예방 난독화난독화된 코드컴파일러/인터프리터실행 파일/바이트코드

방어 계층으로 볼 때의 제약

난독화는 분석을 불가능하게 만드는 기술이 아니다. 충분한 시간과 자원을 가진 공격자는 결국 분석할 수 있으므로, 성격상 지연 전략(Time Delay Strategy)에 가깝다.

복잡해진 제어 흐름과 추가 연산은 실행 속도를 낮출 수 있고, 코드 크기 증가는 메모리 사용량 증가로 이어질 수 있다. 개발자에게도 유지보수와 오류 추적이 어려워진다는 비용이 남는다.

도구 품질에 따라 효과가 달라지는 점도 고려해야 한다. 이미 알려진 난독화 패턴은 역난독화 도구로 분석될 수 있다.

보호 대상에 맞춰 적용하는 모습

모바일 애플리케이션에서는 인증 로직, 암호화 키 관리, 보안 검증 루틴에 난독화를 적용할 수 있다. 앱 위변조 시도를 줄이고 중요 알고리즘을 보호하려는 목적이다.

개발중요 로직 식별코드 난독화 적용안티탬퍼링 기법 추가 출시

온라인 게임에서는 치트와 불법 복제를 막기 위해 게임 로직을 난독화하고, 라이선스 검증 루틴을 숨기며, 메모리 조작 방지 기법을 적용한다. 불법 복제와 해킹 시도를 줄이고 게임 수명을 연장하는 데 목적이 있다.

B2B 솔루션에서는 라이선스 관리와 핵심 알고리즘 보호를 위해 라이선스 검증 코드를 난독화하고, 핵심 알고리즘을 분할해 난독화하며, 하드웨어 ID 기반 바인딩 로직을 숨길 수 있다. 이는 라이선스 우회 시도를 줄이고 핵심 기술을 보호하는 방향이다.

언어별 도구 선택지

JavaScript에서는 UglifyJS가 변수명 변경, 공백 제거, 최적화 기능을 제공한다. JavaScript Obfuscator는 고급 난독화 기법을 구현하며, Closure Compiler는 Google에서 제공하는 JS 최적화 및 난독화 도구다.

Java 환경에서는 안드로이드 앱 개발에서 널리 쓰이는 ProGuard가 있고, DashO는 고급 제어 흐름 난독화를 제공한다. Javaguard는 오픈소스 Java 난독화 도구다.

.NET에서는 Visual Studio와 통합된 Dotfuscator, 자동화된 .NET 코드 보호 도구인 Eazfuscator.NET, 오픈소스 .NET 난독화 프로젝트인 ConfuserEx를 선택지로 둘 수 있다.

중요 보안 로직, 핵심 알고리즘, 라이선스 검증처럼 보호 가치가 큰 기능에 선별적으로 적용하면 성능과 보안 사이의 균형을 잡을 수 있다. 난독화는 다른 보안 기법과 함께 전체 소프트웨어 보안 전략의 일부로 사용할 때 의미가 커진다.

코드난독화소프트웨어 보안역공학라이선스 보호안티디버깅