Flutter 프로젝트 시작 전 필수 체크리스트 📋
실무에서 바로 쓰는 Flutter 프로젝트 초기 설정 가이드
더 이상 프로젝트 중간에 “아, 이걸 처음에 설정했어야 했는데…” 하지 마세요!
안녕하세요! 모바일 개발의 새로운 패러다임인 Flutter로 첫 프로젝트를 시작하려고 하시나요?
Android/iOS 네이티브 개발을 해보신 분들이나 웹 프론트엔드에서 모바일로 확장을 고려하고 계신 분들에게 “프로젝트 시작 전에 이것만은 꼭 확인하자!”는 실전 가이드를 준비했습니다.
제가 여러 Flutter 프로젝트를 진행하면서 겪었던 시행착오를 바탕으로, 프로젝트 초기에 놓치기 쉬운 핵심 설정들을 정리해봤습니다. 이 글을 따라하시면 나중에 “아, 처음에 이걸 설정했어야 했는데…”라는 후회를 하지 않으실 거예요! 😊
🎯 왜 초기 설정이 중요할까?
Flutter 프로젝트에서 초기 설정을 제대로 하지 않으면:
- 🔄 중간에 패키지 의존성 충돌로 며칠을 삽질하게 됩니다
- 📱 플랫폼별 설정 누락으로 배포 직전에 당황하게 됩니다
- 🔐 권한 설정 실수로 앱스토어 리젝을 당하게 됩니다
- ⚡ 성능 최적화를 나중에 하려고 하면 리팩토링 지옥에 빠집니다
특히 안드로이드나 iOS에서 넘어오신 분들은 “Flutter는 크로스 플랫폼이니까 설정이 간단하겠지?”라고 생각하시는데, 오히려 두 플랫폼을 모두 고려해야 하기 때문에 더 신경 써야 할 부분이 많습니다.
📋 체크리스트 개요
이 글에서 다룰 핵심 체크 포인트들입니다:
- Android 설정 – Manifest와 Gradle 설정
- iOS 설정 – info.plist와 Xcode 프로젝트 설정
- pubspec.yaml 완벽 설정 – 의존성부터 리소스까지
- 필수 패키지 미리 세팅 – 나중에 후회하지 않을 패키지들
- 권한 및 보안 설정 – 앱스토어 승인을 위한 필수 사항들
각 단계별로 왜 필요한지, 어떻게 설정하는지, 주의사항은 무엇인지 상세히 알아보겠습니다.
1️⃣ Android 설정: 탄탄한 기반 다지기
📱 Android Manifest 설정
Android Manifest는 앱의 신분증 같은 역할을 합니다. android/app/src/main/AndroidManifest.xml 파일에서 핵심 설정들을 확인해봅시다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.your_app">
<!-- 인터넷 권한 (API 통신 필수) -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 카메라 권한 (카메라 기능 사용 시) -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 저장소 권한 (파일 업로드/다운로드 시) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 위치 권한 (지도 기능 사용 시) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:label="Your App Name" <!-- 앱 이름 -->
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher" <!-- 앱 아이콘 -->
android:usesCleartextTraffic="true"> <!-- HTTP 통신 허용 (개발 시에만) -->
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- 딥링크 설정 -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="yourapp.com" />
</intent-filter>
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
</activity>
<!-- Firebase 설정 (푸시 알림 사용 시) -->
<service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
💡 Pro Tip: 권한은 처음부터 다 추가하지 마세요! 필요한 기능이 생길 때마다 추가하는 것이 좋습니다. Google Play Store에서는 불필요한 권한을 요청하는 앱을 좋지 않게 봅니다.
🔧 build.gradle 설정
android/app/build.gradle 파일은 앱의 빌드 설정을 담당합니다.
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
// Firebase 사용 시 추가
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 34 // 최신 SDK 버전 사용
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
applicationId "com.example.your_app" // 고유한 패키지명
minSdkVersion 21 // Android 5.0 이상 지원
targetSdkVersion 34 // 최신 타겟 SDK
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
// MultiDex 활성화 (패키지가 많을 때 필요)
multiDexEnabled true
// 프로가드 설정
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
signingConfigs {
release {
// 릴리즈 빌드를 위한 키스토어 설정
keyAlias localProperties.getProperty('keyAlias')
keyPassword localProperties.getProperty('keyPassword')
storeFile localProperties.getProperty('storeFile') ? file(localProperties.getProperty('storeFile')) : null
storePassword localProperties.getProperty('storePassword')
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true // 코드 난독화 활성화
shrinkResources true // 불필요한 리소스 제거
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".debug" // 디버그 버전 구분
debuggable true
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Firebase 사용 시
implementation platform('com.google.firebase:firebase-bom:32.7.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-crashlytics'
// MultiDex 지원
implementation 'com.android.support:multidex:1.0.3'
}
⚠️ 주의사항:
minSdkVersion은 21 이상으로 설정하세요 (Android 5.0). 더 낮으면 최신 Flutter 기능들을 사용할 수 없습니다.compileSdkVersion과targetSdkVersion은 최신 버전을 사용하세요.- 키스토어 정보는 절대 코드에 하드코딩하지 마세요!
🔑 키스토어 설정 (배포 준비)
배포를 위해서는 앱 서명용 키스토어가 필요합니다.
# 키스토어 생성
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
# android/key.properties 파일 생성
storePassword=your_store_password
keyPassword=your_key_password
keyAlias=upload
storeFile=/Users/your_username/upload-keystore.jks
2️⃣ iOS 설정: 애플 생태계 정복하기
🍎 info.plist 설정
iOS 설정의 핵심인 ios/Runner/Info.plist 파일을 살펴봅시다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- 앱 기본 정보 -->
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Your App Name</string> <!-- 홈 화면에 표시될 앱 이름 -->
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>your_app</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<!-- 최소 iOS 버전 -->
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
<!-- UI 설정 -->
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<!-- 지원 기기 방향 -->
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<!-- 권한 설명 메시지 (필수!) -->
<key>NSCameraUsageDescription</key>
<string>이 앱은 사진 촬영을 위해 카메라에 접근합니다.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>이 앱은 사진 저장을 위해 사진 라이브러리에 접근합니다.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>이 앱은 위치 기반 서비스 제공을 위해 위치 정보를 사용합니다.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>이 앱은 백그라운드에서도 위치 기반 서비스를 제공하기 위해 위치 정보를 사용합니다.</string>
<key>NSMicrophoneUsageDescription</key>
<string>이 앱은 음성 녹음을 위해 마이크에 접근합니다.</string>
<!-- App Transport Security -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/> <!-- 프로덕션에서는 false로 설정 -->
<key>NSExceptionDomains</key>
<dict>
<key>your-api-domain.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
</dict>
</dict>
<!-- Deep Link 설정 -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>your-app-scheme</string>
<key>CFBundleURLSchemes</key>
<array>
<string>yourapp</string>
</array>
</dict>
</array>
<!-- App Tracking Transparency (iOS 14.5+) -->
<key>NSUserTrackingUsageDescription</key>
<string>이 앱은 더 나은 광고 경험을 제공하기 위해 추적 권한을 요청합니다.</string>
</dict>
</plist>
🚨 중요: iOS에서는 권한 사용 이유를 반드시 명시해야 합니다. 애매한 설명은 앱스토어 리뷰에서 리젝당할 수 있습니다!
🔨 Xcode 프로젝트 설정
Xcode에서 직접 설정해야 할 항목들:
- Bundle Identifier: 고유한 식별자 설정
- Deployment Target: 최소 iOS 버전 (12.0 이상 권장)
- Signing & Capabilities: 개발자 계정 연결
- App Transport Security: HTTPS 보안 설정
- Background Modes: 백그라운드 실행 권한
# Xcode에서 프로젝트 열기
open ios/Runner.xcworkspace
💡 Pro Tip: Xcode에서 설정하는 내용들은 자동으로 관련 파일들에 반영됩니다. 가능하면 Xcode GUI를 통해 설정하세요.
3️⃣ pubspec.yaml: Flutter 프로젝트의 심장
📦 기본 설정
pubspec.yaml은 Flutter 프로젝트의 모든 의존성과 설정을 관리하는 핵심 파일입니다.
name: your_app
description: A new Flutter project.
publish_to: 'none' # 패키지로 배포하지 않음
# 버전 정보
version: 1.0.0+1
# 환경 설정
environment:
sdk: '>=3.0.0 <4.0.0'
flutter: ">=3.10.0"
# 의존성
dependencies:
flutter:
sdk: flutter
# UI 컴포넌트
cupertino_icons: ^1.0.6 # iOS 스타일 아이콘
# 상태 관리 (선택: riverpod OR bloc OR provider)
flutter_riverpod: ^2.4.9
# flutter_bloc: ^8.1.3
# provider: ^6.1.1
# 네트워킹
dio: ^5.4.0 # HTTP 클라이언트 (http보다 기능이 풍부)
retrofit: ^4.0.3 # REST API 클라이언트 생성
# 로컬 저장소
shared_preferences: ^2.2.2 # 간단한 키-값 저장
hive: ^2.2.3 # NoSQL 로컬 데이터베이스
hive_flutter: ^1.1.0
# 유틸리티
get_it: ^7.6.7 # 의존성 주입
injectable: ^2.3.2 # 코드 생성 기반 DI
auto_route: ^7.9.2 # 자동 라우팅 생성
# JSON 직렬화
json_annotation: ^4.8.1
freezed_annotation: ^2.4.1
# 환경 변수
flutter_dotenv: ^5.1.0
# 네이티브 기능
permission_handler: ^11.2.0 # 권한 관리
device_info_plus: ^9.1.1 # 디바이스 정보
package_info_plus: ^4.2.0 # 앱 정보
url_launcher: ^6.2.2 # 외부 링크 열기
# 이미지 & 미디어
cached_network_image: ^3.3.0 # 이미지 캐싱
image_picker: ^1.0.5 # 이미지 선택
photo_view: ^0.14.0 # 이미지 확대/축소
video_player: ^2.8.1 # 비디오 재생
# Firebase (필요한 것만 선택)
firebase_core: ^2.24.2
firebase_auth: ^4.15.3
cloud_firestore: ^4.13.6
firebase_storage: ^11.5.6
firebase_messaging: ^14.7.10
firebase_analytics: ^10.7.4
firebase_crashlytics: ^3.4.8
# 소셜 로그인
google_sign_in: ^6.1.6
sign_in_with_apple: ^5.0.0
# flutter_facebook_auth: ^6.0.3
# UI 라이브러리
flutter_svg: ^2.0.9 # SVG 이미지
lottie: ^2.7.0 # Lottie 애니메이션
shimmer: ^3.0.0 # 로딩 효과
flutter_staggered_grid_view: ^0.7.0 # 그리드 뷰
# 유틸리티 위젯
gap: ^3.0.1 # 간격 위젯
flutter_screenutil: ^5.9.0 # 반응형 UI
# 기타
intl: ^0.19.0 # 국제화
equatable: ^2.0.5 # 값 비교 유틸리티
# 개발 의존성
dev_dependencies:
flutter_test:
sdk: flutter
# 린팅
flutter_lints: ^3.0.1
very_good_analysis: ^5.1.0 # 더 엄격한 린트 규칙
# 코드 생성
build_runner: ^2.4.7
freezed: ^2.4.6
json_serializable: ^6.7.1
retrofit_generator: ^8.0.4
injectable_generator: ^2.4.1
auto_route_generator: ^7.3.2
hive_generator: ^2.0.1
# 테스팅
mockito: ^5.4.4
integration_test:
sdk: flutter
# Flutter 설정
flutter:
uses-material-design: true
# 리소스 파일
assets:
- assets/images/
- assets/icons/
- assets/animations/
- .env
- .env.dev
- .env.prod
# 폰트
fonts:
- family: Pretendard
fonts:
- asset: assets/fonts/Pretendard-Regular.ttf
weight: 400
- asset: assets/fonts/Pretendard-Medium.ttf
weight: 500
- asset: assets/fonts/Pretendard-SemiBold.ttf
weight: 600
- asset: assets/fonts/Pretendard-Bold.ttf
weight: 700
🎨 리소스 관리 전략
프로젝트에서 사용할 리소스들을 체계적으로 관리하세요:
assets/
├── images/
│ ├── logos/
│ ├── icons/
│ ├── illustrations/
│ └── backgrounds/
├── animations/
│ └── loading.json
├── fonts/
│ └── Pretendard/
└── configs/
├── .env
├── .env.dev
└── .env.prod
환경 변수 관리 (.env 파일):
# .env.dev
API_BASE_URL=https://dev-api.yourapp.com
GOOGLE_MAPS_API_KEY=your_dev_api_key
FIREBASE_PROJECT_ID=your-dev-project
# .env.prod
API_BASE_URL=https://api.yourapp.com
GOOGLE_MAPS_API_KEY=your_prod_api_key
FIREBASE_PROJECT_ID=your-prod-project
4️⃣ 필수 패키지 미리 세팅: 미래의 나를 위한 투자
🎯 패키지 선택 가이드
프로젝트 유형별로 필요한 패키지들을 정리해봤습니다:
📱 모든 프로젝트 공통 (필수)
# 상태 관리
flutter_riverpod: ^2.4.9 # 또는 bloc, provider 중 선택
# 네트워킹
dio: ^5.4.0
# 로컬 저장소
shared_preferences: ^2.2.2
# 권한 관리
permission_handler: ^11.2.0
# 환경 변수
flutter_dotenv: ^5.1.0
# JSON 처리
json_annotation: ^4.8.1
freezed_annotation: ^2.4.1
🛒 E-커머스/소셜 앱
# 인증
firebase_auth: ^4.15.3
google_sign_in: ^6.1.6
sign_in_with_apple: ^5.0.0
# 이미지 처리
cached_network_image: ^3.3.0
image_picker: ^1.0.5
# 푸시 알림
firebase_messaging: ^14.7.10
# 결제
# in_app_purchase: ^3.1.11
📍 위치 기반 서비스
# 위치
geolocator: ^10.1.0
geocoding: ^2.1.1
# 지도
google_maps_flutter: ^2.5.0
🎵 미디어 앱
# 미디어
video_player: ^2.8.1
audio_players: ^5.2.1
camera: ^0.10.5+5
# 파일 처리
file_picker: ^6.1.1
path_provider: ^2.1.2
📚 패키지 관리 팁
- 버전 호환성 확인:
flutter pub deps명령어로 의존성 트리 확인 - 정기적인 업데이트:
flutter pub upgrade하되 메이저 업데이트는 신중히 - 불필요한 패키지 제거: 사용하지 않는 패키지는 과감히 제거
- 라이선스 확인: 상업적 사용 가능한 라이선스인지 확인
# 패키지 추가
flutter pub add package_name
# 개발 의존성 추가
flutter pub add --dev package_name
# 특정 버전 지정
flutter pub add package_name:^1.0.0
# 의존성 확인
flutter pub deps
# 오래된 패키지 확인
flutter pub outdated
5️⃣ 권한 및 보안 설정: 앱스토어 승인의 지름길
🔐 iOS App Tracking Transparency (iOS 14.5+)
iOS 14.5부터는 사용자 추적을 위한 명시적 권한 요청이 필요합니다:
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:permission_handler/permission_handler.dart';
class AppInitializer {
static Future<void> initialize() async {
WidgetsFlutterBinding.ensureInitialized();
// App Tracking Transparency 권한 요청
if (Platform.isIOS) {
await _requestTrackingPermission();
}
// 알림 권한 요청
await _requestNotificationPermission();
// 기타 초기화 작업...
}
static Future<void> _requestTrackingPermission() async {
final status = await AppTrackingTransparency.trackingAuthorizationStatus;
if (status == TrackingStatus.notDetermined) {
// 커스텀 다이얼로그 표시 (선택사항)
await _showTrackingDialog();
// 시스템 권한 요청
await AppTrackingTransparency.requestTrackingAuthorization();
}
}
static Future<void> _showTrackingDialog() async {
// 사용자에게 추적 권한의 필요성을 설명하는 커스텀 다이얼로그
return showDialog(
context: navigatorKey.currentContext!,
builder: (context) => AlertDialog(
title: Text('개인화된 광고'),
content: Text(
'더 나은 앱 경험을 위해 다른 회사의 앱과 웹사이트에서 회원님의 활동을 추적하도록 허용하시겠습니까?'
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('계속'),
),
],
),
);
}
static Future<void> _requestNotificationPermission() async {
final status = await Permission.notification.status;
if (status.isDenied) {
await Permission.notification.request();
}
}
}
// main.dart
void main() async {
await AppInitializer.initialize();
runApp(MyApp());
}
🛡️ 네트워크 보안 설정
Android Network Security Config
android/app/src/main/res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">your-api-domain.com</domain>
<pin-set expiration="2025-12-31">
<pin digest="SHA-256">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</pin>
<pin digest="SHA-256">BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=</pin>
</pin-set>
</domain-config>
<!-- 개발 환경에서만 허용 -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
</network-security-config>
iOS App Transport Security
개발 단계에서는 임시로 HTTP를 허용하되, 프로덕션에서는 반드시 HTTPS만 사용:
<!-- 개발 시 임시 설정 -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<!-- 프로덕션 권장 설정 -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSExceptionDomains</key>
<dict>
<key>your-api-domain.com</key>
<dict>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
</dict>
</dict>
</dict>
🔑 API 키 보안 관리
절대 API 키를 코드에 하드코딩하지 마세요!
// ❌ 잘못된 방법
const String apiKey = "AIzaSyB123456789";
// ✅ 올바른 방법
class ApiConfig {
static String get googleMapsApiKey {
return dotenv.env['GOOGLE_MAPS_API_KEY'] ?? '';
}
static String get firebaseApiKey {
return dotenv.env['FIREBASE_API_KEY'] ?? '';
}
}
// 환경별 설정 로드
Future<void> loadEnvConfig() async {
const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'dev');
switch (flavor) {
case 'prod':
await dotenv.load(fileName: '.env.prod');
break;
case 'staging':
await dotenv.load(fileName: '.env.staging');
break;
default:
await dotenv.load(fileName: '.env.dev');
}
}
6️⃣ 프로젝트 구조 & 아키텍처 설정
📁 추천 폴더 구조
확장 가능하고 유지보수하기 쉬운 폴더 구조를 설정하세요:
lib/
├── main.dart
├── app/
│ ├── app.dart # 앱 진입점
│ ├── router/ # 라우팅 설정
│ ├── theme/ # 테마 설정
│ └── constants/ # 앱 상수
├── core/
│ ├── error/ # 에러 처리
│ ├── network/ # 네트워크 설정
│ ├── utils/ # 유틸리티 함수
│ └── di/ # 의존성 주입
├── features/
│ ├── auth/
│ │ ├── data/ # 데이터 레이어
│ │ ├── domain/ # 비즈니스 로직
│ │ └── presentation/ # UI 레이어
│ ├── home/
│ └── profile/
├── shared/
│ ├── widgets/ # 공통 위젯
│ ├── models/ # 공통 모델
│ └── services/ # 공통 서비스
└── generated/ # 자동 생성 파일
🏗️ Clean Architecture 기본 설정
// core/di/injection.dart
@InjectableInit()
Future<void> configureDependencies() async => getIt.init();
final getIt = GetIt.instance;
// main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 환경 설정 로드
await loadEnvConfig();
// 의존성 주입 설정
await configureDependencies();
// Hive 초기화
await Hive.initFlutter();
// Firebase 초기화
if (Firebase.apps.isEmpty) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}
runApp(
ProviderScope(
child: MyApp(),
),
);
}
7️⃣ 디버깅 & 개발 도구 설정
🔧 개발 환경 최적화
// core/utils/logger.dart
import 'package:logger/logger.dart';
class AppLogger {
static final _logger = Logger(
printer: PrettyPrinter(
methodCount: 2,
errorMethodCount: 8,
lineLength: 120,
colors: true,
printEmojis: true,
printTime: true,
),
);
static void d(String message) => _logger.d(message);
static void i(String message) => _logger.i(message);
static void w(String message) => _logger.w(message);
static void e(String message, [dynamic error, StackTrace? stackTrace]) {
_logger.e(message, error, stackTrace);
}
}
// Firebase Crashlytics 연동
class CrashReporter {
static Future<void> recordError(
dynamic exception,
StackTrace? stack, {
bool fatal = false,
}) async {
await FirebaseCrashlytics.instance.recordError(
exception,
stack,
fatal: fatal,
);
}
static Future<void> log(String message) async {
await FirebaseCrashlytics.instance.log(message);
}
}
📊 앱 성능 모니터링
// core/services/performance_service.dart
class PerformanceService {
static Future<void> startTrace(String traceName) async {
final trace = FirebasePerformance.instance.newTrace(traceName);
await trace.start();
}
static Future<void> stopTrace(String traceName) async {
final trace = FirebasePerformance.instance.newTrace(traceName);
await trace.stop();
}
static Future<void> recordNetworkRequest(
String url,
String method,
int responseCode,
int responseSize,
) async {
final metric = FirebasePerformance.instance.newHttpMetric(url, HttpMethod.Get);
await metric.start();
metric.responseCode = responseCode;
metric.responsePayloadSize = responseSize;
await metric.stop();
}
}
8️⃣ 배포 준비: 한 번에 성공하는 배포
🚀 배포 전 체크리스트
## Android 배포 체크리스트
- [ ] 키스토어 생성 및 설정 완료
- [ ] 프로가드 규칙 설정
- [ ] 앱 서명 확인
- [ ] 권한 최소화
- [ ] APK/AAB 크기 최적화
- [ ] 64비트 아키텍처 지원 확인
## iOS 배포 체크리스트
- [ ] Apple Developer 계정 등록
- [ ] Bundle ID 등록
- [ ] 인증서 및 프로비저닝 프로파일 생성
- [ ] App Store Connect 앱 등록
- [ ] 권한 사용 이유 명시
- [ ] ATS (App Transport Security) 설정
## 공통 체크리스트
- [ ] 앱 아이콘 설정 (모든 사이즈)
- [ ] 스플래시 스크린 설정
- [ ] 앱 이름 및 설명 다국어 지원
- [ ] 개인정보 보호정책 URL 설정
- [ ] 테스트 디바이스에서 최종 확인
- [ ] 성능 최적화 확인
- [ ] 크래시 없는지 확인
🔧 빌드 최적화 설정
// 릴리즈 빌드 최적화
flutter build apk --release --shrink --obfuscate --split-debug-info=build/debug-info
flutter build ios --release --obfuscate --split-debug-info=build/debug-info
🎉 마무리: 성공적인 Flutter 프로젝트의 시작
축하합니다! 🎊 이제 여러분은 Flutter 프로젝트를 시작하기 전에 확인해야 할 모든 핵심 사항들을 숙지하셨습니다.
📋 최종 점검 요약
- ✅ Android 설정: Manifest, Gradle, 키스토어
- ✅ iOS 설정: info.plist, Xcode 프로젝트, 인증서
- ✅ pubspec.yaml: 의존성, 리소스, 환경 설정
- ✅ 필수 패키지: 프로젝트 유형별 패키지 선택
- ✅ 권한 및 보안: 플랫폼별 권한, API 키 관리
- ✅ 프로젝트 구조: Clean Architecture 기반 폴더 구조
- ✅ 개발 도구: 디버깅, 로깅, 성능 모니터링
- ✅ 배포 준비: 플랫폼별 배포 체크리스트
🚀 다음 단계
이제 본격적인 개발에 집중할 수 있습니다! 다음 글에서는:
- Dart 언어 핵심 개념 마스터하기
- Flutter 위젯 시스템 완전 정복
- 상태 관리 패턴 비교 및 선택 가이드
- 실전 API 연동 및 에러 처리
등의 주제로 더 깊이 있는 내용을 다룰 예정입니다.
💬 커뮤니티와 함께 성장하기
Flutter 개발 여정에서 막히는 부분이 있다면:
혼자서는 어려운 길이지만, 함께라면 더 즐겁고 빠르게 성장할 수 있습니다!
즐거운 Flutter 개발 되세요! 🚀
이 글이 도움이 되셨다면 좋아요 👍와 공유 📤 부탁드립니다!
답글 남기기