Flutter Init Skill
λλ©μΈ κΈ°λ° Flutter νλ‘μ νΈλ₯Ό μμ±νκ³ νλμ μΈ μν€ν
μ²λ‘ μλ μ€μ ν©λλ€.
Todo, Habit, Note, Expense λλ Custom λλ©μΈμ μ ννμ¬ Clean Architecture κΈ°λ°μ μμ ν CRUD μ±μ μ¦μ μμ±ν μ μμ΅λλ€.
Quick Start
μ€ν¬ μ€ν μ λ€μ μ 보λ₯Ό μ
λ ₯λ°μ΅λλ€:
- ν΄λλͺ
(μ: my_habit_app)
- νλ‘μ νΈλͺ
/ν¨ν€μ§λͺ
(μ: habit_app)
- λλ©μΈ μ ν (Todo/Habit/Note/Expense/Custom)
- μ€ν ν리μ
(Minimal/Essential/Full Stack/Custom)
κ·Έ ν μλμΌλ‘ λ€μ λ¨κ³κ° μ€νλ©λλ€:
# 1. νλ‘μ νΈ μμ± (Android/Kotlin, iOS/Swift)
flutter create --platforms android,ios --android-language kotlin --org com.example [ν΄λλͺ
]
# 2. ν¨ν€μ§ μ€μΉ
flutter pub get
# 3. λλ©μΈλ³ Clean Architecture μ½λ μλ μμ±
# - domain/entities/[domain].dart (Freezed μν°ν°)
# - data/datasources/local/app_database.dart (Drift ν
μ΄λΈ)
# - data/repositories/[domain]_repository_impl.dart (Repository ꡬν)
# - presentation/providers/[domain]_providers.dart (Riverpod 3.0)
# - presentation/screens/* (List/Detail/Form νλ©΄)
# 4. μ½λ μμ± (Freezed, Drift, JSON Serializable)
dart run build_runner build --delete-conflicting-outputs
# 5. μ½λ κ²μ¦ λ° μ€λ₯ μλ μμ (νμ)
flutter analyze
# 6. μ± μ€ν
flutter run
Task Instructions
IMPORTANT: μ΄ μ€ν¬μ λννμΌλ‘ μ§νλ©λλ€.
Step 1: λλ©μΈ λ° νλ‘μ νΈ μ€μ μ§λ¬Έ
λ¨Όμ μ¬μ©μμκ² μ΄λ κ² λ¬Όμ΄λ³΄μΈμ:
"Flutter μ±μ μμ±ν©λλ€. λ€μ μ 보λ₯Ό μλ €μ£ΌμΈμ:
1. λλ©μΈ(μν°ν°) μ ν
μ΄λ€ λλ©μΈμ μ±μ λ§λμκ² μ΅λκΉ?
A) Todo (ν μΌ κ΄λ¦¬)
- νλ: title, description, isCompleted, createdAt, completedAt
- κΈ°λ₯: CRUD, νν°λ§(μ 체/μ§νμ€/μλ£), 체ν¬λ°μ€ ν κΈ
B) Habit (μ΅κ΄ νΈλ컀)
- νλ: name, description, frequency(daily/weekly/monthly), streak, lastCompletedAt, goal, isActive
- κΈ°λ₯: CRUD, μ°μ κΈ°λ‘ μΆμ , λͺ©ν λ¬μ±λ₯ , μλ£ μ²΄ν¬
C) Note (λ©λͺ¨)
- νλ: title, content, tags, isPinned, createdAt, updatedAt
- κΈ°λ₯: CRUD, νκ·Έ νν°λ§, κ³ μ λ©λͺ¨, κ²μ
D) Expense (μ§μΆ κ΄λ¦¬)
- νλ: amount, category, description, date, paymentMethod
- κΈ°λ₯: CRUD, μΉ΄ν
κ³ λ¦¬λ³ μ§κ³, μλ³ ν΅κ³, νν°λ§
E) Custom (μ§μ μ μ)
- μν°ν°λͺ
κ³Ό νλλ₯Ό μ§μ μ
λ ₯
2. νλ‘μ νΈ μ 보
- ν΄λλͺ
: νλ‘μ νΈλ₯Ό μμ±ν ν΄λ μ΄λ¦ (κΈ°λ³Έκ°: [λλ©μΈ]_app, μ: habit_app)
- μ΄ ν΄λμ Flutter νλ‘μ νΈκ° μμ±λ©λλ€
- νλ‘μ νΈλͺ
(ν¨ν€μ§λͺ
): Flutter ν¨ν€μ§ μ΄λ¦ (κΈ°λ³Έκ°: ν΄λλͺ
κ³Ό λμΌ)
- pubspec.yamlμ name νλμ μ¬μ©λ©λλ€
- import λ¬Έμ μ¬μ©λ©λλ€ (μ: package:habit_app/...)
- μ‘°μ§λͺ
: (κΈ°λ³Έκ°: com.example)
- Android/iOS ν¨ν€μ§ μλ³μμ μ¬μ©λ©λλ€ (μ: com.example.habit_app)
3. μ€ν ν리μ
μ ν
λ€μ μ€ νλλ₯Ό μ νν΄μ£ΌμΈμ:
A) Essential (κΆμ₯)
- β
GoRouter (νμ
μμ ν λΌμ°ν
)
- β
SharedPreferences (λ‘컬 μ€μ μ μ₯)
- β
FPDart (ν¨μν μλ¬ νΈλ€λ§)
- β
Google Fonts
- β
FluentUI Icons
- β Auth μμ€ν
μ μΈ
- β Responsive Utils μ μΈ
B) Minimal (κ°μ₯ λ¨μ)
- β GoRouter (κΈ°λ³Έ Navigator μ¬μ©)
- β
SharedPreferences
- β FPDart μ μΈ
- β Google Fonts μ μΈ
- β
κΈ°λ³Έ FluentUI Icons
- β Auth μμ€ν
μ μΈ
- β Responsive Utils μ μΈ
C) Full Stack (λͺ¨λ κΈ°λ₯)
- β
GoRouter
- β
SharedPreferences
- β
FPDart (ν¨μν μλ¬ νΈλ€λ§)
- β
Google Fonts
- β
Responsive Utils
- β
FluentUI Icons
- β
Auth μμ€ν
(Login/Register) - μ ν λλ©μΈμ λ°λΌ
D) Custom (μ§μ μ ν)
- κ° κΈ°λ₯μ κ°λ³μ μΌλ‘ μ ν
μ΄λ€ λλ©μΈκ³Ό ν리μ
μ μ ννμκ² μ΅λκΉ? (λλ©μΈ: A/B/C/D/E, ν리μ
: A/B/C/D)"
Step 2: Custom μ ν μ μΆκ° μ§λ¬Έ
2-1. Custom λλ©μΈ (E) μ ν μ:
- μν°ν°λͺ
: μν°ν° μ΄λ¦μ μ
λ ₯νμΈμ (μ: Task, Event, Book)
- νλ μ μ: κ° νλλ₯Ό μ
λ ₯νμΈμ (νμ: νλλͺ
:νμ
, μ: title:String, amount:double, isActive:bool)
- μ§μ νμ
: String, int, double, bool, DateTime
- createdAt, updatedAtμ μλ μΆκ°λ¨
- μ£Όμ κΈ°λ₯: νν°λ§/μ λ ¬ κΈ°μ€μ΄ λ νλλ₯Ό μ ννμΈμ
2-2. Custom μ€ν ν리μ
(D) μ ν μ:
λ€μ μ§λ¬Έλ€μ μμ°¨μ μΌλ‘ νμΈμ:
- λ€λΉκ²μ΄μ
: GoRouterλ₯Ό μ¬μ©νμκ² μ΅λκΉ? (μ/μλμ€)
- μλ¬ νΈλ€λ§: FPDartλ₯Ό μ¬μ©νμκ² μ΅λκΉ? (μ/μλμ€)
- UI: Google Fontsλ₯Ό μ¬μ©νμκ² μ΅λκΉ? (μ/μλμ€)
- λ°μν: Responsive Utilsλ₯Ό ν¬ν¨νμκ² μ΅λκΉ? (μ/μλμ€)
- μΈμ¦ μμ€ν
: Auth μμ€ν
μ ν¬ν¨νμκ² μ΅λκΉ? (μ/μλμ€)
Step 3: μ νλ λλ©μΈκ³Ό μ€νμ λ°λΌ νλ‘μ νΈ μμ±
Flutter νλ‘μ νΈ μμ±:
- μ¬μ©μκ° μ§μ ν ν΄λλͺ
μΌλ‘ νλ‘μ νΈ μμ±
- λͺ
λ Ήμ΄:
flutter create --platforms android,ios --android-language kotlin --org [μ‘°μ§λͺ
] [ν΄λλͺ
]
- μ:
flutter create --platforms android,ios --android-language kotlin --org com.example my_habit_app
- ν΄λλͺ
κ³Ό νλ‘μ νΈλͺ
(ν¨ν€μ§λͺ
)μ΄ λ€λ₯Έ κ²½μ°, μμ± ν pubspec.yamlμ
name νλλ₯Ό μμ
Kotlin DSL νμΈ (μ΅μ Flutterλ μλμΌλ‘ Kotlin DSL μ¬μ©)
μ νλ ν¨ν€μ§ μ€μΉ: pubspec.yaml μ
λ°μ΄νΈ ν flutter pub get
ν΄λ ꡬ쑰 μμ±: Clean Architecture (core, data, domain, presentation)
λλ©μΈλ³ 보μΌλ¬νλ μ΄νΈ μμ±:
A) Todo: title, description, isCompleted, createdAt, completedAt
- Repository: getTodos, createTodo, updateTodo, toggleCompletion, deleteTodo
- Providers: filteredTodosProvider (all/pending/completed)
- UI: TodoListScreen (νν°λ§), TodoDetailScreen, TodoFormDialog
B) Habit: name, description, frequency, streak, lastCompletedAt, goal, isActive
- Repository: getHabits, createHabit, updateHabit, completeHabit, deleteHabit
- Providers: filteredHabitsProvider (active/inactive), habitStatsProvider
- UI: HabitListScreen (ν΅κ³), HabitDetailScreen, HabitFormDialog
C) Note: title, content, tags, isPinned, createdAt, updatedAt
- Repository: getNotes, createNote, updateNote, togglePin, deleteNote
- Providers: filteredNotesProvider (pinned/all/byTag), searchProvider
- UI: NoteListScreen (κ²μ/νκ·Έ), NoteDetailScreen, NoteFormDialog
D) Expense: amount, category, description, date, paymentMethod
- Repository: getExpenses, createExpense, updateExpense, deleteExpense
- Providers: expensesByCategory, monthlyStats, filteredExpenses
- UI: ExpenseListScreen (ν΅κ³), ExpenseDetailScreen, ExpenseFormDialog
E) Custom: μ¬μ©μ μ μ νλ
- Repository: κΈ°λ³Έ CRUD λ©μλ
- Providers: κΈ°λ³Έ list provider
- UI: κΈ°λ³Έ List/Detail/Form νλ©΄
μ€μ νμΌ μμ± (λΌμ°ν
, μ€ν 리μ§, λ€κ΅μ΄ λ±)
Android μ€μ μ
λ°μ΄νΈ (CRITICAL for flutter_local_notifications):
μ½λ μμ±: dart run build_runner build --delete-conflicting-outputs
μ½λ κ²μ¦ λ° μ€λ₯ μμ :
a. flutter analyze μ€ν
b. λ°κ²¬λ μ€λ₯ μμ :
- Freezed 3.0 νΈνμ± (CRITICAL): λͺ¨λ Freezed μν°ν°λ
sealed class μ¬μ©
- β
class User with _$User
- β
sealed class User with _$User
- ν
λ§ μ€μ :
CardTheme β CardThemeData μ¬μ© (deprecated)
- API Client Map νμ
:
Map<String, dynamic> λ°ν μ μμ± μ½λ κ²μ¦
- retrofit_generatorκ° μμ±ν
dynamic.fromJson μλ¬ λ°μ μ μμ νμ
- import κ²½λ‘ μμ : λͺ¨λ μλ κ²½λ‘λ₯Ό
package: νμμΌλ‘ λ³κ²½
- μ:
import '../../domain/entities/todo.dart'; β import 'package:todo_app/domain/entities/todo.dart';
- ν¨ν€μ§ μμ‘΄μ± νμΈ: λλ½λ ν¨ν€μ§ μΆκ° (μ:
shared_preferences)
- Riverpod 3.0 νΈνμ±:
StateNotifier β Notifier, StateProvider β NotifierProvider
- FluentUI μμ΄μ½ μ΄λ¦ νμΈ: μ‘΄μ¬νμ§ μλ μμ΄μ½μ λ체
- νμ
μμ μ±: switch expression μ¬μ©, null safety μ€μ
c. μ¬κ²μ¦: λͺ¨λ error λ 벨 μ€λ₯κ° μμ λκΉμ§ λ°λ³΅
d. λͺ©ν: flutter analyze κ²°κ³Όκ° "0-1 issues found" (info λ λ²¨λ§ νμ©)
β
CRITICAL: μ΄ λ¨κ³λ νμμ
λλ€. λͺ¨λ errorλ₯Ό μ κ±°ν΄μΌ λ€μ λ¨κ³λ‘ μ§νν μ μμ΅λλ€.
Step 4: μ΅μ’
κ²μ¦ λ° μλ΄
β
CRITICAL: μ΄ λ¨κ³λ νλ‘μ νΈ μλ£μ νμ 쑰건μ
λλ€.
μ΅μ’
λΆμ μ€ν:
flutter analyze
μ±κ³΅ κΈ°μ€:
β
μ±κ³΅ μμ:
Analyzing todo_app...
No issues found!
λλ
Analyzing todo_app...
1 issue found. (ran in 2.3s)
info β’ Prefer using lowerCamelCase for constant names β’ lib/core/constants.dart:5:7 β’ constant_identifier_names
β μ€ν¨ μμ (errorκ° μμΌλ©΄ λ°λμ μμ ):
error β’ Target of URI doesn't exist: 'package:...' β’ lib/main.dart:5:8 β’ uri_does_not_exist
error β’ The getter 'xyz' isn't defined for the type 'ABC' β’ lib/presentation/screens/home.dart:42:15
κ²μ¦ κ²°κ³Ό μμ½ (μ±κ³΅ μ):
β
Flutter νλ‘μ νΈ μμ± μλ£!
β
μ½λ μμ± μλ£ (Freezed, Drift, JSON Serializable)
β
Flutter analyze ν΅κ³Ό (0-1 issues found, info λ 벨λ§)
β
λͺ¨λ ν¨ν€μ§ μ€μΉ μλ£
νλ‘μ νΈ μ 보 μ 곡:
- ν΄λλͺ
: [μ¬μ©μ μ
λ ₯κ°] (μ: my_habit_app)
- νλ‘μ νΈλͺ
(ν¨ν€μ§λͺ
): [μ¬μ©μ μ
λ ₯κ°] (μ: habit_app)
- μ‘°μ§λͺ
: [μ¬μ©μ μ
λ ₯κ°] (μ: com.example)
- λλ©μΈ: [μ νλ λλ©μΈ] (Todo/Habit/Note/Expense/Custom)
- μ νλ μ€ν: [ν리μ
λͺ
] (GoRouter, Drift, FPDart λ±)
- μ£Όμ κΈ°λ₯: [λλ©μΈ] CRUD, λ€κ΅μ΄ μ§μ, λ‘컬 μ μ₯μ λ±
- μμ±λ νμΌ: XXκ° Dart νμΌ (core, data, domain, presentation)
μ€ν λ°©λ² μλ΄:
cd [ν΄λλͺ
]
flutter run
λ€μ λ¨κ³ μ μ (μ νμ¬ν, λλ©μΈλ³):
- Todo: νλͺ© μΆκ°/μμ /μμ , νν°λ§(μ 체/μ§νμ€/μλ£), μλ£ ν κΈ
- Habit: μ΅κ΄ κΈ°λ‘, μ°μ κΈ°λ‘ νμΈ, λͺ©ν λ¬μ±λ₯ , ν΅κ³ νμΈ
- Note: λ©λͺ¨ μμ±/νΈμ§, νκ·Έ μΆκ°, κ³ μ λ©λͺ¨, κ²μ
- Expense: μ§μΆ κΈ°λ‘, μΉ΄ν
κ³ λ¦¬λ³ ν΅κ³, μλ³ μ§κ³, νν°λ§
- 곡ν΅: μΈμ΄ μ ν (μμ΄ β νκ΅μ΄), λ€ν¬/λΌμ΄νΈ ν
λ§ μ ν
Core Principles
- Repository ν¨ν΄: λ°μ΄ν° λ μ΄μ΄μ λλ©μΈ λ μ΄μ΄ λΆλ¦¬
- μμ‘΄μ± μ£Όμ
: Riverpod 3.xλ₯Ό ν΅ν μμ‘΄μ± κ΄λ¦¬
- λΆλ³μ±: Freezedλ‘ λΆλ³ λͺ¨λΈ μμ±
- λ€κ΅μ΄ μ§μ: Easy LocalizationμΌλ‘ i18n
- λͺ¨λ UI: FluentUI Icons μ¬μ©
Reference Files
references/setup-guide.md - μμ ν κ°μ΄λ
- κΈ°λ³Έ μ
μ
(λλ©μΈλ³ CRUD, λ€κ΅μ΄, FluentUI Icons)
- μ ν μ΅μ
: GoRouter, Auth, FPDart, Google Fonts, Responsive Utils, ν¨ν€μ§ μ
λ°μ΄νΈ
Notes
- λνν μ€ν¬: μ¬μ©μμκ² λλ©μΈκ³Ό ν리μ
μ νμ ν΅ν΄ λ§μΆ€ν μ± κ΅¬μ±
- λλ©μΈ μ§μ: Todo, Habit, Note, Expense, Custom (μ¬μ©μ μ μ)
- ν리μ
μ 곡: Full Stack, Essential, Minimal, Custom
- μ ν κ°λ₯ κΈ°λ₯: GoRouter, Auth, FPDart, Google Fonts, Responsive Utils
- κΈ°λ³Έ ν¬ν¨: Riverpod 3.x, Easy Localization, FluentUI Icons, Drift, Dio, SharedPreferences
- λ€κ΅μ΄: μμ΄/νκ΅μ΄ (νμ₯ κ°λ₯)
- νλ«νΌ: Android/Kotlin, iOS/Swift (μΉ/μλμ°/리λ
μ€ μ μΈ)
- νμ§ λ³΄μ¦:
- λͺ¨λ νλ‘μ νΈλ
flutter analyze ν΅κ³Ό νμ
- package: imports μ€νμΌ μ€μ
- νμ
μμ μ± λ³΄μ₯
- μ½λ μμ± μλν
- λλ©μΈλ³ μ΅μ νλ UI/UX