본문 바로가기
Android/Reverse

Android 동적 로딩 이론편 - DexClassLoader, PathClassLoader, InMemoryDexClassLoader 이해하기

by 굿햄 2026. 4. 6.

프롤로그

최근 Android의 개발자 인증 정책을 보면서, 자연스럽게 한 가지 질문을 떠올렸습니다.

 

"앞으로 앱 설치 경로와 개발자 신뢰 체인이 더 강하게 묶이면, 런타임에는 어떤 코드가 실제로 실행되는지가 더 중요해지는 것 아닐까?"

 

정책 변화 자체가 곧바로 동적 로딩 문제로 이어지는 것은 아닙니다.
하지만 앱이 설치된 이후 어떤 코드 경로가 열리고, 어떤 클래스가 런타임에 실제로 메모리에 올라오는지를 이해하는 일은 분명 더 중요해집니다.

 

그래서 이번에는 Android에서 자주 언급되는 세 가지 동적 로딩 방식,

  • DexClassLoader
  • PathClassLoader
  • InMemoryDexClassLoader

를 중심으로, 왜 이 주제가 Android 개발자에게도 중요하게 읽혀야 하는지 먼저 정리해 보려고 합니다.

 


개발자 인증 정책은 무엇이 바뀌고 있나

Android Developers의 공식 가이드를 보면, 개발자 인증은 악의적인 행위자를 차단하고 인증된 Android 기기에서 설치되는 앱을 더 강하게 추적하기 위한 방향으로 설명됩니다. 일정도 이미 꽤 구체적입니다.

  • 2025년 8월: 새로운 Android 개발자 인증 요구사항 발표
  • 2025년 11월: 사전 체험 프로그램 시작
  • 2026년 3월: 모든 개발자 등록 개시
  • 2026년 6월: 제한된 배포 계정 사전 체험 프로그램 시작

이 정책에 대해 커뮤니티에서는 반발과 우려도 분명 존재합니다.

Keep Android Open 같은 사이트는 이 흐름이 Android의 개방성을 약화시킬 수 있다고 주장합니다.

 

다만 이 글의 핵심은 정책 비판이 아닙니다.
여기서 중요한 것은 아래 한 줄입니다.

 

동적 로딩 자체가 개발자 인증 우회책은 아닙니다.
하지만 설치 이후 어떤 코드가 실제로 로드되고 실행되는지를 숨길 수 있다는 점에서, 동적 로딩은 여전히 보안적으로 매우 민감한 주제입니다.


왜 동적 로딩이 보안에서 민감한가

Android 공식 보안 문서는 동적 코드 로딩이 애플리케이션에 추가적인 위험을 들여온다고 분명하게 설명합니다.

로드 대상 코드가 변조되거나 대체되면, 민감한 데이터에 접근하거나 해로운 동작을 실행할 수 있기 때문입니다.

 

특히 공식 문서는 아래 두 가지를 강하게 권고합니다.

  • 비즈니스상 꼭 필요한 경우가 아니면 동적 코드 로딩을 피할 것
  • 꼭 써야 한다면 신뢰 가능한 저장소와 무결성 검증을 사용할 것

또 원격 소스에서 코드를 내려받아 실행하는 형태의 동적 로딩은 Google Play 정책과 충돌할 수 있다고도 언급합니다.
개발자 입장에서는 "기술적으로 가능하다"와 "제품에 넣어도 된다"를 분리해서 봐야 한다는 뜻입니다.

실제 위 라이브러리를 포함한 경우 공식 앱 스토어에 배포 진행은 불가능 한 것으로 보입니다.
그러나, 앱을 유포하는 경로는 다양하고 테스트 권한을 가진 계정으로 설치를 유도하는 것을 어렵지 않아 보입니다.

 

보안 분석 글에서도 이 지점이 반복해서 등장합니다. 최근 안드로이드 악성 앱은 정적 분석을 회피하기 위해 핵심 로직을 별도 DEX로 숨기고, 실행 시점에만 로드하는 패턴을 자주 사용합니다. 설치된 APK만 열어 봐서는 중요한 로직이 보이지 않게 만드는 것입니다.


DEX와 ClassLoader 기본기

안드로이드 앱은 결국 DEX(Dalvik Executable) 형태의 바이트코드로 실행됩니다.

자바나 코틀린 소스가 컴파일되면 .class 파일이 만들어지고, 안드로이드 빌드 과정을 거치며 다시 .dex로 변환됩니다.

 

