FRAMEWORK/FLUTTER

Flutter Flavor 완전 정복: 개발/운영 환경 완벽 분리 가이드 (feat. .env, Android & iOS)

나나나나나나나ㅏ나난ㄴ나ㅏ나나 2025. 9. 3. 19:43
728x90

정----말 오랜만에 Flutter로 사이드 프로젝트를 시작했습니다. 한동안 손 놓고 있던 사이에 Flutter 버전은 2.x대에서 3.x대로 훌쩍 업데이트되었고, 그러면서 바뀐 점들도 꽤 있더라고요.

프로젝트를 진행하며 알게 된 몇 가지를 정리해 보려고 합니다. 그 첫 번째 타자가 바로 Flavor! 그럼 시작해 볼까요?

Flavor란?

프로젝트를 진행하거나 출시하다 보면 하나의 소스 코드로 여러 환경에 맞춰 앱을 빌드해야 할 때가 많습니다. 개발, 스테이징, 운영 등등.. 각 환경은 서로 다른 API 주소나 앱 이름, 아이콘을 가져와야 하죠. 만약 이런 설정을 수동으로 변경한다면 개발 서버를 바라봐야 할 앱이 운영 서버를 본다거나 하는 크리티컬한 실수를 피하기 쉽지 않습니다.

Flutter의 Flavor는 이런 문제를 해결하기 위한 공식적인 기능입니다. 다음에 또 허둥댈 저를 위해, 처음부터 끝까지 정리해 보겠습니다!


1단계: 환경별 main 파일 및 설정 파일 생성

가장 먼저 Dart 코드 단에서 각 환경을 구분할 수 있는 파일을 만들어 줍니다.

 

1. 환경별 진입점, main_ 파일 만들기

lib 폴더 안에 각 환경의 시작점이 될 파일을 생성해 줍니다. 이 파일의 역할은 앱이 어떤 Flavor로 실행되어야 하는지 알려주는 것입니다.

 

lib/main_dev.dart

import 'package:flutter/material.dart';
import 'flavors.dart';
import 'main.dart'; // 모든 환경이 공통으로 사용할 앱 시작 로직

void main() {
  F.appFlavor = Flavor.dev; // 앱 시작 전에 'dev' Flavor라고 알려주기
  startApp();
}

 

(똑같이 main_production.dart 파일도 만들고 F.appFlavor = Flavor.production;으로 설정해 줍니다.)

 

 

2. 설정값 관리자, flavors.dart 만들기

환경별로 달라질 앱 제목, API 주소 등의 값을 이곳에서 중앙 관리합니다.

 

lib/flavors.dart

enum Flavor { dev, production }

class F {
  static late final Flavor appFlavor;

  static String get title {
    switch (appFlavor) {
      case Flavor.dev:
        return '내 앱 (개발)';
      case Flavor.production:
        return '내 앱';
    }
  }
  // ... API 주소 등 다른 설정도 여기에 추가!
}

2단계: 민감 정보는 .env로!

API 키처럼 Git에 올리면 절대 안 되는 민감 정보는 .env 파일로 따로 빼서 관리하는 게 안전하겠죠?

 

1. 패키지 설치 및 파일 생성

flutter pub add flutter_dotenv

프로젝트 최상단에 .env 파일을 만들고 키를 넣어줍니다.

 

 

.env

HASURA_ADMIN_SECRET="your_secret_api_key_here"

 

 

2. .gitignore에 .env 파일 추가하기 가장 중요한 단계! .gitignore 파일 맨 아래에 .env*를 추가해서 Git이 이 파일을 추적하지 못하게 막아줍니다.

 

 

3. 공통 main.dart에서 .env 파일 로드하기

모든 Flavor가 공통으로 사용할 startApp() 함수에서 앱이 실행되기 전에 .env 파일을 로드하도록 코드를 추가합니다.

 

lib/main.dar

import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'app.dart'; // MaterialApp 위젯이 있는 파일

