본문 바로가기
프로그래밍/Flutter

[Flutter] Flavor 처리(Old version)

by YuminK 2022. 5. 5.

https://medium.com/@dev.juyoung/flutter-flavor%EB%A5%BC-%ED%86%B5%ED%95%9C-%EB%B9%8C%EB%93%9C-%EB%B3%80%ED%98%95-part-3-ba94fa1b4985

 

아래 내용은 모두 Native에서 직접 Flavor 및 스킴 처리를 하는 방식을 기반으로 합니다. 

 

현재 회사 Meetings 프로젝트에서는 다양한 회사들에 따른 BuildConfig 정보가 분리되어 있고 리소스도 분리가 되어 있는 상태이다. 지금까지 조사한 방식에 대해서 정리한다. 

 

아직 직접 적용하는 과정을 거치지는 않았고 테스트를 위한 사전 조사 과정까지 진행했다.

 

고려사항으로는 ApplicationId(BundleID), BuildConfig, 리소스(이미지) 분리, versionCode와 VersionName이 있다.

1. ApplicationId(BundleId)

flavor간 ApplicationId가 조금씩 차이가 있어 Flutter에서 어떠한 방식으로 적용해야 하는지 알아봤다.

https://docs.flutter.dev/deployment/flavors (공식 홈페이지 참조 문서)

 

https://medium.com/@dev.juyoung/flutter-flavor%EB%A5%BC-%ED%86%B5%ED%95%9C-%EB%B9%8C%EB%93%9C-%EB%B3%80%ED%98%95-part-1-161be6928c50

Android의 경우에는 productFlavors처리를 통해 ApplicationId를 구분한다. IOS의 경우에는 xxconfig라는 Flutter 프로젝트에서 생성되는 파일에 BundleId를 구분하여 연결해주는 과정이 필요한다고 한다. 

 

이때 Android의 flavor이름과 동일시 처리를 해야 한다고 한다. 

(Native 방식대로 처리한다.)

 

2. BuildConfig

위에서 작업한 내용을 바탕으로 Flavor간 BuildConfig를 작성해야 하는데 Dart파일을 기반으로 동작할 수 있도록 싱글톤 클래스를 생성하고 main.dart 파일을 분리하여 원하는 값들을 일괄적으로 저장해놓는 방식으로 사용한다.

 

dart 프로젝트의 define이라는 개념을 사용하여 원하는 string을 전달해줄 수 있다. 이 내용을 이용하여 flavor 정보를 전달하여 각 처리에 맞게 분기 처리를 한다.

 

매번 명령어를 통해 dart 파일을 실행하길 원하지 않는 경우에는 Configurations 속성을 지정하여 원하는 옵션으로 미리 만들어주는 과정이 필요하다.

 

3. 리소스 분기 처리(image)

회사의 Meetings 어플은 Flavor의 이름에 따라 리소스 폴더가 분리되어 있다. Flutter에서 어떤 식으로 리소스 분기 처리를 할 수 있는지 파악하기 위해 Android, IOS플랫폼에서 어떻게 처리가 되는지 간단하게 알아봤다.

 

Android

Android의 경우에는 프로젝트의 src 폴더에 main이라고 폴더가 있는데 각 flavor 이름에 따른 폴더를 만들고 res폴더에 drawable, mipmap 폴더 같은 곳에 이름이 같은 리소스를 넣으면 분기 처리를 할 수 있다.

 

즉, 기존의 main/res 폴더에서 있는 구조와 위치를 동일하게 처리하고 동일한 리소스 이름을 사용하여 처리하면 된다. 

 

main/res/drawable/logo.png가 있다면 flavorName/res/drawble/logo.png 위치에 다른 리소스가 들어있는 형태이다. 

이렇게 하면, Flavor간 다른 리소스 위치를 분리하여 동일한 코드 R.drawable.logo의 이름으로 처리할 수 있다.

 

만약에 각 Flavor에서 사용할 수 있는 리소스 경로가 없는 경우에는 기존 main폴더의 리소스를 사용하는 형태이다.

 

IOS

IOS의 경우에는 체크 박스 형태로 사용하는 리소스를 묶여서 빌드를 진행할 수 있다고 들었다.

 