ClassLoader는 이 바이트코드를 런타임에 JVM/ART가 이해할 수 있는 Class로 연결하는 역할을 맡습니다.
평소에는 앱 설치 시점에 포함된 코드를 기본 클래스 로더가 처리하므로 이 과정을 의식할 일이 거의 없습니다.

하지만 앱이 런타임에 별도의 DEX를 읽어 오거나, 이미 설치된 다른 경로의 코드 조각을 참조하거나, 아예 메모리 버퍼에서 직접 DEX를 읽기 시작하면 이야기가 달라집니다.

 

이때 등장하는 것이 BaseDexClassLoader 계열의 클래스들입니다.

 

여기서 중요한 관점은 단순합니다.

  • 무엇이 APK 안에 들어 있었는가
  • 무엇이 런타임에 실제로 로드되었는가

DexClassLoader, PathClassLoader, InMemoryDexClassLoader 비교

Android 공식 레퍼런스를 기준으로 보면, 이번 글에서 볼 핵심 로더는 아래 셋입니다.

DexClassLoader

DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent)

  • .jar나 .apk 안의 classes.dex를 포함한 파일 경로를 로드할 수 있습니다.
  • API 26 이전에는 앱 전용 writable cache 디렉터리가 필요했습니다.
  • optimizedDirectory는 API 26부터는 더 이상 효과가 없습니다.
  • 파일 기반이라 로딩 대상이 디스크에 남는 편입니다.

가장 전형적인 파일 기반 동적 로딩이라고 보면 됩니다.

PathClassLoader

PathClassLoader(String dexPath, ClassLoader parent)
PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent)

  • 로컬 파일 시스템이나 APK 경로를 기반으로 동작합니다.
  • Android는 이 계열을 시스템 클래스 로더와 애플리케이션 클래스 로더에 사용합니다.
  • optimizedDirectory 파라미터가 없습니다.

이 로더는 "외부 플러그인을 붙인다"기보다, Android가 원래 클래스 경로를 해석하는 방식과 더 가깝습니다.

InMemoryDexClassLoader

InMemoryDexClassLoader(ByteBuffer dexBuffer, ClassLoader parent)

  • API 26부터 사용할 수 있습니다.
  • 파일 시스템에 DEX를 쓰지 않고 ByteBuffer에서 직접 클래스 로딩이 가능합니다.
  • 따라서 저장소 기반 포렌식이나 정적 분석 관점에서는 가장 까다로운 축에 속합니다.

이 로더가 중요한 이유는, "파일이 안 보이는데도 코드가 실행될 수 있다"는 사실을 가장 직관적으로 보여 주기 때문입니다.


안드로이드 개발자가 보안 관점에서 봐야 할 점

일반적인 앱 개발 실무에서 동적 로딩은 기본 선택지가 아닙니다.


기본적인 배포 방식보다 구현이 까다롭고, 검증과 운영 비용도 더 크기 때문입니다. 그래서 이 주제는 "어떻게 도입할까"보다 "어떤 앱이 왜 이런 구조를 쓰는가"를 읽어내는 관점이 더 중요합니다.

 

  • 비즈니스상 꼭 필요한 이유가 없다면, 기능은 앱 안에 직접 포함하는 쪽이 더 안전합니다.
  • 꼭 써야 한다면 내부 저장소나 scoped storage 같은 신뢰 가능한 위치를 사용하고, 로딩 전에 무결성 검증을 해야 합니다.
  • 파일 기반 동적 로딩을 쓰면서 외부 저장소에 그냥 두는 것은 특히 좋지 않습니다.
  • 보안 검토에서는 "설치된 앱"과 "런타임에 실제로 실행되는 코드"가 다를 수 있다는 점을 함께 봐야 합니다.
  • 안드로이드 개발자 관점에서는 기능 분리나 지연 전달이 목적이라면, Play Feature Delivery 같은 정식 메커니즘과 이 구조를 구분해서 보는 정도면 충분합니다.

요약

이론만 먼저 짧게 정리하면 아래와 같습니다.

  • DexClassLoader는 파일 기반이라 이해와 추적이 가장 쉽습니다.
  • PathClassLoader는 Android의 기본 클래스 로딩 모델을 이해하는 데 중요합니다.
  • InMemoryDexClassLoader는 흔적이 적고 런타임 의존성이 커서 분석 난도가 가장 높습니다.

정책 변화는 배경일 뿐이고, 이 글의 핵심은 다른 데 있습니다.
안드로이드 앱에서 "무엇이 설치되었는가"만큼이나 "런타임에 무엇이 실제로 로드되는가"도 중요하다는 점입니다.

 

다음 글은 실습을 통한 모의해킹 구현으로 찾아오겠습니다.

감사합니다

 

 

댓글