Flutter 튜토리얼 79편: 빌드 모드(Debug/Profile/Release)

요약#

핵심 요지#

  • Flutter는 Debug, Profile, Release 세 가지 빌드 모드를 제공합니다.
  • Debug 모드는 개발 중 Hot Reload와 디버깅을 위해 사용합니다.
  • Profile 모드는 성능 분석을 위해 사용합니다.
  • Release 모드는 앱 배포 시 최적화된 빌드를 생성합니다.

문서가 설명하는 범위#

Flutter 공식 문서의 Flutter’s build modes를 기반으로 각 빌드 모드의 특징, 사용 시점, 명령어를 설명합니다.

참고 자료#

문제 상황#

Flutter 앱을 개발하다 보면 여러 상황을 마주하게 됩니다.

  • 개발 중에는 코드를 수정하고 즉시 결과를 확인하고 싶습니다.
  • 앱이 느리게 동작할 때 어디서 병목이 발생하는지 파악해야 합니다.
  • 스토어에 출시할 때는 가장 최적화된 버전이 필요합니다.

각 상황에 맞는 빌드 모드를 선택해야 합니다.

해결 방법#

챕터 1: 빌드 모드 개요#

Why: 왜 빌드 모드가 필요한가요?#

개발, 테스트, 배포는 각각 다른 요구사항을 가집니다. 개발 중에는 빠른 반복 작업이 중요하고, 배포 시에는 성능과 보안이 중요합니다.

What: 세 가지 빌드 모드#

Flutter는 개발 단계에 따라 세 가지 모드를 제공합니다.

모드용도특징
Debug개발Hot Reload, 디버깅 도구
Profile성능 분석성능 측정, 일부 디버깅
Release배포최적화, 최소 용량

How: 빌드 모드 선택하기#

Terminal window
# Debug 모드 (기본값)
flutter run
# Profile 모드
flutter run --profile
# Release 모드
flutter run --release

빌드 명령어도 모드를 지정할 수 있습니다.

Terminal window
# Release APK 빌드
flutter build apk --release
# Release iOS 빌드
flutter build ios --release

Watch out: 주의할 점#

  • 에뮬레이터/시뮬레이터에서는 Debug 모드만 실행됩니다.
  • Profile과 Release 모드는 실제 기기에서만 테스트하세요.
  • Debug 모드의 성능으로 앱 성능을 판단하지 마세요.

챕터 2: Debug 모드#

Why: 왜 Debug 모드를 사용하나요?#

Debug 모드는 개발 생산성을 극대화합니다. 코드 수정 후 즉시 결과를 확인하고, 문제가 생기면 바로 디버깅할 수 있습니다.

What: Debug 모드의 특징#

활성화되는 기능

  • Hot Reload: 코드 변경 즉시 반영
  • Assertions1: assert() 문 실행
  • 서비스 확장: DevTools 연결 가능
  • 소스 레벨 디버깅: 브레이크포인트, 스텝 실행

비활성화되는 최적화

  • 코드 최적화 없음 (빌드 속도 우선)
  • Tree Shaking2 없음
  • 코드 압축(minification) 없음

How: Debug 모드 사용하기#

IDE에서 실행

Android Studio에서는 Run > Debug... 메뉴를 선택하거나, 벌레 아이콘이 있는 실행 버튼을 클릭합니다.

VS Code에서는 F5 키를 누르거나 Run > Start Debugging을 선택합니다.

명령줄에서 실행

Terminal window
flutter run

디버깅 활용

void processData(List<int> data) {
// Debug 모드에서만 실행되는 검증
assert(data.isNotEmpty, 'Data must not be empty');
// assert가 false면 AssertionError 발생
assert(data.length <= 1000, 'Too many items: ${data.length}');
// 실제 로직
for (var item in data) {
process(item);
}
}

빌드 모드 확인

import 'package:flutter/foundation.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Debug 모드에서만 배너 표시
debugShowCheckedModeBanner: kDebugMode,
home: Scaffold(
body: Center(
child: Text(
kDebugMode ? 'Debug Build' : 'Release Build',
),
),
),
);
}
}

Watch out: 주의할 점#

  • Debug 모드는 성능이 느립니다. 실제 성능 테스트는 Profile/Release 모드에서 하세요.
  • print() 문은 Debug 모드에서만 사용하고, Release 빌드 전에 제거하세요.
  • 에뮬레이터에서는 실제 기기보다 느릴 수 있습니다.

챕터 3: Release 모드#

Why: 왜 Release 모드를 사용하나요?#

Release 모드는 사용자에게 배포할 최적화된 앱을 생성합니다. 가장 빠른 실행 속도와 가장 작은 파일 크기를 달성합니다.