Flutter

우리가 Flutter project로 개발을 하면서 각 IOS/Android 모듈에서 리소스를 긁어올 것은 아니라 자체적으로 flavor에 따른 리소스 분기 처리 시스템이 있는지 확인했다. (없다)

 

이미지 파일을 flavor별로 구분하여 각 패스에 이미지가 없는 경우에는 기본 이미지를 사용한다.

 

Icon 처리

https://medium.com/@salvatoregiordanoo/flavoring-flutter-392aaa875f36

Android은 기존에 사용하던 리소스 분기 방식을 사용하여 분리할 수 있는 것 같다.

 

https://medium.com/@animeshjain/build-flavors-in-flutter-android-and-ios-with-different-firebase-projects-per-flavor-27c5c5dac10b

IOS에서는 Flutter 프로젝트 xxconfig 파일 가지고 아이콘 처리를 해야 하는 것으로 파악된다.


Create in the ios/Flutter folder a configuration file for every flavor, including the Generated.xcconfig file, setting FLUTTER_TARGET to the main file required by the target and the bundle_suffix.
Remember also to include the generated Pods xcconfig file (as Flutter does in the predefined Debug.xcconfig and Release.xcconfig

Note that you need to have two configurations for each flavor named with Release-[flavorName] and Debug-[flavorName]. Names are really important for flutter matching reasons.

 

리소스 분기처리

찾아본 내용으로는 Flutter 시스템 자체적으로 리소스 관리 시스템을 지원하고 있지 않다. (22.05.05)

 

1. 리소스 모두 넣고 경로로 구분하는 방식 
https://stackoverflow.com/questions/64737643/how-to-use-different-assets-for-flutter-flavor-implementation

=> 리소스 많아지면 답이 없음. 

2. yalm 파일을 분리하여 필요한 리소스를 받아오는 형태
https://github.com/flutter/flutter/issues/21682

1번 방식은 당연히 동작할 거고 yalm파일을 분기처리 하는 방식과 비교를 해봤는데 필요한 리소스만 적재할 수 있다는 점이 가장 큰 장점이다. 다만, 개발 중에 package 하나를 추가하면 다른 yalm파일들에 모두 넣어줘야 한다. 

 

아직 yalm파일에 상속개념이 존재하는지 테스트 해보지 않았고 우리 프로젝트의 이미지 리소스가 유의미할 정도로 많은 것도 아니라 1번의 방식으로 개발을 할 생각이다. yalm파일에서 일부 리소스를 매칭해주지 않았다고 해서 build에서 막히지는 않는다. 코드 실행할 때 exception이 나는 거라 굳이 yalm파일로 처리할 필요성을 느끼지는 못 했다.

 

yalm파일로 리소스를 분기 처리하는 방식으로 진행한다고 하더라도 모든 flavor마다 통째로 리소스 폴더를 분리하는 방식으로 작업하는 것도 별로고 분기 처리가 되는 리소스만 처리를 한다고 하더라도 결국에는 코드단에서 분기 처리를 해야 할 것으로 예상이 되어 이렇게 작업할 필요는 없어 보였다. 굳이 이익을 찾아보자면 한정된 리소스의 Load인데 이 마저도 우리 솔루션에서는 딱히 이득을 볼 수 있는 것이 없다. (리소스가 많지 않음)

 

(선택)

각 Flavor마다 폴더를 분리해서 분기 처리를 하고자 하는 리소스만 만들어 둔다. (안드로이드쪽 폴더 그대로 복사 예정)

이후에 flavor마다 중간 폴더값을 분리해서 처리를 할 것이다.

 

리소스 별 Custom이 필요한 부분에 대해서만 코드 분기 처리를 진행하며 다음과 같이 사용한다. 

Image.asset(
'assets/flavor/image.png',
errorBuilder: (context, exception, stackTrace) {
return Image.asset("assets/images/image.png");})

flavor에 있는 리소스 로드 실패시 기본 이미지 지정하는 코드.

 

4. Version Code, Version Name

마찬가지로 Native Side에서 직접 관리를 하는 방식이다. Android는 flavor처리에서 직접하고... IOS도 따로 하고

댓글