Future<void> startApp() async {
  // .env 파일을 찾아 변수를 메모리에 로드합니다.
  await dotenv.load(fileName: ".env");
  
  // 이제 앱을 실행합니다.
  runApp(const MyApp());
}

3단계: 네이티브(Android/iOS) 설정하기

Dart 코드 설정이 끝났다고 방심하면 안 됩니다.

Flutter 앱은 결국 네이티브 앱으로 빌드되기에, Android와 iOS에게도 우리가 만든 Flavor를 알려줘야 합니다.

 

안그럼 그냥 실행 단축키로 실행했을때 오류가 납니다 ㅠ 

실제로 봤던 오류: LateError (LateInitializationError: Field 'appFlavor' has not been initialized.)

 

1. Android 설정 (build.gradle.kts)

android/app/build.gradle.kts 파일을 열고 아래 내용을 추가해 주세요.

android {
    ...
    flavorDimensions += "app"

    productFlors {
        create("dev") {
            dimension = "app"
            // 앱 패키지명에 .dev를 붙여 운영 버전과 같이 설치할 수 있게 함
            applicationIdSuffix = ".dev" 
            // 안드로이드 앱 이름을 변경
            resValue("string", "app_name", "내 앱 (개발)")
        }
        create("production") {
            dimension = "app"
            resValue("string", "app_name", "내 앱")
        }
    }
}

 

 

2. iOS 설정 (Xcode Schemes)

iOS는 Xcode에서 Scheme을 이용해 Flavor를 설정합니다. 조금 복잡하지만 차근차근 따라 해보세요.

  1. Xcode 실행: 터미널에서 open ios/Runner.xcworkspace 명령어로 Xcode를 엽니다.
  2. Configuration 복제: Project 'Runner' > Info > Configurations에서 Debug와 Release를 각각 복제하여 Debug-dev, Release-dev를 만듭니다.
  3. Scheme 복제: 상단 메뉴 Product > Scheme > Manage Schemes...에서 Runner를 복제하여 Runner-dev를 만듭니다.
  4. Scheme과 Configuration 연결: Runner-dev의 Edit Scheme... > Build 탭에서 각 단계의 Configuration을 위에서 만든 Debug-dev, Release-dev로 바꿔줍니다.
  5. 앱 이름, 번들 ID 설정:
    • Build Settings에서 + 버튼을 눌러 User-Defined Setting을 추가하고 APP_NAME과 BUNDLE_ID_SUFFIX 변수를 만듭니다.
    • Debug-dev 환경에 맞춰 APP_NAME은 내 앱 (개발), BUNDLE_ID_SUFFIX는 .dev로 값을 설정합니다.
    • Info.plist 파일을 열어 Bundle display name의 값을 $(APP_NAME)으로, Bundle identifier의 값을 $(PRODUCT_BUNDLE_IDENTIFIER)$(BUNDLE_ID_SUFFIX)로 수정합니다.

 


## 4단계: VS Code에서 편하게 실행하기 (launch.json)

마지막으로, 매번 긴 명령어를 치는 대신 F5 키로 편하게 디버깅하기 위해 VS Code를 설정해 줍니다.

 

.vscode/launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "🚀 DEV",
            "request": "launch",
            "type": "dart",
            "program": "lib/main_dev.dart",
            "args": ["--flavor", "dev"]
        },
        {
            "name": "✅ PRODUCTION",
            "request": "launch",
            "type": "dart",
            "program": "lib/main_production.dart",
            "args": ["--flavor", "production"]
        }
    ]
}

 

 

VS Code의 'Run and Debug' 탭에서 원하는 Flavor를 선택하고 실행하면 끝!


 

이제 하나의 코드로 여러 환경을 테스트 해볼 수 있는 프로젝트가 되었어요! 역시 버전이 업데이트 되면서 이런저런 기능이 추가되네요. 늘 공부해야되는게 힘들기도 하지만 결론적으로 공식적으로 개발자를 편하게 해주려고 하는거니 열심히 따라가야겠어요 앞으로의 나 화이팅

 

728x90