What: Release 모드의 특징#

활성화되는 최적화

  • AOT(Ahead-of-Time) 컴파일3: 미리 기계어로 변환
  • Tree Shaking: 사용하지 않는 코드 제거
  • 코드 압축: 변수명, 함수명 축소
  • 디버그 정보 제거

비활성화되는 기능

  • Hot Reload/Hot Restart
  • Assertions
  • 디버깅 도구 연결
  • 서비스 확장

How: Release 모드 사용하기#

앱 실행

Terminal window
# 실제 기기에서 Release 모드로 실행
flutter run --release

빌드 생성

Terminal window
# Android APK
flutter build apk --release
# Android App Bundle (권장)
flutter build appbundle --release
# iOS
flutter build ios --release
# Web
flutter build web --release

Release 전용 코드 분기

import 'package:flutter/foundation.dart';
class AppConfig {
static String get apiBaseUrl {
if (kReleaseMode) {
return 'https://api.production.example.com';
} else {
return 'https://api.dev.example.com';
}
}
static void log(String message) {
// Release 모드에서는 로깅하지 않음
if (!kReleaseMode) {
print(message);
}
}
}

조건부 import

// 환경별 설정 파일
import 'config_dev.dart' if (dart.library.html) 'config_web.dart';

Watch out: 주의할 점#

  • Release 빌드는 에뮬레이터에서 실행되지 않습니다.
  • print() 문이 남아있으면 앱 크기와 성능에 영향을 줍니다.
  • 난독화(obfuscation)를 추가하면 보안이 강화됩니다.
Terminal window
# 난독화 적용 빌드
flutter build apk --obfuscate --split-debug-info=./debug-info

챕터 4: Profile 모드#

Why: 왜 Profile 모드를 사용하나요?#

Profile 모드는 Release에 가까운 성능을 유지하면서 성능 분석 도구를 사용할 수 있습니다. 실제 사용자 환경과 비슷한 조건에서 병목 지점을 찾을 수 있습니다.

What: Profile 모드의 특징#

Release와 동일한 점

  • AOT 컴파일
  • 대부분의 최적화 적용

추가로 활성화되는 기능

  • 성능 오버레이
  • 트레이싱
  • DevTools 연결
  • 타임라인 이벤트 수집

How: Profile 모드 사용하기#

앱 실행

Terminal window
flutter run --profile

성능 오버레이 활성화

MaterialApp(
showPerformanceOverlay: true, // 성능 오버레이 표시
home: MyHomePage(),
)

DevTools로 분석

Terminal window
# 앱 실행 후 DevTools 열기
flutter run --profile
# 다른 터미널에서
dart devtools

DevTools에서 확인할 수 있는 정보는 다음과 같습니다.

  • Timeline: 프레임별 렌더링 시간
  • CPU Profiler: 함수별 실행 시간
  • Memory: 메모리 사용량 및 누수
  • Network: 네트워크 요청 분석

성능 측정 코드

import 'dart:developer' as developer;
void expensiveOperation() {
// 타임라인에 이벤트 기록
developer.Timeline.startSync('ExpensiveOperation');
// 무거운 작업 수행
for (var i = 0; i < 1000000; i++) {
// computation
}
developer.Timeline.finishSync();
}

Watch out: 주의할 점#

  • Profile 모드도 에뮬레이터에서는 실행되지 않습니다.
  • 웹 앱은 Profile 모드에서 DevTools 연결이 제한됩니다. Chrome DevTools를 사용하세요.
  • Profile 모드의 성능이 Release와 약간 다를 수 있습니다.

챕터 5: 플랫폼별 빌드 옵션#

Why: 왜 플랫폼별로 다른 설정이 필요한가요?#

각 플랫폼(iOS, Android, Web)은 고유한 빌드 시스템과 요구사항을 가집니다. 최적의 결과물을 얻으려면 플랫폼별 옵션을 이해해야 합니다.

What: 플랫폼별 특성#

Android

Terminal window
# APK 빌드 (직접 설치용)
flutter build apk --release
# App Bundle 빌드 (Play Store용)
flutter build appbundle --release
# 아키텍처별 분리 빌드
flutter build apk --split-per-abi

iOS

Terminal window
# iOS 앱 빌드
flutter build ios --release
# IPA 생성 (배포용)
flutter build ipa --release

Web

Terminal window
# 웹 앱 빌드
flutter build web --release
# 렌더러 지정
flutter build web --web-renderer canvaskit # 고품질
flutter build web --web-renderer html # 작은 용량

How: 빌드 옵션 활용하기#

build.gradle 설정 (Android)

android {
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
profile {
initWith debug
matchingFallbacks = ['debug', 'release']
}
}
}

환경 변수 사용

