앱 크기 최적화 — Tree Shaking, Deferred Components

앱 크기가 클수록 다운로드 전환율이 떨어집니다. Google에 따르면 APK 크기가 6MB 증가할 때마다 설치율이 1% 감소합니다. Flutter 앱의 크기를 줄이는 방법을 정리해보겠습니다.


앱 크기 분석

BASH
# 앱 크기 분석 (Android)
flutter build apk --analyze-size

# 앱 크기 분석 (iOS)
flutter build ios --analyze-size

# 결과를 DevTools에서 시각화
# 터미널에 표시된 JSON 파일을 DevTools App Size 탭에서 열기

Tree Shaking

Dart는 빌드 시 사용하지 않는 코드를 자동으로 제거합니다(Tree Shaking). 하지만 몇 가지 주의할 점이 있습니다.

DART
// Tree Shaking이 잘 동작하려면:

// 1. 사용하지 않는 import 제거
import 'package:huge_package/huge_package.dart'; // 전체 import 지양
import 'package:huge_package/only_needed.dart';  // 필요한 것만 import

// 2. Material과 Cupertino 중 하나만 사용
// 둘 다 import하면 두 프레임워크 모두 포함됨
import 'package:flutter/material.dart';
// import 'package:flutter/cupertino.dart';  // 불필요하면 제거

// 3. 사용하지 않는 패키지 정리
// pubspec.yaml에서 사용하지 않는 의존성 제거

에셋 최적화

이미지 압축

BASH
# 이미지 크기 확인
find assets -name "*.png" -exec ls -la {} \;

# WebP 형식으로 변환 (PNG/JPEG보다 30-50% 작음)
# Flutter는 WebP를 지원합니다
DART
// WebP 이미지 사용
Image.asset('assets/images/photo.webp')

불필요한 에셋 제거

YAML
# pubspec.yaml — 폴더 전체 대신 필요한 파일만 등록
flutter:
  assets:
    - assets/images/logo.webp      # 필요한 파일만
    - assets/images/background.webp
    # - assets/images/            # 폴더 전체는 불필요한 파일 포함 가능

폰트 최적화

YAML
flutter:
  fonts:
    - family: Pretendard
      fonts:
        - asset: assets/fonts/Pretendard-Regular.otf
          weight: 400
        - asset: assets/fonts/Pretendard-Bold.otf
          weight: 700
        # 사용하지 않는 두께는 포함하지 않기

Android 앱 번들 (AAB)

APK 대신 AAB로 빌드하면 Google Play가 디바이스에 맞는 리소스만 포함시킵니다.

BASH
# AAB 빌드 (권장)
flutter build appbundle

# 크기 비교
# APK: 모든 ABI(arm64, arm, x86) 포함 → 크기 큼
# AAB: 디바이스에 맞는 ABI만 배포 → 30-50% 작음

ABI별 APK 분리

BASH
# ABI별로 분리된 APK 생성
flutter build apk --split-per-abi

# 결과:
# app-armeabi-v7a-release.apk  (32bit ARM)
# app-arm64-v8a-release.apk    (64bit ARM)
# app-x86_64-release.apk       (x86)

Deferred Components (지연 로딩)

앱의 일부 기능을 나중에 다운로드하는 방식입니다. Android의 Dynamic Feature Module을 활용합니다.

DART
// 지연 로드할 라이브러리
import 'package:my_app/heavy_feature.dart' deferred as heavy;

// 필요할 때 로드
Future<void> _loadHeavyFeature() async {
  await heavy.loadLibrary();
  // 로드 후 사용
  heavy.showHeavyScreen();
}

// UI에서 사용
ElevatedButton(
  onPressed: () async {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (_) => const Center(child: CircularProgressIndicator()),
    );

    await _loadHeavyFeature();
    Navigator.pop(context);

    Navigator.push(
      context,
      MaterialPageRoute(builder: (_) => heavy.HeavyScreen()),
    );
  },
  child: const Text('고급 기능'),
)

프로가드 (Android 코드 축소)

GROOVY
// android/app/build.gradle
android {
    buildTypes {
        release {
            minifyEnabled true    // 코드 축소
            shrinkResources true  // 리소스 축소
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                          'proguard-rules.pro'
        }
    }
}

크기 최적화 체크리스트

항목효과
AAB 빌드 사용30-50% 감소
이미지를 WebP로 변환30-50% 감소 (이미지)
불필요한 패키지 제거가변적
폰트 서브셋 사용폰트 크기 감소
--split-per-abiABI별 분리
사용하지 않는 에셋 제거가변적
Deferred Components초기 크기 감소
ProGuard 활성화네이티브 코드 축소

앱 크기 기준

크기평가
~10MB매우 작음
10-30MB일반적
30-50MB크지만 허용 범위
50MB+최적화 필요

면접 포인트: Flutter 앱의 기본 크기(최소 약 5-6MB)는 Dart VM과 Flutter 엔진이 포함되기 때문입니다. 네이티브 앱보다 기본 크기가 크지만, AAB와 에셋 최적화로 충분히 관리할 수 있습니다.


정리

  • flutter build apk --analyze-size로 앱 크기를 분석하세요
  • AAB(App Bundle) 빌드는 디바이스 맞춤 리소스만 배포합니다
  • 이미지는 WebP로 변환하고, 불필요한 에셋과 패키지를 정리하세요
  • Tree Shaking이 잘 동작하도록 필요한 것만 import하세요
  • --split-per-abi로 ABI별 APK를 분리하면 크기가 크게 줄어듭니다
  • Deferred Components로 무거운 기능을 필요 시에만 다운로드할 수 있습니다
댓글 로딩 중...