71. 소스코드 난독화 (Obfuscation) 적용 여부 감리

⚠️ 이 문서는 웹(Web) 환경과 달리 사용자 기기에 실행 파일(APK, IPA 등) 통째로 다운로드되는 모바일 앱이나 클라이언트 소프트웨어에서, 해커가 디컴파일(Decompile) 도구를 통해 소스코드를 원본 그대로 복원해 내어 치명적인 로직과 비밀키를 탈취하는 '역공학(Reverse Engineering)'을 막기 위해 필수적으로 적용해야 하는 '난독화' 기술의 점검 가이드라인을 다룹니다.

핵심 인사이트 (3줄 요약)

  1. 본질: 해커가 디컴파일러를 돌려서 보게 되는 소스코드의 변수명, 클래스명, 제어문 구조를 인간이 도저히 읽고 해석할 수 없는 엉망진창의 상태(의미 없는 알파벳의 나열 등)로 꼬아버리는 보호 기법이다.
  2. 가치: 앱 안에 숨겨진 결제 로직의 취약점이나, 사내 API 서버로 쏘는 암호화 통신 키(Key)가 평문으로 털리는 것을 지연시켜, 사실상 해커가 분석을 포기하게 만드는 가장 현실적이고 강력한 클라이언트 보안의 방패다.
  3. 기술 체계: 단순히 이름만 바꾸는 **'식별자 난독화'**부터 시작해, 코드를 읽는 순서를 뒤죽박죽으로 섞는 '제어 흐름 난독화', 그리고 문자열이나 데이터를 암호화하는 기법까지 다중으로 적용되어야 금융감독원 및 KISA의 감리 기준을 통과할 수 있다.

Ⅰ. 역공학(Reverse Engineering)의 위협과 디컴파일

우리가 짠 예쁜 코드는 해커에게는 완벽한 공략집이 된다.

  1. 디컴파일 (Decompile)의 무서움:
    • 안드로이드 앱 파일(app.apk)을 인터넷에서 다운받아, 무료 디컴파일 툴(JADX 등)에 넣고 돌리면, 개발자가 짰던 자바(Java) 원본 소스코드가 90% 이상 그대로 튀어나온다.
    • if (user_grade == "VIP") { discount(30); } 같은 친절한 코드를 해커가 읽고, 메모리 조작 툴을 써서 일반 회원인데도 VIP 할인을 받게 조작해버린다.
  2. 평문 문자열의 유출:
    • 소스코드 어딘가에 적어둔 String db_password = "admin123!" 이나 aws_secret_key = "..." 같은 중요한 하드코딩 값이 그대로 노출되어 대형 보안 사고로 직결된다.

📢 섹션 요약 비유: 군대에서 작전 지도(앱 파일)를 병사들(사용자)에게 하나씩 나눠주었는데, 그 지도를 적군(해커)이 뺏어서 보면 아군의 화약고 위치와 비밀 통로가 아주 친절한 한글로 적혀있는 끔찍한 상황입니다. 그래서 적군이 지도를 뺏더라도 해독할 수 없게, 지도의 모든 글씨를 외계어로 바꿔 적어두는 것이 바로 난독화입니다.


Ⅱ. 난독화의 3대 기술 메커니즘

읽지 못하게 만드는 방법은 다양하며, 조합할수록 뚫기 어려워진다.

  1. 식별자 (Identifier) 난독화:
    • 가장 기본적이고 널리 쓰이는 기법이다. (안드로이드의 ProGuard 등)
    • CustomerManager라는 클래스 이름은 A, calculateSalary()라는 메서드 이름은 b()로 바꿔버린다.
    • 컴퓨터(기계) 입장에서는 이름이 ACustomerManager든 똑같이 실행되지만, 인간 해커는 이 클래스가 도대체 무슨 역할을 하는 코드인지 짐작할 길이 없어진다.
  2. 제어 흐름 (Control Flow) 난독화:
    • 해커는 if-elsewhile 루프의 모양을 보고 프로그램의 논리를 파악한다.
    • 이를 막기 위해, 원래 한 줄로 끝나는 코드를 의미 없는 쓰레기 코드(Dead Code) 백 줄 사이에 숨겨놓거나, goto 문을 수십 개 섞어 넣어(스파게티 코드 화) 로직의 흐름을 꽈배기처럼 비틀어버린다.
  3. 문자열 (String) 암호화:
    • 해커가 소스코드 내에서 검색(Search) 기능으로 "password", "http" 같은 단어를 치면 중요 로직을 바로 찾을 수 있다.
    • 모든 평문 문자열을 암호화해 두고, 프로그램이 실행되는 순간(Runtime)에만 메모리에서 잠깐 풀어서(복호화) 사용하게 만든다.

📢 섹션 요약 비유: 난독화 3종 세트는 이렇습니다. 첫째, 문서의 등장인물 이름(철수, 영희)을 무작위 알파벳(A, B)으로 싹 바꿉니다(식별자 난독화). 둘째, 문서의 1페이지 다음에 2페이지가 아니라 75페이지 중간으로 가서 읽으라고 화살표를 엉망으로 꼬아놓습니다(제어 흐름 난독화). 셋째, 문서에 적힌 은행 계좌번호는 특수 잉크로 칠해 평소엔 안 보이다가 불을 쬘 때만 1초 보이게 만듭니다(문자열 암호화).


Ⅲ. 감리 시 핵심 점검 체크리스트 및 트레이드오프

법은 깐깐하고, 개발팀은 불편해한다.

  1. 상용 난독화 솔루션 적용 여부 점검 (금융/공공 의무):
    • 오픈소스 난독화(ProGuard)는 뚫리기 쉽기 때문에, 금융권이나 중요 공공기관 앱 감리 시에는 DexGuard, Arxan 같은 **'상용 난독화 솔루션'**이 빌드 파이프라인(CI/CD)에 반드시 연동되어 있는지 확인한다.
    • 감리인이 직접 디컴파일 툴을 돌려보고, "코드가 평문으로 안 보이네요, 통과!"라고 실증 테스트를 해야 한다.
  2. 트레이드오프 1: 성능 저하 및 용량 증가:
    • 제어 흐름 난독화를 세게 걸면 쓸데없는 코드가 많아져 앱 용량이 늘어나고, 스마트폰 배터리를 많이 먹으며 앱 실행 속도가 느려진다.
  3. 트레이드오프 2: 크래시(Crash) 로그 분석의 고통:
    • 앱이 죽어서 남긴 에러 로그(Stack Trace)도 A.b()에서 에러 발생이라고 난독화되어 찍히므로, 개발자가 디버깅을 할 수 없다.
    • 따라서 난독화 솔루션이 뱉어내는 매핑(Mapping) 파일(외계어를 원본어로 다시 돌려주는 족보)을 깃허브나 백업 서버에 절대 유출되지 않게 철저히 챙겨두고 있는지 감리해야 한다.

📢 섹션 요약 비유: 도둑(해커)을 막겠다고 창문에 철창을 너무 많이 치고(과도한 난독화), 집안의 물건 이름을 다 외계어로 바꿔버리면, 정작 주인(개발자)이 보일러가 고장 났을 때(버그 발생) 고치기가 너무 힘들어집니다. 그래서 주인은 반드시 '외계어 번역 사전(매핑 파일)'을 비밀 금고에 잘 보관해 두어야만 나중에 집수리를 할 수 있습니다.