당근, 숏폼 기능 DFM 도입으로 앱 용량 200MB → 40MB
200MB에 달하는 숏폼 비디오 편집 기능의 용량 문제를 해결하기 위해 DFM(Dynamic Feature Module)을 도입
CDN(Content Delivery Network) 전환을 통해 리소스 용량을 40MB로 감소시켰으나, 여전히 글로벌 사용자에게 부담
On-demand Delivery 방식을 선택하여 편집 기능 사용 시에만 모듈을 다운로드하도록 변경, 앱 설치 용량 절감 효과
Hilt/DI 제약, SplitCompat 설정, SO 파일 관리 등 DFM 도입 과정에서 다양한 기술적 문제 발생
최종적으로 SO 파일만 DFM으로 분리하고 기능 코드는 base 모듈에 유지, 안정성과 개발 편의성을 확보
DFM(Dynamic Feature Module) 아키텍처 설계
당근 숏폼팀은 DFM(Dynamic Feature Module)을 통해 숏폼 편집 기능의 데이터 격리 아키텍처(Data Isolation Architecture)를 구현했다. 초기에는 기능 코드 전체를 DFM으로 이전하려 했으나, Hilt/DI 제약, SplitCompat 설정, SO 파일 관리의 어려움으로 인해 SO 파일만 DFM으로 분리하는 방식으로 변경했다.
On-demand Delivery: 사용자가 편집 기능을 처음 사용할 때 DFM을 다운로드
Base 모듈: 기능 코드 및 DFM 로딩 관리
DFM: SO 파일(네이티브 라이브러리) 포함
이러한 설계를 통해 안정성(Stability)과 개발 편의성(Developer Experience)을 동시에 확보했다.
Hilt/DI 제약과 해결 방법
DFM 환경에서 Hilt를 사용하기 위한 해결책은 EntryPoint 패턴을 활용하는 것이다. DFM은 base 모듈과 별도로 빌드되므로, Hilt의 어노테이션 프로세서가 DFM 안의 의존성을 인식할 수 없다. 따라서 base 모듈에서 EntryPoint 인터페이스(EntryPoint Interface)를 정의하여 의존성을 노출하고, DFM에서는 Dagger 컴포넌트를 직접 구성해야 한다.
EntryPoint: base 모듈에서 의존성 제공
Dagger Component: DFM에서 의존성 주입
이러한 방식을 통해 DFM에서도 의존성 주입(Dependency Injection)을 안전하게 사용할 수 있다.
SplitCompat 설정과 SO 파일 관리
DFM은 split APK 형태로 설치되므로, 기본 ClassLoader가 DFM의 클래스나 리소스를 인식하지 못하는 문제가 발생한다. 이를 해결하기 위해 SplitCompat을 적용하여 ClassLoader를 패치해야 한다. 또한, SO 파일 로딩 경로, ABI 필터, STL 버전 관리 등 다양한 문제를 해결해야 한다.
SplitCompat.install(this): DFM 코드 및 리소스 접근
SplitInstallHelper.loadLibrary(): DFM의 SO 파일 로딩
ABI 필터 일치: base 모듈과 DFM의 ABI 세트 일치
이러한 과정을 통해 DFM 환경에서 SO 파일 로딩(SO File Loading) 문제를 해결하고, 앱의 안정성을 확보했다.
R8 규칙 관리와 난독화 문제
DFM 환경에서 R8(ProGuard) 규칙 관리는 매우 중요하다. DFM에만 keep 규칙을 적용하면 base 모듈의 타입이 난독화되어 런타임에 타입을 찾지 못하는 문제가 발생할 수 있다. 따라서 keep 규칙은 base 모듈에 집중하고, DFM의 consumerProguard는 최소한으로 유지하는 것이 좋다.
Base 모듈 keep 규칙: 핵심 코드 보호
DFM consumerProguard: 최소한의 규칙 유지
이러한 전략을 통해 코드 난독화(Code Obfuscation) 문제를 해결하고, 앱의 안정성을 높였다.
DFM 테스트 전략
DFM은 설치된 상태와 설치되지 않은 상태 모두를 테스트해야 하므로, 다양한 테스트 방식을 활용한다. 실제 환경에서는 Play Console 내부 테스트나 Internal App Sharing을 통해 실제 다운로드 플로우를 검증하고, 로컬 환경에서는 bundletool을 사용하여 DFM 설치/미설치 상태를 전환하며 반복 테스트를 수행한다. 또한, Universal APK를 통해 모든 모듈이 합쳐진 상태로 빠르게 설치 및 검증할 수 있다.
Play Console 테스트: 실제 다운로드 플로우 검증
bundletool: DFM 설치/미설치 상태 전환
Universal APK: 모든 모듈 통합 테스트
이러한 테스트 전략을 통해 DFM의 안정성(Stability)을 확보하고, 사용자 경험을 개선한다.