위와 같이 기업들은 다양한 이유로 크로스 플랫폼을 선택한다. 이 같이 크로스 플랫폼으로 개발했을 때의 장점은 명확하지만, 무시할 수 없는 단점 또한 가지고 있다.
위 문제와 더불어 기업에서 크로스 플랫폼을 도입하기 어려운 이유는 기존에 잘 만들어진 플랫폼 별 Native 프로젝트가 있기 때문일 것이다. 때문에 이 글에서는 Flutter를 사용하여 조금 더 라이트하게 기존 프로젝트에 크로스 플랫폼을 도입할 수 있는 방법을 설명하려한다.
기존 Android Native 프로젝트에 Flutter를 사용하려면 Flutter Module을 만들어 연결하는 방법이 있다.
먼저 Android Studio에서 New Flutter Project > Flutter > Set Flutter Sdk > Flutter Module을 선택해 모듈을 생성해준다.
생성된 모듈은 aar을 빌드해 사용하는 방법과 소스 코드를 그대로 사용하는 방법이 있다. 이번 글에서는 aar을 빌드해 사용하는 방법을 소개하겠다.
aar을 빌드하기 위해서는 Flutter 모듈 위치에서 terminal을 실행해 다음을 실행한다.
cd some/path/flutter_module
flutter build aar
이후 Android 프로젝트의 settings.gradle 파일을 다음과 같이 수정한다.
dependencyResolutionManagement {
// 이 모드가 설정되면 프로젝트에서 직접 또는 플러그인을 통해 직접 선언된 모든 저장소가 무시된다.
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
google()
mavenCentral()
maven {
// 적용할 Flutter 모듈의 repo 위치를 등록한다.
url = uri("android_with_flutter_module/build/host/outputs/repo")
}
maven {
url = uri("https://storage.googleapis.com/download.flutter.io")
}
}
}
또한 Android 프로젝트의 app/build.gradle 파일에 다음 코드를 추가한다.
dependencies {
// libs.flutter.* 는 gradle/libs.versions.toml 파일에 기록되어있다.
debugImplementation(libs.flutter.debug)
releaseImplementation(libs.flutter.release)
}
추가로 profile 환경 분리가 필요하다면 아래 코드를 추가한다.
android {
buildTypes {
release {
...
}
debug {
...
}
create("profile") {
initWith(getByName("debug"))
}
}
dependencies {
// ...
add("profileImplementation", "com.example.flutter_module:flutter_profile:1.0")
}
AndroidManifest.xml 파일을 열어 application 태그에 아래 코드를 추가한다.
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
/>
이 프로젝트에서는 두가지 방법으로 Flutter 엔진을 사용한다.
1번의 경우 비교적 간단한 코드를 사용해 Flutter engine을 실행한다.
val createFlutterEngineButton: Button = findViewById(R.id.create_flutter_engine_button)
createFlutterEngineButton.setOnClickListener {
startActivity(
FlutterActivity.createDefaultIntent(this)
)
}

이렇게 실행된 페이지는 페이지를 다시 실행할 경우 정보가 초기화된다.
2번의 경우 아래의 코드를 사용해 Flutter engine을 실행한다.
flutterEngine = FlutterEngine(this)
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
FlutterEngineCache.getInstance().put(CACHED_ENGINE, flutterEngine)
val cacheFlutterEngineButton: Button = findViewById(R.id.cache_flutter_engine_button)
cacheFlutterEngineButton.setOnClickListener {
startActivity(
FlutterActivity.withCachedEngine(CACHED_ENGINE).build(this)
)
}

이렇게 실행된 페이지는 페이지를 다시 실행해도 정보를 캐싱하고 있다.
이번 글에서는 간단한 예제를 통해 Flutter Module을 연결하는 법을 사용해보았다. 단순히 모듈을 사용하는 예제라 필요할지 모르겠지만, 확인해보고 싶은 사람들을 위해 프로젝트 링크를 아래에 포함했다.
참고한 문서
https://docs.flutter.dev/add-to-app/android/add-flutter-screen