Terminal window
# 환경 변수로 빌드 설정
flutter run --dart-define=API_KEY=your_api_key
flutter build apk --dart-define=FLAVOR=production
// 코드에서 환경 변수 사용
const apiKey = String.fromEnvironment('API_KEY');
const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'development');

Flavor 설정

여러 버전(개발, 스테이징, 프로덕션)을 관리할 때 유용합니다.

Terminal window
# Flavor로 빌드
flutter run --flavor development
flutter run --flavor production
flutter build apk --flavor production --release

Watch out: 주의할 점#

  • App Bundle(.aab)은 Play Store 업로드 전용입니다. 직접 설치하려면 APK를 사용하세요.
  • iOS 빌드는 macOS에서만 가능합니다.
  • 웹의 CanvasKit 렌더러는 초기 로딩이 느리지만 그래픽 품질이 좋습니다.

챕터 6: 코드에서 빌드 모드 확인#

Why: 왜 코드에서 빌드 모드를 확인하나요?#

빌드 모드에 따라 다른 동작이 필요할 때가 있습니다. 개발 중에만 보여줄 디버그 정보나, 프로덕션에서만 활성화할 기능 등을 제어할 수 있습니다.

What: 빌드 모드 상수#

Flutter는 package:flutter/foundation.dart에서 상수를 제공합니다.

import 'package:flutter/foundation.dart';
// bool 값
kDebugMode // Debug 모드인지
kProfileMode // Profile 모드인지
kReleaseMode // Release 모드인지

How: 실전 활용 패턴#

로깅 제어

class Logger {
static void debug(String message) {
if (kDebugMode) {
print('[DEBUG] $message');
}
}
static void error(String message, [Object? error]) {
if (kDebugMode) {
print('[ERROR] $message');
if (error != null) print(error);
}
// Release에서는 에러 리포팅 서비스로 전송
if (kReleaseMode) {
// Crashlytics, Sentry 등에 전송
}
}
}

환경별 설정

class Environment {
static const bool isProduction = kReleaseMode;
static String get apiUrl {
if (kReleaseMode) {
return 'https://api.myapp.com';
} else if (kProfileMode) {
return 'https://staging-api.myapp.com';
} else {
return 'http://localhost:3000';
}
}
static Duration get cacheTimeout {
// Debug에서는 캐시 짧게
return kDebugMode
? const Duration(seconds: 10)
: const Duration(hours: 1);
}
}

디버그 전용 UI

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, // 기본 배너 숨김
home: Stack(
children: [
const MainScreen(),
// Debug에서만 표시되는 정보
if (kDebugMode)
const Positioned(
top: 50,
right: 10,
child: DebugInfoPanel(),
),
],
),
);
}
}
class DebugInfoPanel extends StatelessWidget {
const DebugInfoPanel({super.key});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(8),
color: Colors.black54,
child: const Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('Debug Build', style: TextStyle(color: Colors.red)),
Text('v1.0.0+1', style: TextStyle(color: Colors.white)),
],
),
);
}
}

Watch out: 주의할 점#

  • kDebugMode, kReleaseMode는 컴파일 타임 상수입니다.
  • 조건문 안의 코드는 해당 모드가 아니면 컴파일에서 제외됩니다.
  • assert() 안의 코드는 Release에서 완전히 제거됩니다.

한계#

  • 이 문서는 기본적인 빌드 모드를 설명합니다. 고급 CI/CD 설정은 다루지 않습니다.
  • Flavor 구성의 상세한 설정(iOS Scheme, Android productFlavors)은 별도 학습이 필요합니다.
  • 난독화와 코드 서명에 대한 자세한 내용은 배포 가이드를 참조하세요.

Footnotes#

  1. Assertions는 개발 중 조건을 검증하는 문입니다. assert(condition, 'message')로 작성하며, 조건이 false면 에러가 발생합니다. Release 모드에서는 완전히 제거됩니다.

  2. Tree Shaking은 사용하지 않는 코드를 빌드에서 제거하는 최적화 기법입니다. 앱에서 호출되지 않는 함수나 클래스를 자동으로 제외하여 최종 바이너리 크기를 줄입니다.

  3. AOT(Ahead-of-Time) 컴파일은 실행 전에 미리 기계어로 변환하는 방식입니다. JIT(Just-in-Time)보다 시작 시간이 빠르고 성능이 일관됩니다. Release 빌드에서 사용됩니다.

공유

이 글이 도움이 되었다면 다른 사람과 공유해주세요!

Flutter 튜토리얼 79편: 빌드 모드(Debug/Profile/Release)
https://moodturnpost.net/posts/flutter/flutter-build-modes/
작성자
Moodturn
게시일
2026-01-08
Moodturn

목차